Oracle EXECUTE IMMEDIATE 可能具有可变数量的绑定吗?

发布于 2024-07-24 01:58:24 字数 352 浏览 9 评论 0原文

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

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

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

我尝试了类似的方法

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

,但它返回了ORA-01008:并非所有变量都已绑定。

I need to use dynamic SQL execution on Oracle where I do not know the exact number of bind variables used in the SQL before runtime.

Is there a way to use a variable number of bind variables in the call to EXECUTE IMMEDIATE somehow?

More specifically, I need to pass one parameter into the unknown SQL but I do not know how often it will be used there.

I tried something like

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

But it threw back with ORA-01008: not all variables bound.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

牛↙奶布丁 2024-07-31 01:58:24

您无法使用 EXECUTE IMMEDIATE 来执行此操作。 不过,您可以使用 Oracle 的 DBMS_SQL 包来完成此操作。 数据库应用程序开发人员指南您熟悉的 EXECUTE IMMEDIATEdbms_sql 方法之间的比较。 此页面文档DBMS_SQL,但有一些示例(上面链接)可以帮助您入门(示例 1 是运行可能具有任意数量的绑定变量的语句的简单情况)。 从编码的角度来看,DBMS_SQL 要麻烦得多,但它可以让您做任何您能想到的事情。

允许在 SQL 中出现绑定变量的多个实例。 但是,您必须知道用作绑定变量的名称(例如,在您的情况下为 :var),才能将其传递到 DBMS_SQL.BIND_VARIABLE 中。

You can't do this with EXECUTE IMMEDIATE. However, you can do this by using Oracle's DBMS_SQL package. The Database Application Developer's Guide has a comparison between the EXECUTE IMMEDIATE you're familiar with and dbms_sql methods. This page documents DBMS_SQL, but has some examples (linked above) that should get you started (example 1 is a simple case of running a statement that could have an arbitrary number of bind variables). DBMS_SQL is a lot more cumbersome from a coding perspective, but it will allow you to do just about anything you can conceive.

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.

你没皮卡萌 2024-07-31 01:58:24

您还可以使用 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;

You could also work around this problem by using a WITH statement. Generally using DBMS_SQL is better, but sometimes this is a simpler way:

BEGIN
    EXECUTE IMMEDIATE 'WITH var AS (SELECT :var FROM dual) SELECT SYSDATE FROM DUAL WHERE (SELECT * FROM var) = (SELECT * FROM var)' USING 1;
END;
∞觅青森が 2024-07-31 01:58:24

这个

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

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

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

您可以优化谓词这样优化器就会明白它总是正确的。

This Thread on AskTom covers the subject in details.

In your case if you want to pass one parameter or none, you could build two queries that have a single parameter and in one of these query it is not used (i-e the predicate is always true) like this:

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

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

You can probably refine the predicate so that the optimizer will understand that it is always true.

笑脸一如从前 2024-07-31 01:58:24

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

事实上,几天前我也遇到了同样的问题,一位朋友与我分享了一种使用 EXECUTE IMMEDIATE 来实现这一点的方法。

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

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

More specifically, I need to pass one parameter into the unknown SQL but I do not know how often it will be used there.

I actually ran into this exact same issue a couple of days ago, and a friend shared with me a way to do exactly that with EXECUTE IMMEDIATE.

It involves generating a PLSQL block as opposed to the SQL block itself. When using EXECUTE IMMEDIATE with a block of PLSQL code, you can bind variables by name as opposed to just by position.

Check out my example/code and on my own similar question/answer thread:

远昼 2024-07-31 01:58:24

人们可以像 Steve Broberg 解释的那样使用 dbms_sql ,但生成的游标无法在许多客户端中使用(读取)。 Oracle 11增加了转换函数(dbms_sql .to_refcursor),使得可以将 dbms_sql 游标转换为引用游标,但由于某种原因,人们无法在 .Net 应用程序中使用此转换后的引用游标。 人们可以使用 .net 中的普通引用游标,但不能使用曾经是 dbms_sql 游标的引用游标。

那么什么样的客户端会使用这个游标呢?

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?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文