zoukankan      html  css  js  c++  java
  • oracle 动态SQL

    动态SQL的书写:
    1.本地动态SQL(Native Dynamic SQL),用于建立和执行SQL语句, 使用EXECUTE IMMEDIATE命令来执行动态SQL语句。
    2.包DBMS_SQL也可用于执行动态SQL。

    CREATE OR REPLACE PROCEDURE  CreateTable(tablename VARCHAR2)
    IS
    BEGIN
        EXECUTE IMMEDIATE  'CREATE TABLE ' || tablespace || '(name VARCHAR(20),producer VARCHAR(30),price NUMBER)' ;
    END;
    --存储过程 CreateTable的输入参数是表的名字,根据表名的不同,动态创建不同的表。

    处理TCL语句:(事务控制语句)
    可以在PL/SQL代码中直接执行COOMMIT或ROLLBACK等事务控制语句,也可以在动态SQL中执行事务控制语句。

     1 DECLARE
     2 SQLstring VARCHAR2(1000);
     3 BEGIN
     4     SQLstring := 'COMMIT';
     5     EXECUTE IMMEDIATE 'INSERT INTO phone_info  VALUES(''N97'',''诺基亚'',400)';
     6     EXECUTE IMMEDIATE SQLstring;
     7 END;
     8 --查询执行结果:
     9 SELECT * FROM phone_info;
    10 
    11 NAME                 PRODUCER                            PRICE
    12 -------------------- ------------------------------ ----------
    13 N97                  诺基亚                                400

    处理DML语句
    普通的DML语句,不带占位符,不带USING子句:

     1 BEGIN
     2    EXECUTE IMMEDIATE 'INSERT INTO phone_info VALUES(''V800'',''中兴'',500)';
     3    COMMIT;
     4 END;
     5 --结果:
     6 SQL> SELECT * FROM phone_info;
     7 
     8 NAME                 PRODUCER                            PRICE
     9 -------------------- ------------------------------ ----------
    10 N97                  诺基亚                                400
    11 V800                 中兴                                  500
    12 
    13 已选择2行。

    有占位符的DML,使用USING子句传入值

     1 DECLARE
     2     v_phone_name  VARCHAR2(20) := 'C510c';
     3     v_producer VARCHAR2(20) := '爱立信';
     4     v_price NUMBER := 1000;
     5 BEGIN
     6     EXECUTE IMMEDIATE 'INSERT INTO phone_info VALUES(:a, :b,:c)' 
     7     USING v_phone_name,v_producer,v_price;
     8 COMMIT;
     9 END;
    10 
    11 SQL> SELECT * FROM phone_info;
    12 
    13 NAME                 PRODUCER                            PRICE
    14 -------------------- ------------------------------ ----------
    15 N97                  诺基亚                                400
    16 V800                 中兴                                  500
    17 C510c                爱立信                               1000

    执行有返回值的DML:

     1 DECLARE
     2     SQLstring VARCHAR2(1000);
     3     v_phone_name  VARCHAR2(20);
     4     v_producer VARCHAR2(20);
     5     v_price NUMBER := 400;
     6 BEGIN
     7     SQLstring := 'UPDATE phone_info SET price = 499 WHERE price = :a RETURNING name,producer,price INTO :b,:c,:d';
     8     EXECUTE IMMEDIATE SQLstring USING v_price RETURNING INTO v_phone_name,v_producer,v_price;
     9     COMMIT;
    10     DBMS_OUTPUT.PUT_LINE(v_phone_name||'  '||v_producer||'   '||v_price);
    11 END;
    1 --结果: price为400的已经更新为499.
    2 SQL> SELECT * FROM phone_info;
    3 
    4 NAME                 PRODUCER                            PRICE
    5 -------------------- ------------------------------ ----------
    6 N97                  诺基亚                                499
    7 V800                 中兴                                  500
    8 C510c                爱立信                               1000

    在动态SQL中调用存储过程或者函数:

     1 --定义procedure,
     2 CREATE  OR REPLACE  PROCEDURE  P_call (p1 IN VARCHAR2 := NULL ) AS
     3 BEGIN
     4     DBMS_OUTPUT.PUT_LINE(p1 || 'is from PROCEDURE P_call');
     5 END P_call;
     6 在动态SQL中调用procedure,
     7 BEGIN
     8     EXECUTE IMMEDIATE ' CALL P_call(''hihihi '')';
     9 END;
    10   4  /
    11 hihihi is from PROCEDURE P_call
    12 
    13 PL/SQL 过程已成功完成。

    在动态SQL中调用函数:

     1 CREATE OR REPLACE  FUNCTION F_call (p1 IN VARCHAR2)
     2 RETURN VARCHAR2 AS
     3 BEGIN
     4     RETURN p1 || ' is from FUNCTION F_call';
     5 END F_call;
     6 
     7 DECLARE 
     8 V_return VARCHAR2(50);
     9 functiong_Result VARCHAR2(50);
    10 BEGIN
    11     EXECUTE IMMEDIATE 'CALL F_call(''hello Daisy'') INTO :functiong_Result'
    12     USING OUT V_return;
    13 DBMS_OUTPUT.PUT_LINE(V_return);
    14 END;
    15   8  /
    16 hello Daisy is from FUNCTION F_call

    处理单行查询
    利用动态SQL,在PL/SQL中,可以对表进行查询,通过INTO子句,可以把查询结果保存在变量中。

    1 DECLARE 
    2     v_maxprice NUMBER;
    3     v_producer VARCHAR2(20) := '诺基亚';
    4 BEGIN
    5     EXECUTE IMMEDIATE 'SELECT max(price) FROM phone_info  WHERE producer= :a' 
    6     INTO v_maxprice     
    7     USING v_producer;
    8     dbms_output.put_line(v_maxprice);
    9 END;

    处理多行查询:
    两种方法,一是使用带有子句BULK COLLECT INTO的EXECUTE IMMEDIATE语句
    二是使用BULK COLLECT INTO 处理多行查询。
    BULK COLLECT可以将查询结果一次性的加载到集合中,而不是通过游标一条条地处理,这样的处理速度慢,可以在SELECT INTO 、FETCH INTO 、RETURNING INTO

    语句中使用BULK COLLECT,所有的INTO变量都必须是集合(COLLECTIONN)

     1 CREATE OR REPLACE  TYPE phone_type AS OBJECT
     2 (--定义新类型对象 
     3 name VARCHAR2(20),
     4 producer VARCHAR2(20),
     5 price NUMBER
     6 );
     7 
     8 CREATE  OR REPLACE  TYPE  phone_tab AS TABLE OF phone_type;--定义新类型
     9 
    10 DECLARE
    11     v_rec phone_tab;
    12 BEGIN
    13     EXECUTE IMMEDIATE 'SELECT phone_type (name,producer,price) FROM phone_info' BULK COLLECT INTO v_rec;
    14       FOR i IN v_rec.FIRST ..v_rec.LAST LOOP
    15         DBMS_OUTPUT.PUT_LINE(v_rec(i).name || '  ' ||v_rec(i).producer||'  ' ||v_rec(i).price);
    16     END LOOP;
    17 END;
     1 DECLARE 
     2     TYPE ref_type IS REF CURSOR;
     3     v_cursor  ref_type;
     4     v_record phone_info%ROWTYPE;
     5     sqlstring  VARCHAR2(200);
     6 BEGIN
     7     sqlstring := 'SELECT * FROM phone_info WHERE price > :p';
     8     OPEN v_cursor FOR sqlstring
     9         USING 450;
    10     LOOP
    11         FETCH v_cursor
    12             INTO  v_record;
    13     DBMS_OUTPUT.PUT_LINE('the record which >'||:p||' :  '||v_record.name || '     '||v_record.price );
    14     EXIT WHEN v_cursor%NOTFOUND;
    15     CLOSE v_cursor;
    16 END;
    17 --该procedure把手机价格大于500的打印出来。

    DBMS_SQL包提供一个接口,用于执行动态SQL(DDL和DML),DBMS_SQL定义了一个实体叫做游标ID,游标ID是一个PL/SQL整型数,通过游标ID可以对游标进行操作。
    包DBMS_SQL提供了一系列的过程和函数,用于协同执行动态SQL,这些函数和过程是:

     1 ---------------------------函数-------------------
     2 OPEN_CURSOR,打开一个动态游标,并返回一个整型;
     3 EXECUTE(c IN INTEGER),执行游标,并返回处理的函数(INSERTDELETE、UPDATE有意义);
     4 FETCH_ROWS(c IN INTEGER)循环对游标中取数据。
     5 ------------------------过程----------------------
     6 CLOSE_CURSOR(c IN OUT INTEGER) --关闭游标,
     7 PARSE(c IN INTEGER,statement IN VARCHAR2,language_flag IN INTEGER)--.对动态游标所提供的SQL语句进行解析,参数c表示有效,statement为SQL语句,language_flag为解析SQL语句所用的版本,一般是V6、NATIVE、V7。若被解析的是DDL语句,则解析完成后被立即执行。
     8 DEFINE_COLUMN(c IN INTEGER, position IN INTEGER,column ANY DATATYPE,[column_size IN INTEGER]),--定义从游标中选出的列,c为游标,position为对应动态SQL中的位置(从1开始),column为该值所对应的变量,可以为任何类型,column_size定义列的宽度,如果列的类型为字符型,必须定义宽度,这个语句只用于带有SELECT语句。
     9 COLUMN_VALUE(c IN INTEGER,position IN INTEGER,VALUE),--将所取得的游标数据赋值到相应的变量,c为游标,position为位置,VALUE则为对应的变量。
    10 BIND_VARIABLE(c IN INTEGER, name IN VARCHAR2,VALUE)--定义动态SQL语句(DML)中所对应字段的值。c为游标,name为字段名称,VALUE为字段的值。

    DBMS_SQL执行DDL语句的过程是:打开游标-->SQL语句解析-->关闭游标。

     1 CREATE OR REPLACE PROCEDURE  CreateTable(tablename VARCHAR2)
     2 IS
     3 SQL_string VARCHAR2(1000);--存放SQL语句
     4 V_cur integer;--存放游标
     5 BEGIN
     6 SQL_string := 'CREATE TABLE '||tablename || '(name VARCHAR2(20))';
     7 V_cur :=dbms_sql.open_cursor;
     8 dbms_sql.parse(V_cur,SQL_string,DBMS_SQL.NATIVE);
     9 dbms_sql.close_cursor(V_cur);
    10 END;
    11 SQL> EXECUTE CreateTable('MYTB');
    12 
    13 PL/SQL 过程已成功完成。
    14 
    15 已用时间:  00: 00: 00.17
    16 SQL> desc MYTB;
    17  名称
    18  -----------------------------------------
    19 ------------------------------------------
    20  NAME

    利用DBMS_SQL执行SELECT语句:

     1 DECLARE
     2     V_cursor NUMBER;
     3     SQLstring VARCHAR2(1000);
     4     v_phone_name  VARCHAR2(20);
     5     v_producer VARCHAR2(20);
     6     v_price NUMBER := 400;
     7     v_count INT;
     8 BEGIN
     9     SQLstring := 'SELECT name,producer,price FROM phone_info WHERE price >:p';
    10     V_cursor := dbms_sql.open_cursor;--open the cursor;
    11     dbms_sql.parse(V_cursor,SQLstring,dbms_sql.native);--parse the sql statement;
    12     dbms_sql.bind_variable(V_cursor,'p',v_price);
    13     
    14     dbms_sql.define_column(v_cursor,1,v_phone_name,20);
    15     dbms_sql.define_column(v_cursor,2,v_producer,20);
    16     dbms_sql.define_column(v_cursor,3,v_price);
    17     v_count := dbms_sql.EXECUTE(V_cursor);
    18 
    19     LOOP
    20         EXIT WHEN DBMS_sql.fetch_rows(V_cursor) <= 0;
    21         dbms_sql.column_value(V_cursor,1,v_phone_name);
    22         dbms_sql.column_value(V_cursor,2,v_producer);
    23         dbms_sql.column_value(V_cursor,3,v_price);
    24         dbms_output.put_line(v_phone_name|| '   '||v_producer ||'  '||v_price);
    25     END LOOP;
    26     dbms_sql.close_cursor(V_cursor);
    27 END;
    28 --把price >400的都打印出来了。

    利用DBMS_SQL执行DML语句
    过程:打开游标--》解析动态SQL--》绑定输入参数—》执行动态SQL--》关闭游标。

     1 DECLARE 
     2     v_cursor NUMBER;
     3     sqlstring VARCHAR2(200);
     4     v_phone_name VARCHAR2(20);
     5     v_producer VARCHAR2(20);
     6     v_price NUMBER;
     7     v_count    INT;
     8 BEGIN
     9     sqlstring := 'INSERT INTO phone_info VALUES(:a,:b,:c)'; ---:a,:b,:c
    10     v_phone_name := 'iphone';
    11     v_producer := 'APPLE';
    12     v_price := 3999;
    13     v_cursor :=dbms_sql.open_cursor;
    14     dbms_sql.parse(v_cursor,sqlstring,dbms_sql.native);
    15     dbms_sql.bind_variable (v_cursor,':a',v_phone_name);
    16     dbms_sql.bind_variable (v_cursor,':b',v_producer);
    17     dbms_sql.bind_variable (v_cursor,':c',v_price);
    18     v_count := dbms_sql.EXECUTE(v_cursor);
    19     dbms_sql.close_cursor(v_cursor);
    20     dbms_output.put_line('INSERT '||to_char(v_count)||'  row');
    21     COMMIT;
    22 END;
  • 相关阅读:
    Java 简单算法--打印乘法口诀(只使用一次循环)
    Java简单算法--求100以内素数
    ubuntu 16.04 chrome flash player 过期
    java 网络API访问 web 站点
    java scoket (UDP通信模型)简易聊天室
    leetcode1105 Filling Bookcase Shelves
    leetcode1140 Stone Game II
    leetcode1186 Maximum Subarray Sum with One Deletion
    leetcode31 Next Permutation
    leetcode834 Sum of Distances in Tree
  • 原文地址:https://www.cnblogs.com/happinessqi/p/3352820.html
Copyright © 2011-2022 走看看