Oracle Native Dynamic SQL PL/SQL 语句没有开始和结束

Posted

技术标签:

【中文标题】Oracle Native Dynamic SQL PL/SQL 语句没有开始和结束【英文标题】:Oracle Native Dynamic SQL PL/SQL statement without begin and end 【发布时间】:2012-11-16 08:23:14 【问题描述】:

我遇到了通过创建一系列插入语句来为表创建备份的问题。

输入是表名,每个表可以有不同的列数。假设数据类型只能是 varchar2、数字或日期

所以我有这行代码:

execute immediate fetchStmt;

fetchStmt 可以在哪里:

fetch tableColCursor into valuesArray(1), valuesArray(2), ...,  valuesArray(n)

这只是从游标中获取每一行并将其放入一个可变数组中,如果它不在立即执行语句中,则语句本身会起作用。

我知道立即执行只能处理 SQL 查询或 PL/SQL 块。 问题是我如何才能完成这项工作,或者有什么类似的解决方案可以解决这个问题?

请注意,在编译时不知道表及其列及其数据类型

【问题讨论】:

:你有一个包含所有 dml 语句的表吗?如果有,你能把表的结构或你的光标贴出来吗? 【参考方案1】:

EXECUTE IMMEDIATE 只能处理完整的语句,即:SQL 语句或 PLSQL 块(带有[DECLARE]..BEGIN..END)。

此外,以这种方式执行的块不会看到来自调用块的任何变量(它们不共享相同的范围),例如这不起作用:

DECLARE
  l NUMBER := 1;
  k NUMBER := 0;
BEGIN
  EXECUTE IMMEDIATE 'BEGIN l := k; END;';
END;

上面的代码会产生错误,因为lk没有在子块中定义。相反,您需要使用输入/输出变量:

DECLARE
  l NUMBER := 1;
  k NUMBER := 0;
BEGIN
  EXECUTE IMMEDIATE 'BEGIN :P1 := :P2; END;' USING OUT l, k;
  dbms_output.put_line(l); -- return 0
END;

在您的情况下,您不知道变量的数量,因此您将无法使用EXECUTE IMMEDIATE。您可以使用DBMS_SQL,但我认为有更简单的方法:您可以找到已经工作的代码(例如,它存在于 Oracle APEX 中),或者您可以通过运行会生成必要的 INSERT 字符串的 SELECT 自行编程。对于此方法,您必须动态生成 SQL 语句(取决于表列)。该语句看起来像这样(对于一个表TEST(a,b,c),其中所有列都是整数[需要适应其他数据类型]):

SELECT 'INSERT INTO test(a,b,c) VALUES ('||a||', '||b||', '||c||');'
  FROM test

【讨论】:

以上是关于Oracle Native Dynamic SQL PL/SQL 语句没有开始和结束的主要内容,如果未能解决你的问题,请参考以下文章

如何在oracle存储过程中执行动态sql语句

Oracle 优化器动态统计(Dynamic Statistics)

Oracle使用dynamic in子句选择查询

Oracle Dynamic Performance Views Version 12.2.0.1

为啥NATIVE FOR ORACLE查询速度慢

Dynamic SQL