• 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

  • 相关阅读:
    6.11 考试修改+总结
    6.10 考试修改+总结+颓废记
    我们都一样
    【HDU 5730】Shell Necklace
    【SPOJ 8093】Sevenk Love Oimaster
    【BZOJ 3238】【AHOI 2013】差异
    【UOJ #131】【NOI 2015】品酒大会
    【SPOJ 220】Relevant Phrases of Annihilation
    【POJ 3177】Redundant Paths
    【POJ 2186】Popular Cows
  • 原文地址:https://www.cnblogs.com/zjfjava/p/7979633.html
Copyright © 2020-2023  润新知