【问题标题】:Oracle EXECUTE IMMEDIATE with variable number of binds possible?Oracle EXECUTE IMMEDIATE 可以绑定可变数量吗?
【发布时间】:2010-11-03 17:19:19
【问题描述】:

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

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

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

我尝试了类似的东西

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

但它以ORA-01008: not all variables bound. 退回

【问题讨论】:

标签: oracle plsql dynamic-sql


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 这是我最喜欢的答案。我会命名它,例如with vars as ( select :1 v_surname, :2 v_forename from dual ) select person_id from people where surname = (select v_surname from vars) and forename = (select v_forename from vars)
    【解决方案3】:

    Thread on AskTom 详细介绍了该主题。

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

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

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

    【讨论】:

    • 问题在于传入的SELECT语句是未知的,除了一个参数(一个ID)至少使用了一次甚至多次。绑定的数量未知。
    • 如果参数个数未知,则必须使用dbms_sql
    【解决方案4】:

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

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

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

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • 后续PL/SQL中会用到,所以客户端没问题。
      猜你喜欢
      • 2019-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-10
      • 2015-07-18
      相关资源
      最近更新 更多