动态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. 2013第49周一jsp标签

    2013第49周一jsp标签 今天在调试一些前台页面上的问题,在处理structs标签.jstl标签时遇到了些麻烦,为了调用后台数据字典中的类方法,开始在<c:forEach>中尝试怎么样 ...

  2. SSH2.0编程 ssh协议过程实现

    之前为了自己做一套SSH,先自己实现了一套telnet.但经过这么多天的苦逼,发现以前的工作都是徒劳.ssh的协议很繁杂,核心的内容在于密码算法,而且自己很难在网上找到周全的细节讲解与详细的实现,只有 ...

  3. pyqt 简单判断指定的内容强度(比如帐号)

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.QtGui import * from PyQ ...

  4. 格而知之16:我所理解的Block(2)

    11.那么Block到底是怎么实现的呢?试一试通过将Block 的代码转换成普通C语言代码来查看它的实现过程. 要将OC代码转换成C语言代码,可以使用clang编译的一个命令: 通过这个命令能把指定文 ...

  5. java与.net比较学习系列(6) 数组

    这一篇文章要总结的内容是数组,数组可以简单地看成是同种数据类型变量的集合,它在我们的开发中经常用到,我们主要从以下几个方面进行总结: 1,数组的创建和初始化 2,数组的访问和遍历 3,数组的总结 数组 ...

  6. CodeForces 158 B. Taxi(模拟)

    [题目链接]click here~~ [题目大意]n组团体去包车,每组团体的人数<=4,一辆车最多容纳4人,求所求车的数目最小 [解题思路]:思路见代码~~ // C #ifndef _GLIB ...

  7. LeetCode: Longest Consecutive Sequence [128]

    [题目] Given an unsorted array of integers, find the length of the longest consecutive elements sequen ...

  8. [汇编学习笔记][第五章[BX]和loop指令]

    第五章[BX]和loop指令 前言 定义描述性符号“()”来表示一个寄存器或一个内存单元的内容,比如: (ax)表示ax中的内容,(al)表示al的内容. 约定符号ideta表示常量. 5.1 [BX ...

  9. easyui-window

    <div id="win" class="easyui-window" title="My Window" style="w ...

  10. win7 AnkhSVN 安装报错

    重装系统后,需要安装AnkhSVN,结果一直报如下错误 An error occurred during the installation of assembly"Microsoft.VC8 ...