PL/SQL --> 动态SQL调用包中函数或过程

      动态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语句执行计划

时间: 2024-11-05 19:00:18

PL/SQL --&gt; 动态SQL调用包中函数或过程的相关文章

PL/SQL --&amp;gt; 动态SQL

--==================== -- PL/SQL --> 动态SQL --====================         使用动态SQL是在编写PL/SQL过程时经常使用的方法之一.很多情况下,比如根据业务的需要,如果输入不同查询条件,则生成不同的执行 SQL查询语句,对于这种情况需要使用动态SQL来完成.再比如,对于分页的情况,对于不同的表,必定存在不同的字段,因此使用静态SQL则只 能针对某几个特定的表来形成分页.而使用动态的SQL,则可以对不同的表,不同的字段进行

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

  SQL> create or replace procedure sp_guocheng1 is--如果有这个名字就替换  2  begin--执行部分  3  insert into guocheng values('liyifeng','liyifeng');  4  end;  5  /  --执行的意思 Procedure created     显示错误SQL> show error;Errors for PROCEDURE LIYIFENG.SP_GUOCHENG1: LINE

PL/SQL --&amp;gt; 动态SQL的常见错误

--============================ -- PL/SQL --> 动态SQL的常见错误 --============================       动态SQL在使用时,有很多需要注意的地方,如动态SQL语句结尾处不能使用分号(;),而动态PL/SQL结尾处需要使用分号(;),但不能使用正 斜杠结尾(/),以及shcema对象不能直接作为变量绑定.本文介绍了动态SQL的常见问题.   一.演示动态SQL的使用     下面的示例中,首先使用动态SQL基于sco

SQL Server ——动态SQL

动态SQL:code that is executed dynamically.它一般是根据用户输入或外部条件动态组合的SQL语句块.动态SQL能灵活的发挥SQL强大的功能.方便的解决一些其它方法难以 解决的问题.相信使用过动态SQL的人都能体会到它带来的便利,然而动态SQL有时候在执行性能(效率)上面不如静态SQL,而且使用不恰当,往往会在安 全方面存在隐患(SQL 注入式攻击). 动态SQL可以通过EXECUTE 或SP_EXECUTESQL这两种方式来执行.(来自MSDN)     EXE

sqlserver 支持定位当前页,自定义排序的分页SQL(拒绝动态SQL)_MsSql

1,场景:根据学生编号查询,返回该学生所在班级的所有学生.支持分页.自定义排序及结果集自动定位到查询条件的学生编号所在页. 复制代码 代码如下: CREATE PROC [dbo].[Sp_testpagerandsorting] (@GroupID INT, @CurrentId INT, @TimeFrom DATETIME, @TimeTo DATETIME, @OrderBy CHAR(50), @PageSize INT, @CurrentPage INT) AS SET nocoun

sqlserver 支持定位当前页,自定义排序的分页SQL(拒绝动态SQL)

1,场景:根据学生编号查询,返回该学生所在班级的所有学生.支持分页.自定义排序及结果集自动定位到查询条件的学生编号所在页. 复制代码 代码如下: CREATE PROC [dbo].[Sp_testpagerandsorting] (@GroupID INT, @CurrentId INT, @TimeFrom DATETIME, @TimeTo DATETIME, @OrderBy CHAR(50), @PageSize INT, @CurrentPage INT) AS SET nocoun

PL/SQL动态SQL(原创)

概述 使用动态SQL是在编写PL/SQL过程时经常使用的方法之一.很多情况下,比如根据业务的需要,如果输入不同查询条件,则生成不同的执行SQL查询语句,对于这种情况需要使用动态SQL来完成.再比如,对于分页的情况,对于不同的表,必定存在不同的字段,因此使用静态SQL则只能针对某几个特定的表来形成分页.而使用动态的SQL,则可以对不同的表,不同的字段进行不同的分页.这些情况的处理通常都是用动态SQL来完成. 动态SQL和静态SQL静态SQL静态SQL通常用于完成可以确定的任务.比如传递部门号调用存

动态sql 和静态sql 上篇

本文讲解基于Oracle高性能动态SQL程序开发. 1.静态SQL与动态SQL: Oracle编译PL/SQL程序块分为两个种: 其一为前期联编(early binding),即SQL语句在程序编译期间就已经确定,大多数的编译情况属于这种类型: 另外一种是后期联编(late binding),即SQL语句只有在运行阶段才能建立,例如当查询条件为用户输入时,那么Oracle的SQL引擎就无法在编译期对该程序语句进行确定,只能在用户输入一定的查询条件后才能提交给SQL引擎进行处理. 通常,静态SQL

Oracle基础 动态SQL语句

原文:Oracle基础 动态SQL语句 一.静态SQL和动态SQL的概念. 1.静态SQL 静态SQL是我们常用的使用SQL语句的方式,就是编写PL/SQL时,SQL语句已经编写好了.因为静态SQL是在编写程序时就确定了,我们只能使用SQL中的DML和事务控制语句,但是DDL语句,以及会话控制语句却不能再PL/SQL中直接使用,如动态创建表或者某个不确定的操作时,这就需要动态SQL来实现. 2.动态SQL 动态SQL是指在PL/SQL编译时SQL语句是不确定的,如根据用户输入的参数的不同来执行不