11

我需要在 Oracle 上使用动态 SQL 执行,我不知道运行前 SQL 中使用的绑定变量的确切数量。

有没有办法在调用中以某种方式使用可变数量的绑定变量EXECUTE IMMEDIATE

更具体地说,我需要将一个参数传递给未知的 SQL,但我不知道它在那里使用的频率。

我尝试了类似的东西

EXECUTE IMMEDIATE 'SELECT SYSDATE FROM DUAL WHERE :var = :var' USING 1;

但它与ORA-01008: not all variables bound.

4

5 回答 5

10

你不能用EXECUTE IMMEDIATE. 但是,您可以使用 Oracle 的DBMS_SQL包来执行此操作。Database Application Developer's GuideEXECUTE IMMEDIATE您熟悉的方法和方法进行了比较dbms_sql此页面文档DBMS_SQL,但有一些示例(上面链接)可以帮助您入门(示例 1 是运行可能具有任意数量绑定变量的语句的简单案例)。 DBMS_SQL从编码的角度来看,这要麻烦得多,但它可以让你做任何你能想到的事情。

Multiple instances of the bind variable occurring in the SQL are allowed. However, you will have to know the name being used as the bind variable (e.g. :var in your case) in order to pass it into DBMS_SQL.BIND_VARIABLE.

于 2009-06-17T19:52:31.833 回答
7

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;
于 2009-08-07T14:36:23.337 回答
2

AskTom 上的此主题详细介绍了该主题。

在您的情况下,如果您想传递一个参数或不传递一个参数,您可以构建两个具有单个参数的查询,并且在其中一个查询中不使用它(即谓词始终为真),如下所示:

-- query1
SELECT * FROM DUAL WHERE dummy = :x;

-- query2
SELECT * FROM DUAL WHERE nvl(:x, 1) IS NOT NULL;

您可能可以改进谓词,以便优化器了解它始终为真。

于 2009-06-17T16:03:50.877 回答
1

One can use dbms_sql like Steve Broberg explained but the resulting cursor can't be consumed (read) in a lot of clients. Oracle 11 has added a conversion function (dbms_sql.to_refcursor) that makes it possible to convert a dbms_sql cursor to a ref cursor but for some reason one can't consume this converted ref cursor in a .Net application. One can consume a normal ref cursor in .net but not a ref cursor that used to be dbms_sql cursor.

So what kind of client will be consuming this cursor?

于 2009-06-18T06:52:05.447 回答
1

更具体地说,我需要将一个参数传递给未知的 SQL,但我不知道它在那里使用的频率。

几天前我实际上遇到了同样的问题,一位朋友与我分享了一种使用EXECUTE IMMEDIATE.

它涉及生成 PLSQL 块而不是 SQL 块本身。当EXECUTE IMMEDIATE与 PLSQL 代码块一起使用时,您可以按名称绑定变量,而不仅仅是按位置。

查看我的示例/代码和我自己的类似问题/答案线程:

于 2011-05-18T20:58:37.670 回答