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

简介:       动态SQL主要是用于针对不同的条件或查询任务来生成不同的SQL语句。最常用的方法是直接使用EXECUTE IMMEDIATE来执行动态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,个人更倾向于使用前者

 

Oracle&nbsp;牛鹏社    Oracle DBsupport

更多参考

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

目录
相关文章
|
2月前
|
SQL 数据采集 监控
局域网监控电脑屏幕软件:PL/SQL 实现的数据库关联监控
在当今网络环境中,基于PL/SQL的局域网监控系统对于企业和机构的信息安全至关重要。该系统包括屏幕数据采集、数据处理与分析、数据库关联与存储三个核心模块,能够提供全面而准确的监控信息,帮助管理者有效监督局域网内的电脑使用情况。
40 2
|
3月前
|
SQL Oracle 关系型数据库
SQL优化-使用联合索引和函数索引
在一次例行巡检中,发现一条使用 `to_char` 函数将日期转换为字符串的 SQL 语句 CPU 利用率很高。为了优化该语句,首先分析了 where 条件中各列的选择性,并创建了不同类型的索引,包括普通索引、函数索引和虚拟列索引。通过对比不同索引的执行计划,最终确定了使用复合索引(包含函数表达式)能够显著降低查询成本,提高执行效率。
|
3月前
|
SQL 数据库 数据库管理
数据库SQL函数应用技巧与方法
在数据库管理中,SQL函数是处理和分析数据的强大工具
|
3月前
|
SQL 数据库 索引
SQL中COUNT函数结合条件使用的技巧与方法
在SQL查询中,COUNT函数是一个非常常用的聚合函数,用于计算表中满足特定条件的记录数
|
3月前
|
SQL 关系型数据库 MySQL
SQL日期函数
SQL日期函数
|
4月前
|
SQL 关系型数据库 C语言
PostgreSQL SQL扩展 ---- C语言函数(三)
可以用C(或者与C兼容,比如C++)语言编写用户自定义函数(User-defined functions)。这些函数被编译到动态可加载目标文件(也称为共享库)中并被守护进程加载到服务中。“C语言函数”与“内部函数”的区别就在于动态加载这个特性,二者的实际编码约定本质上是相同的(因此,标准的内部函数库为用户自定义C语言函数提供了丰富的示例代码)
|
5月前
|
SQL 数据处理 数据库
|
5月前
|
SQL Oracle 关系型数据库
SQL与PL/SQL:数据库编程语言的比较
【8月更文挑战第31天】
105 0
|
5月前
|
SQL Oracle 关系型数据库
SQL 中的大小写处理函数详解
【8月更文挑战第31天】
218 0
|
5月前
|
SQL 数据采集 数据挖掘
为什么要使用 SQL 函数?详尽分析
【8月更文挑战第31天】
69 0
下一篇
开通oss服务