• Oracle中执行动态SQL


    这篇文章介绍了Oracle中执行动态SQL的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

    一、概述

    在一般的sql操作中,sql语句基本上都是固定的,如: 
    SELECT t.empno,t.ename FROM scott.emp t WHERE t.deptno = 20; 
    但有的时候,从应用的需要或程序的编写出发,都可能需要用到动态SQl,如: 
    当 from 后的表 不确定时,或者where 后的条件不确定时,都需要用到动态SQL。

    使用execute immediate语句可以处理包括ddl(create、alter和drop)、DCL(grant、revoke)、DML(insert、update、delete)以及单行select语句。

    execute immediate语句:

    1. execute immediate dynamic_string
    2. [into {define_variable[,define_variable]…|record}]
    3. [using [in|out|in out] bind_argument[,[in|out|in out]bind_argument]…]
    4. [{returning|return} into bind_argument[, bind_argument]…]
    • define_variable用于指定存放单行查询结果的变量;
    • using in bind_argument用于指定存放传递给动态sql值的变量,即在dynamic中存在占位符时使用;
    • using out bind_argument用于指定存放动态sql返回值的变量。

    二、执行ddl、dcl语句

    不能使用into和using子句。

    1. begin
    2. execute immediate 'create table ma_org(org_codevarchar2(20),org_name varchar2(254))';
    3. execute immediate 'drop table ma_org';
    4. end;

    三、处理dml语句

    1、给动态语句传值(USING 子句)

    如果dml语句包含占位符,那么在execute immediate语句之后必须要带有using子句;

    1. declare
    2. orgcode varchar2(10);
    3. orgname varchar2(254);
    4. begin
    5. orgcode := 1200;
    6. execute immediate 'select org_name fromma_org
    7. where org_code = :X'
    8. into orgname
    9. using orgcode;
    10. dbms_output.put_line(orgname);
    11. end;

    2、从动态语句检索值(INTO子句)

    1. declare
    2. l_cnt varchar2(20);
    3. begin
    4. execute immediate 'select count(1) from emp'
    5. into l_cnt;
    6. dbms_output.put_line(l_cnt);
    7. end;

    3、动态调用存储过程

    1. declare
    2. l_routin varchar2(100) := 'gen2161.get_rowcnt';
    3. l_tblnam varchar2(20) := 'emp';
    4. l_cnt number;
    5. l_status varchar2(200);
    6. begin
    7. execute immediate 'begin ' || l_routin || '(:2, :3, :4); end;'
    8. using in l_tblnam, out l_cnt, in out l_status;
    9. if l_status != 'OK' then
    10. dbms_output.put_line('error');
    11. end if;
    12. end;

    4、处理包含returing子句的DML语句

    如果dml语句带有returning子句,那么在execute immediate语句之后必须带有returning into子句,并且此时只能处理作用的单行上的dml语句,如果dml语句作用在多行上,则必须使用bulk子句。

    1. declare
    2. orgcode varchar2(10);
    3. orgname varchar2(254);
    4. rname varchar2(254);
    5. begin
    6. orgcode := '1200';
    7. orgname := '天津市分行';
    8. execute immediate 'update ma_org set org_name=:X
    9. where org_code = :Y returning org_name into :rname'
    10. using orgname, orgcode
    11. returning into rname;
    12. dbms_output.put_line(orgname);
    13. end;

    5、在retuing into中使用bulk collect into

    通过bulk collect减少loop处理的开销

    采用bulk collect可以将查询结果一次性地加载到collections中。
    而不是通过cursor一条一条地处理。
    可以在select into,fetch into,returning into语句使用bulk collect。
    注意在使用bulk collect时,所有的into变量都必须是collections.


    举几个简单的例子:

    1. --在select into语句中使用bulk collect
    2. DECLARE
    3. TYPE SalList IS TABLE OF emp.sal%TYPE;
    4. sals SalList;
    5. BEGIN
    6. -- Limit the number of rows to 100.
    7. SELECT sal BULK COLLECT INTO sals FROM emp
    8. WHERE ROWNUM <= 100;
    9. -- Retrieve 10% (approximately) of the rows in the table.
    10. SELECT sal BULK COLLECT INTO sals FROM emp SAMPLE 10;
    11. END;
    12. /
    13. --在fetch into中使用bulk collect
    14. DECLARE
    15. TYPE DeptRecTab IS TABLE OF dept%ROWTYPE;
    16. dept_recs DeptRecTab;
    17. CURSOR c1 IS
    18. SELECT deptno, dname, loc FROM dept WHERE deptno > 10;
    19. BEGIN
    20. OPEN c1;
    21. FETCH c1 BULK COLLECT INTO dept_recs;
    22. END;
    23. /
    24. --在returning into中使用bulk collect
    25. CREATE TABLE emp2 AS SELECT * FROM employees;
    26. DECLARE
    27. TYPE NumList IS TABLE OF employees.employee_id%TYPE;
    28. enums NumList;
    29. TYPE NameList IS TABLE OF employees.last_name%TYPE;
    30. names NameList;
    31. BEGIN
    32. DELETE FROM emp2 WHERE department_id = 30
    33. RETURNING employee_id, last_name BULK COLLECT INTO enums, names;
    34. dbms_output.put_line('Deleted ' || SQL%ROWCOUNT || ' rows:');
    35. FOR i IN enums.FIRST .. enums.LAST
    36. LOOP
    37. dbms_output.put_line('Employee #' || enums(i) || ': ' || names(i));
    38. END LOOP;
    39. END;
    40. /
    41. DROP TABLE emp2;

    四、处理多行查询

    oracle通过使用bulk collect into子句处理动态sql中的多行查询可以加快处理速度,从而提高应用程序的性能。当使用bulk子句时,集合类型可以是plsql所支持的索引表、嵌套表和varray,但集合元素必须使用sql数据类型。在oracle9i以后,有三种语句支持bulk子句,execute immediate,fetch和forall。

    1、使用动态游标(游标变量)处理多行查询类动态sql语句。

    1. DECLARE
    2. TYPE ref_cur IS REF CURSOR;
    3. rc ref_cur;
    4. emprow emp%ROWTYPE;
    5. v_sql VARCHAR2(100):= 'select * from emp where deptno = :x'; --动态执行的SQL语句
    6. BEGIN
    7. OPEN rc FOR v_sql USING 30; --打开游标,绑定执行的SQL语句,并传递参数
    8. LOOP
    9. FETCH rc INTO emprow;
    10. EXIT WHEN rc%NOTFOUND;
    11. dbms_output.put_line('name:'||emprow.ename||' sal:'||emprow.sal);
    12. END LOOP;
    13. CLOSE rc;
    14. END;

    2、在execute immediate中使用bulk collect into

    示例:

    1. declare
    2. type org_table_type is table of ma_org%rowtype;
    3. org_table org_table_type;
    4. v_orgcode varchar2(20);
    5. begin
    6. v_orgcode := '%00%';
    7. execute immediate 'select * from ma_org where org_code like:v_orgcode' bulk collect into org_table
    8. using v_orgcode;
    9. for i in 1..org_table.count
    10. loop
    11. dbms_output.put_line(org_table(i).org_code||','||org_table(i).org_name);
    12. end loop;
    13. end;

    3、在forall语句中使用bulk collect into语句

    示例:

    1. declare
    2. type type_org_code is table of ma_org.org_code%type;
    3. type type_org_name is table of ma_org.org_name%type;
    4. v_orgcode type_org_code;
    5. v_orgname type_org_name;
    6. begin
    7. v_orgcode := type_org_code('1100','1200');
    8. forall i in 1..v_orgcode.count
    9. execute immediate 'update ma_org set org_name = org_code||org_namewhere org_code = :p1 returning org_name into :p2'
    10. using v_orgcode(i)
    11. returning bulk collect into v_orgname;
    12. for i in v_orgname.first..v_orgname.last
    13. loop
    14. dbms_output.put_line(v_orgname(i));
    15. end loop;
    16. end;

    到此这篇关于Oracle中执行动态SQL的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 相关阅读:
    济南大学计算机考研资料汇总
    OpenSSH
    Java面试八股文宝典:初识数据结构-数组
    vue2自定义插件
    【Java-LangChain:使用 ChatGPT API 搭建系统-5】处理输入-思维链推理
    键盘出口欧洲地区需要做哪些检测认证?
    SpringMVC(4)——数据封装与异常处理
    【逐步剖C++】-第二章-C++类和对象(下)
    leetcode刷题日记之做菜顺序
    javaSE学习笔记(四)常见类,基本数据类型包装类,StringBuffer&StringBuilder
  • 原文地址:https://blog.csdn.net/wangshengfeng1986211/article/details/126274552