PL/SQL -- 动态SQL的常见错误

               

--============================

-- PL/SQL --> 动态SQL的常见错误

--============================

 

    动态SQL在使用时,有很多需要注意的地方,如动态SQL语句结尾处不能使用分号(;),而动态PL/SQL结尾处需要使用分号(;),但不能使用正

斜杠结尾(/),以及shcema对象不能直接作为变量绑定。本文介绍了动态SQL的常见问题。

 

一、演示动态SQL的使用

    下面的示例中,首先使用动态SQL基于scott.emp创建表tb2,然后里直接使用动态SQL从新表中获取记录数并输出。再接下来是定义了一个动

    PL/SQL代码并执行以获取当前的系统时间,最后使用动态SQL对新表进行更新。

   

       DECLARE                               --定义变量以及给变量设定初始值

         sql_stmt         VARCHAR2(100);

         plsql_block      VARCHAR2(300);

         v_deptno         NUMBER := 30;

         v_count          NUMBER;

         v_new_sal        VARCHAR2(5);

         v_empno          NUMBER := 7900;

       BEGIN

         sql_stmt := 'CREATE TABLE tb_emp ' ||        --为变量赋值,生成动态SQL语句

                    'AS SELECT * FROM scott.emp WHERE deptno = ' || v_deptno;

         EXECUTE IMMEDIATE sql_stmt;                  --执行动态SQL语句

        

         EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM tb_emp' --直接使用EXECUTE IMMEDIATE后跟动态SQL串获得新表的记录数

           INTO v_count;

         DBMS_OUTPUT.PUT_LINE('The employee count is : ' || v_count);

        

         plsql_block := 'DECLARE ' ||             --声明一个PL/SQL块,存放到变量plsql_block

                      ' v_date DATE; ' ||

                      'BEGIN ' ||

                      ' SELECT SYSDATE INTO v_date FROM DUAL; ' ||

                      ' DBMS_OUTPUT.PUT_LINE (TO_CHAR(v_date,''DD-MON-YYYY''));' ||

                      'END;';

         EXECUTE IMMEDIATE plsql_block;           --执行动态的PL/SQL

        

         sql_stmt := 'UPDATE tb_emp SET sal = sal + 100 WHERE empno =:eno ' ||  --更新新表的一条记录

                    'RETURNING sal INTO :sal';                         --动态SQL语句中包含RETURNING子句返回更新后的结果

         EXECUTE IMMEDIATE sql_stmt               --执行动态SQL

           USING v_empno

           RETURNING INTO v_new_sal;              --使用RETURNING子句将结果存放到变量v_new_sal

         DBMS_OUTPUT.PUT_LINE('New salary is: ' || v_new_sal);

       END;

 

       The employee count is : 6

       04-JAN-2011

       New salary is: 1050

 

二、动态SQL的常见错误  

    1.使用动态DDL时,不能使用绑定变量

       下面的示例中,在创建表示,使用了绑定变量:dno,在执行的时候收到了错误信息。

      

       DECLARE

         sql_stmt         VARCHAR2(100);

         v_deptno         VARCHAR2(5) := '30';

         v_count          NUMBER;

       BEGIN

         sql_stmt := 'CREATE TABLE tb_tmp ' || 'AS SELECT * FROM scott.emp ' ||

                    'WHERE deptno = :dno';

         EXECUTE IMMEDIATE sql_stmt

           USING v_deptno;

 

         EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM tb_tmp'

           INTO v_count;

         DBMS_OUTPUT.PUT_LINE('The temp table count is  ' || v_count);

       END;

 

       DECLARE

       *

       ERROR at line 1:

       ORA-01027: bind variables not allowed for data definition operations

       ORA-06512: at line 8

 

       解决办法,将绑定变量直接拼接,如下:

           sql_stmt := 'CREATE TABLE tb_tmp ' || 'AS SELECT * FROM scott.emp ' || 'WHERE deptno = ' || v_deptno;

 

    2.不能使用schema对象作为绑定参数

       下面的示例中,动态SQL语句查询需要传递表名,因此收到了错误提示。

      

       DECLARE

         sql_stmt VARCHAR2(100);

         v_count  NUMBER;

       BEGIN

         EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM :tb_name'

           INTO v_count;

         DBMS_OUTPUT.PUT_LINE('The table record  is  ' || v_count);

       END;

 

       DECLARE

       *

       ERROR at line 1:

       ORA-00903: invalid table name

       ORA-06512: at line 5

 

       处理办法

           DECLARE

             sql_stmt VARCHAR2(100);

             v_tablename VARCHAR2(30) :='scott.emp';   --增加一个变量并赋值

             v_count  NUMBER;

           BEGIN

             EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || v_tablename   --使用|| 连接变量

              INTO v_count;

             DBMS_OUTPUT.PUT_LINE('The table record is  ' || v_count);

           END;

          

           The temp table count is  14

 

    3.动态SQL块不能使用分号结束(;)

       下面的示例中,动态SQL语句使用了分号来结束,收到错误提示。

      

       DECLARE

         sql_stmt VARCHAR2(100);

         --v_tablename VARCHAR2(30) :='scott.emp';

         v_count  NUMBER;

       BEGIN

         EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM tb_emp;'   --此处多出了分号,应该去掉

           INTO v_count;

         DBMS_OUTPUT.PUT_LINE('The temp table count is  ' || v_count);

       END;

 

       DECLARE

       *

       ERROR at line 1:

       ORA-00911: invalid character

       ORA-06512: at line 6

      

       处理办法

           去掉动态SQL语句末尾的分号

 

    4.动态PL/SQL块不能使用正斜杠来结束块,但是块结尾处必须要使用分号(;)

   

       DECLARE

         plsql_block VARCHAR2(300);

       BEGIN

         plsql_block := 'DECLARE ' ||

                      ' v_date DATE; ' ||

                      ' BEGIN ' ||

                        ' SELECT SYSDATE INTO v_date FROM DUAL; ' ||

                        ' DBMS_OUTPUT.PUT_LINE (TO_CHAR(v_date,''YYYY-MM-DD''));' ||

                      'END;

                        /';   --此处多出了/,应该将其去掉

         EXECUTE再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值