Oracle EXECUTE IMMEDIATE 可能具有可变数量的绑定吗?
-
06-07-2019 - |
题
我需要在 Oracle 上使用动态 SQL 执行,但我不知道运行前 SQL 中使用的绑定变量的确切数量。
有没有办法在调用中使用可变数量的绑定变量 EXECUTE IMMEDIATE
不知何故?
更具体地说,我需要通过 一 参数进入未知的SQL,但我不知道它在那里会被使用多久。
我尝试过类似的东西
EXECUTE IMMEDIATE 'SELECT SYSDATE FROM DUAL WHERE :var = :var' USING 1;
但它又回来了 ORA-01008: not all variables bound.
解决方案
您无法使用 EXECUTE IMMEDIATE
执行此操作。但是,您可以使用Oracle的 DBMS_SQL
包来完成此操作。 数据库应用程序开发人员指南包含您熟悉的 EXECUTE IMMEDIATE
和 dbms_sql
方法之间的比较。 此页文档 DBMS_SQL
,但有一些例子(上面已链接)应该让你入门(例1是运行一个可能有任意数量绑定变量的语句的简单例子)。从编码的角度来看, DBMS_SQL
更加麻烦,但它可以让你做任何你能想到的事情。
允许在SQL中出现多个绑定变量实例。但是,您必须知道用作绑定变量的名称(例如:在您的情况下为var),以便将其传递到 DBMS_SQL.BIND_VARIABLE
。
其他提示
您还可以使用 WITH
语句解决此问题。通常使用 DBMS_SQL
更好,但有时这是一种更简单的方法:
BEGIN
EXECUTE IMMEDIATE 'WITH var AS (SELECT :var FROM dual) SELECT SYSDATE FROM DUAL WHERE (SELECT * FROM var) = (SELECT * FROM var)' USING 1;
END;
这 AskTom上的线程详细介绍了这个主题。
在您的情况下,如果您想传递一个参数或者没有传递,您可以构建两个具有单个参数的查询,并且在其中一个查询中不使用它(即谓词始终为true),如下所示:
-- query1
SELECT * FROM DUAL WHERE dummy = :x;
-- query2
SELECT * FROM DUAL WHERE nvl(:x, 1) IS NOT NULL;
您可以优化谓词,以便优化器能够理解它始终是真的。
更具体地说,我需要将一个参数传递给未知的 SQL,但我不知道该参数在那里使用的频率。
事实上,几天前我遇到了同样的问题,一位朋友与我分享了一种方法来做到这一点 EXECUTE IMMEDIATE
.
它涉及生成 PLSQL 块而不是 SQL 块本身。使用时 EXECUTE IMMEDIATE
使用 PLSQL 代码块,您可以按名称绑定变量,而不仅仅是按位置。
查看我的示例/代码以及我自己的类似问题/答案线程:
可以像Steve Broberg一样使用 dbms_sql
,但是很多客户端都无法使用(读取)生成的游标。 Oracle 11添加了转换功能( dbms_sql .to_refcursor
)可以将 dbms_sql
游标转换为引用游标,但由于某种原因,不能在.Net应用程序中使用这个转换后的引用游标。可以在.net中使用正常的引用游标,但不能使用曾经是 dbms_sql
游标的引用游标。
那么什么样的客户端会消耗这个游标?