DBMS_SQL包使用

 

通常运用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等方法。

下面根据不同情况进行详细展示:
在做展示之前,先准备一些基础数据

Sql代码   
  1. create table demo (a number,b number,c number);   
  2. begin  
  3.   for i in 1 .. 15 loop   
  4.     insert into demo   
  5.     values  
  6.       (round(dbms_random.value, 2) * 100,   
  7.        round(dbms_random.value, 2) * 100,   
  8.        round(dbms_random.value, 2) * 100);   
  9.   end loop;   
  10.   commit;   
  11. end;  
 

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

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

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

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

(1)返回单条记录
Sql代码   
  1. procedure single_insert(c1 in number, c2 in number, r out number) is  
  2.   
  3.   cursor_name number := dbms_sql.open_cursor;   
  4.   n   number;   
  5. begin  
  6.   dbms_sql.parse(cursor_name,   
  7.                  'insert into demo values (:a,:b) returning :a*:b into :r',   
  8.                  dbms_sql.native);   
  9.   dbms_sql.bind_variable(cursor_name, 'a', c1);   
  10.   dbms_sql.bind_variable(cursor_name, 'b', c2);   
  11.   dbms_sql.bind_variable(cursor_name, 'r', r);   
  12.   n := dbms_sql.execute(cursor_name);   
  13.   --使用variable_value函数得到DML操作returning的结果集   
  14.   dbms_sql.variable_value(cursor_name, 'r', r);   
  15.   dbms_output.put_line(r);   
  16.   dbms_sql.close_cursor(cursor_name);   
  17. exception   
  18.   when others then  
  19.     dbms_sql.close_cursor(cursor_name);   
  20. end;  
 
(2)返回多条记录
结合define_array使用,可以更好的完成DML操作。

Sql代码   
  1. create or replace package DBMS_SQL_DEMO as  
  2.   
  3.   procedure multi_insert;   
  4.     
  5. end;   
  6. /   
  7.   
  8. create or replace package body DBMS_SQL_DEMO as  
  9.   
  10.   procedure multi_insert_priv(c1 in dbms_sql.Number_Table,   
  11.                               c2 in dbms_sql.Number_Table,   
  12.                               r  out dbms_sql.Number_Table) is  
  13.     
  14.     cursor_name number := dbms_sql.open_cursor;   
  15.     n           number;   
  16.   begin  
  17.     dbms_sql.parse(cursor_name,   
  18.                    'insert into demo values (:a,:b) returning :a*:b into :r',   
  19.                    dbms_sql.native);   
  20.     --使用bind_array函数将number_table类型的变量赋值给绑定变量   
  21.     dbms_sql.bind_array(cursor_name, 'a', c1);   
  22.     dbms_sql.bind_array(cursor_name, 'b', c2);   
  23.     dbms_sql.bind_array(cursor_name, 'r', r);   
  24.     n := dbms_sql.execute(cursor_name);   
  25.     --使用variable_value函数将returning的结果集赋值给number_table类型的变量   
  26.     dbms_sql.variable_value(cursor_name, 'r', r);   
  27.     dbms_sql.close_cursor(cursor_name);   
  28.   exception   
  29.     when others then  
  30.       dbms_sql.close_cursor(cursor_name);   
  31.   end;   
  32.   
  33.   procedure multi_insert is  
  34.     c1          dbms_sql.Number_Table;   
  35.     c2          dbms_sql.Number_Table;   
  36.     cursor_name number := dbms_sql.open_cursor;   
  37.     n           number;   
  38.     r           dbms_sql.Number_Table;   
  39.     indx        number := 1;   
  40.     d           number;   
  41.   begin  
  42.     dbms_sql.parse(cursor_name, 'select * from demo', dbms_sql.native);   
  43.     dbms_sql.define_array(cursor_name, 1, c1, 5, indx);   
  44.     dbms_sql.define_array(cursor_name, 2, c2, 5, indx);   
  45.     n := dbms_sql.execute(cursor_name);   
  46.     loop   
  47.       d := dbms_sql.fetch_rows(cursor_name);   
  48.       exit when d = 0;   
  49.       dbms_sql.column_value(cursor_name, 1, c1);   
  50.       dbms_sql.column_value(cursor_name, 2, c2);   
  51.       multi_insert_priv(c1, c2, r);   
  52.       for i in 1 .. r.count loop   
  53.         dbms_output.put_line(r(i));   
  54.       end loop;   
  55.     end loop;   
  56.   exception   
  57.     when others then  
  58.       dbms_sql.close_cursor(cursor_name);   
  59.   end;   
  60.   
  61. end;   
  62. /  
 

你可能感兴趣的:(sql,exception,table,Integer,insert,returning)