gpt4 book ai didi

oracle - 在 Oracle PL/SQL 中重用绑定(bind)变量

转载 作者:行者123 更新时间:2023-12-03 15:40:14 25 4
gpt4 key购买 nike

我有一个很重的带有联合的 SQL 语句,其中代码不断被重用。我希望找出是否有一种方法可以重用单个绑定(bind)变量,而无需多次重复该变量以“使用”。

下面的代码返回“并非所有变量都绑定(bind)”,直到我将“USING”行更改为“USING VAR1,VAR2,VAR1;”

我希望避免这种情况,因为我在这两种情况下都提到 :1 - 有什么想法吗?

declare
var1 number :=1;
var2 number :=2;
begin
execute immediate '
select * from user_objects
where
rownum = :1
OR rownum = :2
OR rownum = :1 '
using var1,var2;
end;
/

编辑:有关其他信息,我正在使用动态 SQL,因为我还生成了一系列 where 条件。

我对 SQL 数组不是很好(我在代码中使用了游标,但我认为这会使问题过于复杂),但伪代码是:
v_where varchar2(100) :='';
FOR i in ('CAT','HAT','MAT') LOOP
v_where := v_where || ' OR OBJECT_NAME LIKE ''%' || i.string ||'%''
END;
v_where := ltrim(v_where, ' OR');

然后将上面的 SQL 修改为:
execute immediate '
select * from user_objects
where
rownum = :1
OR rownum = :2
OR rownum = :1 AND ('||V_WHERE||')'
using var1,var2;

最佳答案

您可能会考虑一些选项,尽管它们可能需要更改执行 SQL 语句的方式或 SQL 语句本身。

  • 使用DBMS_SQL而不是 EXECUTE IMMEDIATE -- DBMS_SQL (见 http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_sql.htm )比 EXECUTE IMMEDIATE 更难使用, 但让您可以更好地控制流程——包括(通过 DBMS_SQL.BIND_VARIABLEDBMS_SQL.BIND_ARRAY )按名称而不是按位置绑定(bind)的能力。
  • 使用EXECUTE IMMEDIATEWITH条款 -- 您也许可以重组您的查询以使用 WITH子句在开始时在子查询中收集绑定(bind)变量,然后在需要时加入子查询(而不是直接引用绑定(bind)变量)。它可能看起来像这样

  • with your_parameters as 
    (select :1 as p1, :2 as p2 from dual)
    select *
    from your_table, your_parameters
    where your_table.some_column1 = your_parameters.p1
    and your_table.some_column2 <= your_parameters.p1
    and your_table.some_column3 = your_parameters.p2

    这可能会影响查询的性能,但它可能是一个可以接受的折衷方案。
  • 不要使用动态 SQL -- 当然,如果你不需要动态SQL,你不需要使用EXECUTE IMMEDIATE,所以“仅按位置绑定(bind)”的限制不适用。你确定你真的需要使用动态 SQL 吗?

  • 编辑:如果您使用动态 SQL,因为您有一个可变编号 OR像您在编辑中发布的情况一样,您可以通过执行以下操作之一来避免使用动态 SQL:
  • 如果 OR条件来自表(或查询) -- 加入该表(或查询),而不是使用 OR 的列表标准。例如,如果 CAT、HAT 和 MAT 列在名为 YOUR_CRITERIA 的列中。在名为 YOUR_CRITERIA_TABLE 的表中您可以添加 YOUR_CRITERIA_TABLEFROM子句并替换 OBJECT_NAME LIKE '%CAT% OR OBJECT_NAME LIKE '%MAT% OR OBJECT_NAME LIKE '%HAT% OR OBJECT_NAME LIKE '%MAT%WHERE带有类似 OBJECT_NAME LIKE '%' || YOUR_CRITERIA_TABLE.YOUR_CRITERIA || '%'. 的子句
  • 否则,您可能会将条件放在全局临时表中 -- 如果您的条件不是来自表(或查询),您可以(一次,在设计时,而不是在运行时)创建一个全局临时表来保存它们,然后在运行时将条件插入全局临时表,然后按照第 1 项中的说明加入它。
  • 或者,您可以将条件放在嵌套表中 -- 这类似于第 2 项,除了使用嵌套表(使用 CREATE TYPE...IS TABLE OF 创建的表)而不是全局临时表。您可以创建或拥有嵌套表类型,或使用像 SYS.ODCIVARCHAR2LIST 这样的内置表类型。 .在 PL/SQL 中,您将填充这种类型的变量,然后像第 1 项中的“真实”表一样使用它。

  • 第 3 项的示例可能类似于:
    DECLARE
    tblCriteria SYS.ODCIVARCHAR2LIST;

    BEGIN
    tblCriteria := SYS.ODCIVARCHAR2LIST();

    -- In "real" code you might populate the nested table in a loop.
    -- This example populates it explicitly so that it will compile. For the
    -- purpose of the example, we could have populated the nested table in
    -- a single statement:

    -- tblCriteria := SYS.ODCIVARCHAR2LIST('CAT', 'HAT', 'MAT');

    tblCriteria.EXTEND(1);
    tblCriteria(tblCriteria.LAST) := 'CAT';

    tblCriteria.EXTEND(1);
    tblCriteria(tblCriteria.LAST) := 'HAT';

    tblCriteria.EXTEND(1);
    tblCriteria(tblCriteria.LAST) := 'MAT';

    FOR rec IN
    (
    SELECT
    USER_OBJECTS.*
    FROM
    USER_OBJECTS,
    TABLE(tblCriteria) YOUR_NESTED_TABLE
    WHERE
    USER_OBJECTS.OBJECT_NAME LIKE '%' || YOUR_NESTED_TABLE.COLUMN_VALUE || '%'
    )
    LOOP
    -- Do something. For example, print out the object name.
    DBMS_OUTPUT.PUT_LINE(rec.OBJECT_NAME);
    END LOOP;
    END;

    关于oracle - 在 Oracle PL/SQL 中重用绑定(bind)变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11660564/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com