【问题标题】:Unable to parse bind variables in Execute Immediate inside FORALL无法在 FORALL 内的 Execute Immediate 中解析绑定变量
【发布时间】:2020-08-13 14:50:54
【问题描述】:

我有一个 PL/SQL 过程,它使用 For 循环 并插入大约 5000 条记录。

我正在尝试使用 FORALL,因为我遇到了 For 循环 的性能问题。

我正在传递表名、序列 ID、列名列表(I_columnnames 作为逗号分隔的字符串)、列数据类型(作为逗号分隔的字符串)、多记录级别数据(作为逗号分隔的字符串)

I_columnnames 将有多个列名(每次执行的列数不同) 我已根据一个集合 v_tab 中的相应数据类型格式化每个记录级别数据(例如。'REC01',1500,100,100,TO_TIMESTAMP('2019-10-10','YYYY- MM-DD HH:MM:SS.FF3'))

现在,我必须在这个动态表中插入记录级数据,为此我使用 FORALL 语句并立即执行如下:

FORALL i IN v_tab.first .. v_tab.last 
   
EXECUTE IMMEDIATE 'INSERT INTO ' ||I_tablename||'  (BLCK_ID, SEQ_ID, '||I_columnnames|| ')
   values ('''|| I_blckid||''' ,'||I_sequence||' ,'||':1'||')' using v_tab(i);

但我收到 ORA - no enough values 错误,因为绑定变量:1 已被视为单个字符串(尽管它有多个逗号分隔值)

请帮忙。

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    :1 是包含逗号分隔值的单个字符串,它不会扩展到所有单个元素。

    如您所见,改为连接字符串:

    ...I_sequence||' ,'|| v_tab(i) ||')';
    

    得到“PLS-00435:没有 BULK In-BIND 的 DML 语句不能在 FORALL 中使用”。

    您仍然可以连接字符串,但在普通的for 循环中而不是forall:

    for i in v_tab.first .. v_tab.last loop
      execute immediate 'INSERT INTO ' ||i_tablename||' (BLCK_ID, SEQ_ID, '||i_columnnames|| ')'
          || ' values ('''|| i_blckid||''' ,'||i_sequence||' ,' || v_tab(i) || ')';
    end loop;
    

    假设您的 CSV 字符串中包含适当的引号并进行任何必要的转换,这似乎是这种情况 - 尽管您的示例无效 - 从 SQL 注入的角度来看这是有风险的。

    db<>fiddle

    您可以查看dbms_sql 而不是execute immediate,但我认为它不会带来太大的改进。您最好重新审视一下构建v_tab 的方式和原因。您还可以在现有的块中使用动态 PL/SQL 块,通过操作字符串构建;但是只有 5000 行,简单循环的任何速度或效率增益可能都不值得。但它可以避免 SQL 注入问题。

    【讨论】:

    • 这不起作用,因为它在 FORALL 中。它抛出错误 --> 错误:PLS-00435: DML statement without BULK In-BIND cannot be used inside FORALL
    • 好吧,反正这不是一个好主意,就像我说的那样。你需要重新考虑这一点。如果您编辑问题以解释如何填充参数(v_tab 等),那么我们可能会提出更好的处理方式。或者提出一个新问题,提供所有必要的信息。
    • 我添加了一个示例,说明如何按照您的建议填充 v_tab。
    • 如果您想展示您是如何解决问题的,如果您认为它对其他人有用,您可以添加(并接受)您自己的答案。
    【解决方案2】:

    FORALL 内的EXECUTE IMMEDIATE 不起作用,因为绑定变量与动态列。

    使用INSERT ALL 代替传统的INSERT 效果很好并提高了性能。

    【讨论】:

      猜你喜欢
      • 2023-03-18
      • 2010-11-03
      • 1970-01-01
      • 1970-01-01
      • 2011-07-12
      • 2021-12-17
      • 1970-01-01
      • 2021-04-15
      相关资源
      最近更新 更多