动态SQL主要是用于针对不同的条件或查询任务来生成不同的SQL语句。最常用的方法是直接使用EXECUTE IMMEDIATE来执行动态SQL语句字符串或字符串变量。但是对于系统自定义的包或用户自定的包其下的函数或过程,不能等同于DDL以及DML的调用,其方式稍有差异。如下见本文的描述。

有关动态SQL的描述,请参考:
           PL/SQL --> 动态SQL           PL/SQL --> 动态SQL的常见错误

1、动态SQL调用包中过程不正确的调用方法

--演示环境
scott@USBO> select * from v$version where rownum<2; BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production --下面的调用方法不正确,收到了ORA-00900错误消息
scott@USBO> set serveroutput on;
scott@USBO> DECLARE
2 v_sql VARCHAR2 (300);
3 v_tab VARCHAR2 (30) := 'DEPT';
4 BEGIN
5 v_sql := 'dbms_stats.gather_table_stats(''SCOTT'',''EMP'',cascade=>true)';
6 DBMS_OUTPUT.put_line (v_sql);
7
8 EXECUTE IMMEDIATE v_sql;
9 END;
10 /
dbms_stats.gather_table_stats('SCOTT','EMP',cascade=>true)
DECLARE
*
ERROR at line 1:
ORA-00900: invalid SQL statement
ORA-06512: at line 8 --下面检查一下是否是sql拼接有问题
scott@USBO> DECLARE
2 v_sql VARCHAR2 (300);
3 v_tab VARCHAR2 (30) := 'DEPT';
4 BEGIN
5 v_sql := 'dbms_stats.gather_table_stats(''SCOTT'',''EMP'',cascade=>true)';
6 DBMS_OUTPUT.put_line (v_sql);
7
8 -- EXECUTE IMMEDIATE v_sql;
9 END;
10 /
dbms_stats.gather_table_stats('SCOTT','EMP',cascade=>true) PL/SQL procedure successfully completed. --对于上面的SQL拼接正常,如下,直接复制输出的sql加上exec来执行成功
scott@USBO> exec dbms_stats.gather_table_stats('SCOTT','EMP',cascade=>true) PL/SQL procedure successfully completed.

2、动态SQL调用包中过程正确的调用方法

--如下面这段plsql代码,我们在原代码的基础上增加了begin ..与end部分后,该plsql块被成功执行
--注,字符拼接的plsql块中,end; 之后不需要使用斜杠“/”
scott@USBO> DECLARE
2 v_sql VARCHAR2 (300);
3 v_tab VARCHAR2 (30) := 'DEPT';
4 BEGIN
5 v_sql := 'begin dbms_stats.gather_table_stats(''SCOTT'',''EMP'',cascade=>true); end;';
6 DBMS_OUTPUT.put_line (v_sql);
7
8 EXECUTE IMMEDIATE v_sql;
9 END;
10 /
begin dbms_stats.gather_table_stats('SCOTT','EMP',cascade=>true); end; PL/SQL procedure successfully completed.

3、动态SQL调用包中过程带变量的情形

--下面这个示例中拼接的字串中,调用了声明中的变量
--下面给出了错误提示,是由于我们漏掉了两个单引号,即需要使用转义字符,错误如下
scott@USBO> DECLARE
2 v_sql VARCHAR2 (300);
3 v_tab VARCHAR2 (30) := 'DEPT';
4 BEGIN
5 v_sql := 'begin dbms_stats.gather_table_stats(''SCOTT'',' || v_tab || ',cascade=>true); end;';
6 --DBMS_OUTPUT.put_line (v_sql);
7
8 EXECUTE IMMEDIATE v_sql;
9 END;
10 /
DECLARE
*
ERROR at line 1:
ORA-06550: line 1, column 45:
PLS-00357: Table,View Or Sequence reference 'DEPT' not allowed in this context
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
ORA-06512: at line 8 --下面是增加两个单引号后的情形
scott@USBO> DECLARE
2 v_sql VARCHAR2 (300);
3 v_tab VARCHAR2 (30) := 'DEPT';
4 BEGIN
5 v_sql := 'begin dbms_stats.gather_table_stats(''SCOTT'',''' || v_tab || ''',cascade=>true); end;';
6 DBMS_OUTPUT.put_line (v_sql);
7
8 EXECUTE IMMEDIATE v_sql;
9 END;
10 /
begin dbms_stats.gather_table_stats('SCOTT','DEPT',cascade=>true); end; PL/SQL procedure successfully completed.

4、动态SQL中调用包中函数的情形

--下面我们来调用系统包所带的函数dbms_output.put_line
--Author : Leshami
--Blog : http://blog.csdn.net/leshami scott@USBO> DECLARE
2 v_sql VARCHAR2 (300);
3 BEGIN
4 v_sql := 'begin dbms_output.put_line(''This is only a test''); end;';
5
6 --DBMS_OUTPUT.put_line (v_sql);
7
8 EXECUTE IMMEDIATE v_sql;
9 END;
10 /
This is only a test PL/SQL procedure successfully completed. --直接使用下面的方式可以实现
scott@USBO> BEGIN
2 EXECUTE IMMEDIATE 'begin dbms_output.put_line(''This is only a test''); end;';
3 END;
4 /
This is only a test PL/SQL procedure successfully completed.

5、小结
a、对于动态SQL来调用函数,我们需要使用begin .. end来封装块,而不是简单的类似于DML以及DDL的调用方法
b、不能使用'exec pkg_name.proc_name'方式来拼接动态sql
c、可以拼接sql到变量,也可以直接将动态sql紧跟在EXECUTE IMMEDIATE,个人更倾向于使用前者

   

更多参考

DML Error Logging 特性

PL/SQL --> 游标

PL/SQL --> 隐式游标(SQL%FOUND)

批量SQL之 FORALL 语句

批量SQL之 BULK COLLECT 子句

PL/SQL 集合的初始化与赋值

PL/SQL 联合数组与嵌套表
PL/SQL 变长数组
PL/SQL --> PL/SQL记录

SQL tuning 步骤

高效SQL语句必杀技

父游标、子游标及共享游标

绑定变量及其优缺点

dbms_xplan之display_cursor函数的使用

dbms_xplan之display函数的使用

执行计划中各字段各模块描述

使用 EXPLAIN PLAN 获取SQL语句执行计划

PL/SQL --> 动态SQL调用包中函数或过程的更多相关文章

  1. oracle 包,函数,过程,块的创建和执行及在java中执行(转)

    SQL> create or replace procedure sp_guocheng1 is--如果有这个名字就替换  2  begin--执行部分  3  insert into guoc ...

  2. 使用命令动态更新JAR包中的文件

    动态更新JAR包中的文件,经本人实际测试可正常执行! 一.查询jar包中要替换的文件位置 jar  -tvf  gateway.jar  |  grep  topjui.config.js 二.在当前 ...

  3. [SQL]动态sql语句基本语法

    动态sql语句基本语法 :普通SQL语句可以用Exec执行 eg: Select * from tableName Exec('select * from tableName') Exec sp_ex ...

  4. mybatis Dynamic SQL动态 SQL

    动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦.例如拼接时要确保不能忘记添加必要的空格 ...

  5. DLL模块例1:使用.def模块导出函数,规范修饰名称,显示连接调用dll中函数

    以下内容,我看了多篇文章,整合在一起,写的一个例子,关于dll工程的创建,请参考博客里另一篇文章:http://www.cnblogs.com/pingge/articles/3153571.html ...

  6. <asp:Button点击查询后,调用js中函数展现加载圈

    <div> <div id='paneloading' style='display:none;position:fixed;top:0px;left:0px;z-index:999 ...

  7. R语言学习笔记(二十):stringr包中函数介绍(表格)

    stringr包中的重要函数 函数 功能说明 R Base中对应函数 使用正则表达式的函数 str_extract() 提取首个匹配模式的字符 regmatches() str_extract_all ...

  8. DELPHI中函数、过程变量的声明与应用

    Procedure型变量: 在DELPHI中,函数.过程的地址可以赋给一个特殊类型的变量,变量可用如下方式声明: var p : procedure(num:integer); //过程 或: var ...

  9. PL/SQL 动态SQL

    declare msql varchar2(200); row_id varchar2(200); begin loop row_id := 'AAATGiAAEAAAuLLAAA'; msql := ...

随机推荐

  1. fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'X86'

    这个问题很奇怪.原来是/machine:X86 /machine:X64这两个链接器选项一起使用了.所以就冲突了.接手别人的项目就是晕啊.不知道为什么在VS中linker commandline的ad ...

  2. 【转】android cts failed items

    原文网址:http://blog.csdn.net/linsa0517/article/details/19031479 Fail的一些修改   1.直接设置问题 estUnknownSourcesO ...

  3. Jquery的bootstrap在线文本编辑器插件Summernote

    http://www.jqcool.net/demo/201407/bootstrap-summernote/ Summernote是一个基于jquery的bootstrap超级简单WYSIWYG在线 ...

  4. hdu 1159 Common Subsequence(LCS最长公共子序列)

    Common Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  5. linux之chdir函数解析

    [lingyun@localhost chdir]$ ls chdir.c [lingyun@localhost chdir]$ cat chdir.c  /********************* ...

  6. 第10讲- UI线程阻塞及其优化

    第10讲UI线程阻塞及其优化 .UI 阻塞demo (首先在activity_main.xml中放置两个button,分别命名为button1,button2) //首先设置一个button1用来进行 ...

  7. hdu 4336 Card Collector(期望 dp 状态压缩)

    Problem Description In your childhood, people in the famous novel Water Margin, you will win an amaz ...

  8. PHP初识

    1. php是一种跨平台的语言,支持几乎全部的数据库. 以前觉得PHP与MYSQL是黄金组合,对于PHP能否支持MSSQL没有过了解,PHP支持几乎全部的数据库,也支持MSSQL(5.2.X版本可以用 ...

  9. 通过winForm控制webForm的上传控件file的值

    文件上传是日常开发中经常遇到的,文件上传用的最多的当然是上传控件file了,一个form表单,其中有一点就是form表单的enctype属性设置为multipart/form-data,呵呵,这个在所 ...

  10. [Hapi.js] POST and PUT request payloads

    hapi makes handling POST and PUT payloads easy by buffering and parsing them automatically without r ...