本地动态sql

  
  
  1. DECLARE
  2.   sql_stmt VARCHAR2(100);
  3.   plsql_block VARCHAR2(300);
  4.   v_zip VARCHAR2(5) := '11106';
  5.   v_total_students NUMBER;
  6.   v_new_zip VARCHAR2(5);
  7.   v_student_id NUMBER := 151;
  8. BEGIN
  9.   -- Create table MY_STUDENT
  10.   sql_stmt := 'CREATE TABLE my_student '||
  11.               'AS SELECT * FROM student WHERE zip = '||v_zip;
  12.   EXECUTE IMMEDIATE sql_stmt;
  13.   -- Select total number of records from MY_STUDENT table
  14.   -- and display results on the screen
  15.   EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM my_student'
  16.   INTO v_total_students;
  17.   DBMS_OUTPUT.PUT_LINE ('Students added: '||v_total_students);
  18.    -- Select current date and display it on the screen
  19.   plsql_block := 'DECLARE '                                 ||
  20.                  '   v_date DATE; '                         ||
  21.                  'BEGIN '                                   ||
  22.                  '   SELECT SYSDATE INTO v_date FROM DUAL; '||
  23.                  '   DBMS_OUTPUT.PUT_LINE (TO_CHAR(v_date,
  24.                                            ''DD-MON-YYYY''))
  25. ;'|| 'END;';
  26.   EXECUTE IMMEDIATE plsql_block;
  27.   -- Update record in MY_STUDENT table
  28.   sql_stmt := 'UPDATE my_student SET zip = 11105 WHERE student_id =
  29.                :1 '||
  30.               'RETURNING zip INTO :2';
  31.   EXECUTE IMMEDIATE sql_stmt USING v_student_id RETURNING INTO
  32.      v_new_zip;
  33.   DBMS_OUTPUT.PUT_LINE ('New zip code: '||v_new_zip);
  34. END;
  35. /
  36. Students added: 4
  37. 08-MAR-2016
  38. New zip code: 11105
  39. PL/SQL procedure successfully completed.
上述脚本包含多个动态SQL的范例。

首先创建表my_student,并且使用邮政编码的指定值记录来填充它。要注意变量v_zip与create语句一起使用,而不是作为绑定参数进行传递。

为啥不能绑定变量呢?

  
  
  1. DECLARE
  2.   sql_stmt VARCHAR2(100);
  3.   v_zip VARCHAR2(5) := '11106';
  4. BEGIN
  5.   sql_stmt := 'CREATE TABLE my_student '||
  6.               'AS SELECT * FROM student WHERE zip = :1';
  7.   EXECUTE IMMEDIATE sql_stmt using v_zip;
  8. end;
  9. /
  10. DECLARE
  11. *
  12. ERROR at line 1:
  13. ORA-01027: bind variables not allowed for data definition operations
  14. ORA-06512: at line 7

通过报错可以看出DDL语句是不允许绑定变量的

其次,获取my_student表中学生的总数量,并在屏幕上显示。在EXECUTE IMMEDIATE语句中使用into选项,因为select语句会返回单行数据。

第三,创建一个简单的PL/SQL语句块,用于获取当前日期,并在屏幕上显示。由于这个PL/SQL语句块不包含绑定参数,按照最简单的形式使用EXECUTE IMMEDIATE语句

最后,更新my_student表中指定学生ID的数据记录,并使用returning语句返回邮政编码的更新值。这样的话,EXECUTE IMMEDIATE命令会包含using和returning into选项。借助于using选项,可以在运行时向update语句传递学生ID的值;借助于returning into选项,可以把update语句中邮政编码的新值传入自己的程序。


还需要注意的一点是,使用动态SQL语句时,不可以把模式对象的名称作为绑定参数传递给动态SQL语句(pass names of schema objects to dynamic SQL)

  
  
  1. DECLARE
  2.   sql_stmt VARCHAR2(100);
  3.   v_zip VARCHAR2(5) := '11106';
  4.   v_total_students number;
  5. BEGIN
  6.   sql_stmt := 'CREATE TABLE my_student '||
  7.               'AS SELECT * FROM student WHERE zip = '||v_zip;
  8.   EXECUTE IMMEDIATE sql_stmt;
  9.   EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM :my_student'
  10.   INTO v_total_students using 'my_student';
  11.   DBMS_OUTPUT.PUT_LINE ('Students added: '||v_total_students);
  12. end;
  13. /
  14. DECLARE
  15. *
  16. ERROR at line 1:
  17. ORA-00903: invalid table name
  18. ORA-06512: at line 10
为了运行时提供表的名称,需要把这个范例与SELECT语句连起来。

  
  
  1. EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM '||my_table into v_total_students;
还需要注意的是,动态SQL语句结尾不应该是分号';'。类似的,动态PL/SQL语句块的结尾不能使右斜线'/'

传入NULL值

在一些情况下,需要给动态SQL语句传递NULL值,作为绑定参数的值。

  
  
  1. DECLARE
  2. sql_stmt varchar2(100);
  3. BEGIN
  4. sql_stmt := 'update course set prerequisite = :some_value';
  5. execute immediate sql_stmt using NULL;
  6. end;
  7. /
  8. execute immediate sql_stmt using NULL;
  9.                                 *
  10. ERROR at line 5:
  11. ORA-06550: line 5, column 34:
  12. PLS-00457: expressions have to be of SQL types
  13. ORA-06550: line 5, column 1:
  14. PL/SQL: Statement ignored
之所以产生这个错误,原因在于USING子句中字面值NULL没有被识别为一种SQL类型。为把NULL值传递给动态SQL语句,应该按照如下样子修改这个范例
  
  
  1. DECLARE
  2. sql_stmt varchar2(100);
  3. v_null varchar2(1);
  4. BEGIN
  5. sql_stmt := 'update course set prerequisite = :some_value';
  6. execute immediate sql_stmt using v_null;
  7. end;
  8. /

本地动态SQL,个人理解,目的就是为了使用绑定变量。如果不用动态SQL,where条件是写死的
目前为止的动态SQL都只返回1行数据,要想返回多行,需要使用Ref Cursor

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值