DBMS_SQL使用

一、简介

DBMS_SQL包提供一个接口,用于执行动态SQL(包括DDL 和DML)。

DBMS_SQL定义了一个实体叫游标ID,游标ID是一个PL/SQL整型数,通过游标ID,可以对游标进行操作。

DBMS_SQL包和本地动态SQL在功能上有许多重叠的地方,但是有的功能只能通过本地动态SQL实现,而有些功能只能通过DBMS_SQL实现。
二、主要函数

DBMS_SQL封装过程中的主要函数:
1、OPEN_CURSOR:返回新游标的ID值
2、PARSE:解析要执行的语句
3、BIND_VARIABLE:将给定的数量与特定的变量相连接
4、DEFINE_COLOUMN:定义字段变量,其值对应于指定游标中某个位置元素的值 (仅用于SELECT语句)
5、EXECUTE:执行指定的游标
6、EXECUTE_AND_FETCH:执行指定的游标并取记录
7、FETCH_ROWS:从指定的游标中取出记录
8、COLUMN_VALUE:返回游标中指定位置的元素
9、IS_OPEN:当指定的游标状态为OPEN时返回真值
10、CLOSE_CURSOR:关闭指定的游标并释放内存
11、LAST_ERROR_POSITION:返回出错SQL语句的字节偏移量
12、LAST_ROW_ID:返回最后一条记录的ROWID
13、LAST_SQL_FUNCTION_CODE:返回语句的SQL FUNCTION CODE

三、一般过程

对于一般的select 操作,如果使用动态的sql语句则需要进行以下几个步骤:
open cursor —>parse—>define column—>excute—>fetch rows—>close cursor;
而对于dml操作(insert , update )则需要进行以下几个步骤:
open cursor —>parse—>bind variable—>execute—>close cursor;
对于delete 操作只需要进行以下几个步骤:
open cursor —>parse—>execute—>close cursor;
对DDL操作需要进行一下几个步骤
open cursor—>parse---->close cursor;

复制代码
利用DBMS_SQL执行DDL语句:
CREATE OR REPLACE PROCEDURE CreateTable2(tablename VARCHAR2)
IS
SQL_string VARCHAR2(1000);–存放SQL语句
V_cur integer;–定义整形变量,用于存放游标
BEGIN
SQL_string := 'CREATE TABLE ’ || tablename || ‘(nameVARCHAR(20))’;
V_cur := dbms_sql.open_cursor;–打开游标
dbms_sql.parse(V_cur,SQL_string,DBMS_SQL.NATIVE);–解析并执行SQL语句
dbms_sql.close_cursor(V_cur);–关闭游标
END;
利用DBMS_SQL执行SELECT语句:
open cursor—>parse—> define column—>excute—> fetch rows—>close cursor;
DECLARE
v_cursor NUMBER;–游标ID
sqlstring VARCHAR2(200);–用于存放SQL语句
v_phone_name VARCHAR2(20);–手机名字
v_producer VARCHAR2(20);–手机生产商
v_price NUMBER :=500;–手机价钱
v_count INT;–在这里无意义,只是存放函数返回值
BEGIN
–:p是占位符
–SELECT 语句中的第1列是phone_name,第2列是producer,第3列是price
sqlstring :=‘SELECTphone_name,producer,price FROM phone_infor WHERE price> :p’;
v_cursor :=dbms_sql.open_cursor;–打开游标;
dbms_sql.parse(v_cursor ,sqlstring,dbms_sql.native);–解析动态SQL语句;

–绑定输入参数,v_price的值传给 :p
dbms_sql.bind_variable(v_cursor,’:p’,v_price);

  --定义列,v_phone_name对应SELECT 语句中的第1列

dbms_sql.define_column(v_cursor,1,v_phone_name,20);
–定义列,v_producer对应SELECT语句中的第2列
dbms_sql.define_column(v_cursor,2,v_producer,20);
–定义列,v_price对应SELECT语句中的第3列
dbms_sql.define_column(v_cursor,3,v_price);

v_count := dbms_sql.EXECUTE(v_cursor);–执行动态SQL语句。

LOOP
–从游标中把数据检索到缓存区(BUFFER)中,缓冲区的值只能被函数COULUMN_VALUE()所读取
EXIT WHENdbms_sql.fetch_rows(v_cursor)<=0;
–函数column_value()把缓冲区的列的值读入相应变量中。
–第1列的值被读入v_phone_name中
dbms_sql.column_value(v_cursor,1,v_phone_name);
–第2列的值被读入v_producer中
dbms_sql.column_value(v_cursor,2,v_producer);
–第2列的值被读入v_price中
dbms_sql.column_value(v_cursor,3,v_price);
–打印变量的值
dbms_output.put_line(v_phone_name || ’ '||v_producer|| ’ '||v_price);

END LOOP;
dbms_sql.close_cursor(v_cursor);–关闭游标
END;
利用DBMS_SQL执行DML语句:
open cursor—>parse—> bind variable—>execute—> close cursor;
DECLARE
v_cursor NUMBER;–游标ID
sqlstring VARCHAR2(200);–用于存放SQL语句
v_phone_name VARCHAR2(20);–手机名字
v_producer VARCHAR2(20);–手机生产商
v_price NUMBER :=500;–手机价钱
v_count INT;–被DML语句影响的行数
BEGIN

sqlstring :=‘INSERT INTO phone_infor values(:a,:b,:c)’;-- :a,:b,:c 是占位符

v_phone_name :=‘S123’;
v_producer :=‘索尼AA’;
v_price := 999;

v_cursor :=dbms_sql.open_cursor;–打开游标;
dbms_sql.parse(v_cursor ,sqlstring,dbms_sql.native);–解析动态SQL语句;

–绑定输入参数,v_price的值传给 :p
dbms_sql.bind_variable(v_cursor,’:a’,v_phone_name);
dbms_sql.bind_variable(v_cursor,’:b’,v_producer);
dbms_sql.bind_variable(v_cursor,’:c’,v_price);

v_count := dbms_sql.EXECUTE(v_cursor);–执行动态SQL语句。

dbms_sql.close_cursor(v_cursor);–关闭游标
dbms_output.put_line(’ INSERT ’ || to_char(v_count) ||’ row ');–打印有多少行被插入
COMMIT;
END;
复制代码
四、demo

示例1

复制代码
–这是一个创建一个表的过程的例子。该过程有两个参数:表名和字段及其类型的列表。
CREATE OR REPLACE PROCEDURE ddlproc (tablename varchar2, cols varchar2) AS
   cursor1 INTEGER;
BEGIN
   cursor1 := dbms_sql.open_cursor;
   dbms_sql.parse(cursor1, ‘CREATE TABLE ’ tablename ’ ( ’ cols ’ )’, dbms_sql.v7);
   dbms_sql.close_cursor(cursor1);
end;
复制代码
示例2

复制代码
–用DBMS_SQL包和游标计算用户下所有表行数
DECLARE
t_c1_tname user_tables.table_name%TYPE;
t_command varchar2(200);
t_cid integer;
t_total_records number(10);
stat integer;
row_count integer;
t_limit integer := 0; --限制只取出记录大于0的表的情况

cursor c1 is select table_name from user_tables order by table_name; --查出所有表的名字
BEGIN
t_limit := 0;
open c1;

loop
fetch c1 into t_c1_tname; --取出一个表名
exit when c1%NOTFOUND; --如果游标记录取完,退出循环
t_command := 'SELECT COUNT(0) FROM '||t_c1_tname; --定义SQL命令
t_cid := DBMS_SQL.OPEN_CURSOR; --创建一个游标
DBMS_SQL.PARSE(t_cid,t_command,dbms_sql.native); --向服务器发出一个语句并检查这个语句的语法和语义错误
DBMS_SQL.DEFINE_COLUMN(t_cid,1,t_total_records); --定义将从FetchRows()函数接收数据的变量的数据类型与大小
stat := DBMS_SQL.EXECUTE(t_cid); --执行此语句,因为执行的是查询,所以必须跟着Fetch_Rows函数并为单个行检索数据
row_count := DBMS_SQL.FETCH_ROWS(t_cid); --取回一行数据放入局部缓冲区
DBMS_SQL.COLUMN_VALUE(t_cid,1,t_total_records); --返回调用FetchRows()取回的一列的值,这一列的值存储在t_total_records中

    if t_total_records > t_limit then  
       DBMS_OUTPUT.PUT_LINE(rpad(t_c1_tname,55,' ')||  
       to_char(t_total_records,'99999999')||' record(s)');  
    end if;  
      
    DBMS_SQL.CLOSE_CURSOR(t_cid);  

end loop;

close c1;
END;
复制代码
具体参考以下三篇:

http://blog.csdn.net/u013516966/article/details/49002769

http://blog.csdn.net/tianping168/article/details/3980134

https://www.cnblogs.com/zeromyth/archive/2009/09/29/1576627.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值