日期:2014-05-16  浏览次数:20513 次

dbms_sql的使用

dbms_sql的使用

http://space.itpub.net/13129975/viewspace-624522

通常运用DBMS_SQL包一般分为几步:
1. open cursor: 打开cursor
2. parse cursor:解析你要执行的SQL语句
3. bind variable:如果要执行的SQL语句中包含变量,在此就需要绑定变量
4. execute:执行SQL语句
5. close cursor:在执行后关闭此cursor.
如果你还需要返回执行SQL的结果集,还需要使用define_column,define_array等方法。

下面根据不同情况进行详细展示:
在做展示之前,先准备一些基础数据
create table demo (a number,b number,c number);
begin
? for i in 1 .. 15 loop
??? insert into demo
??? values
????? (round(dbms_random.value, 2) * 100,
?????? round(dbms_random.value, 2) * 100,
?????? round(dbms_random.value, 2) * 100);
? end loop;
? commit;
end;

基础数据完成之后,下面开始对一些具体情况进行分析:
1.执行一般的select语句
?? 首先先介绍最常用情况:
? create or replace procedure define_column(no in number) is
??? cursor_name????? integer := dbms_sql.open_cursor; --在初始化参数时,就可以打开cursor;
??? row_process????? integer;
??? v_b number;
? begin
??? --解析要执行的SQL.
??? dbms_sql.parse(cursor_name,
?????????????????? 'select * from demo where a= :no',
?????????????????? dbms_sql.native);
??? --如果要执行的SQL中不需要参数,则可以省略掉bind_variable--
??? dbms_sql.bind_variable(cursor_name, 'no', no);
??? /*如果需要返回查询语句的结果,则必须在exec之前使用define_column函数定义返回字段;define_column函数的第一个参数是最初定义的cursor name,第二个参数是指需要返回的字段在查询结果中处于第几列,在此例中返回的字段是查询结果中的第二列,即b列;第三个参数就是接收返回结果需要的变量*/
??? dbms_sql.define_column(cursor_name, 2, v_b);
??? --必须定义一个参数接收exec的结果
??? row_process := dbms_sql.execute(cursor_name);
??? loop
????? if dbms_sql.fetch_rows(cursor_name) > 0 then
??????? --将前面定义的字段返回给变量v_b--
??????? dbms_sql.column_value(cursor_name, 2, v_b);
??????? dbms_output.put_line('B is ' || v_b);
????? else
??????? exit;
????? end if;
??? end loop;
??? --数据处理完成后记得要将cursor关闭
??? dbms_sql.close_cursor(cursor_name);
? exception
??? when others then
????? dbms_sql.close_cursor(cursor_name);
? end;

2.使用define_array方法得到查询结果
??? 前面已经分析了如何使用define_column方法得到查询结果,但有时我们想要一次得到多行查询结果,此时我们就需要使用define_array方法,此方法常用于DML操作,稍后会有例子对此介绍,现在先来看一下如果使用define_array.

? create or replace procedure define_array is
??? c????? NUMBER;
??? d????? NUMBER;
??? /*DBMS_SQL.NUMBER_TABLE类型实际就是type NUMBER_TABLE is table of number index by binary_integer;*/
??? n_tab? DBMS_SQL.NUMBER_TABLE;
??? n_tab1 DBMS_SQL.NUMBER_TABLE;
??? indx?? NUMBER := 1;
? BEGIN
??? c := DBMS_SQL.OPEN_CURSOR;
??? DBMS_SQL.PARSE(c,
?????????????????? 'select * from demo where rownum<13 order by 1',
?????????????????? DBMS_SQL.NATIVE);
??? /*在此需要特别介绍一下define_array函数的第一个参数是已经打开的cursor名称, 第二个参数是指需要返回的字段在查询结果中处于第几列,第三个参数就是接收返回结果需要的变量,与define_column不同的是此变量是table,而不是普通的字段类型;第四个参数表示一次可以返回的行数;第五个参数是指n_tab的index从哪个数值开始,此数值是递增的.在此例中index是从1开始的,一次得到9行结果集,则有n_tab(1)到n_tab(9),如果循环再得到新的结果集,则index继续增长n_tab(10)....*/
??? DBMS_SQL.DEFINE_ARRAY(c, 1, n_tab, 9, indx);
??? DBMS_SQL.DEFINE_ARRAY(c, 2, n_tab1, 9, indx);
??? d := DBMS_SQL.EXECUTE(c);
??? loop
????? d := DBMS_SQL.FETCH_ROWS(c);
????? dbms_output.put_line('fetch rows is ' || d);
????? EXIT WHEN d < 9;
????? DBMS_SQL.COLUMN_VALUE(c, 1, n_tab);
????? DBMS_SQL.COLUMN_VALUE(c, 2, n_tab1);
????? for i in 1 .. d loop
??????? dbms_output.put_line(n_tab(i) || ',' || n_tab1(i));
????? end loop;
??? END LOOP;
??? DBMS_SQL.CLOSE_CURSOR(c);
? EXCEPTION
??? WHEN OTHERS THEN
????? IF DBMS_SQL.IS_OPEN(c) THEN
??????? DBMS_SQL.CLOSE_CURSOR(c);
????? END IF;
? END;

3.使用variable_value显示DML后的返回结果(单条记录)
?? 以上我们介绍了如何使用DBMS_SQL包来处理数据查询,如果我们把查询语句更换成DML语句,则可以完成各种DML操作。
? 在PL/SQL中我们可以使用returning方法返回DML操作结果,在DBMS_SQL包中可不可以实现呢?答案当然是可以,用variable_value方法就可以实现。下面就分别用两个例子来展示如何实现,一个是返回单条记录,另一个是返回多条记录。

(1)返回单条记录
? procedure single_insert(c1 in number, c2 in number, r out number) is
?
??? cursor_name number := dbms_sql.open_cursor;
??? n?? number;
? begin
??? dbms_sql.parse(cursor_name,
??????????????????