Oracle EXECUTE IMMEDIATE 可能具有可变数量的绑定吗?
我需要在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您无法使用
EXECUTE IMMEDIATE
来执行此操作。 不过,您可以使用 Oracle 的DBMS_SQL
包来完成此操作。 数据库应用程序开发人员指南您熟悉的EXECUTE IMMEDIATE
和dbms_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'sDBMS_SQL
package. The Database Application Developer's Guide has a comparison between theEXECUTE IMMEDIATE
you're familiar with anddbms_sql
methods. This page documentsDBMS_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
.您还可以使用
WITH
语句来解决此问题。 一般来说,使用 DBMS_SQL 更好,但有时这是一种更简单的方法:You could also work around this problem by using a
WITH
statement. Generally usingDBMS_SQL
is better, but sometimes this is a simpler way:这个
在您的情况下,如果您想传递一个参数或不传递一个参数,您可以构建两个具有单个参数的查询,并且在其中一个查询中不使用它(即谓词始终为真),如下所示:
您可以优化谓词这样优化器就会明白它总是正确的。
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:
You can probably refine the predicate so that the optimizer will understand that it is always true.
事实上,几天前我也遇到了同样的问题,一位朋友与我分享了一种使用
EXECUTE IMMEDIATE
来实现这一点的方法。它涉及生成 PLSQL 块而不是 SQL 块本身。 当将 EXECUTE IMMEDIATE 与 PLSQL 代码块一起使用时,您可以按名称绑定变量,而不仅仅是按位置。
查看我的示例/代码以及我自己的类似问题/答案线程:
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:
人们可以像 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 adbms_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 bedbms_sql
cursor.So what kind of client will be consuming this cursor?