无法在立即执行中调用函数(存储在批量收集中)

Posted

技术标签:

【中文标题】无法在立即执行中调用函数(存储在批量收集中)【英文标题】:Unable to call functions (stored in bulk collect) in execute immediate 【发布时间】:2015-09-29 03:11:08 【问题描述】:

我有一列(USING_FUNCTION) 函数名称,例如 GET_FUNCTION(#value#) 和另一列 (VALUE),其中包含要使用的值

我正在尝试使用以下方法将函数名称和值集中到批量运算符中:

Select (substr(using_function, 1, instr(using_function, '(', -1) -1)) 
        || '(' || value || ')' 
bulk collect into V_value 
from table1 
where using_function != 'N';

然后使用 execute immediate 调用该函数(例如 Executing GET_WEEK_DATE(-2) 将给我 16-SEP-2015 ),然后将其插入另一个表(table2):

Execute immediate ' insert into table2 (name,value) select name, '
      || V_value ||' from table1 where using_function != ''N''';

我收到一个错误:调用“||”时参数的数量或类型错误。

*ps 我避免使用循环

【问题讨论】:

请检查USING_FUNCTION列中的函数所需要的参数是否与传给它的值一致。例如,如果函数是 mod(),并且该函数需要 2 个参数,如果 VALUE 列中包含的值小于 2,则会导致错误。 感谢您的建议 :) 但是 USING_FUNCTION 列中的函数并不一致,它只需要 1 个参数 请解释为什么要避免使用循环。从table1 以及生成的语句使用的表中发布函数调用和值的真实示例数据 您以错误的方式引用 V_value。它是一个集合,因此您必须将其称为 V_value(index) 而不是单独称为 V_value。如果您不想使用循环的原因是因为它会减慢您的程序,那么forall 是您的选择。它以“批量”的方式插入您的数据,而不是逐行插入,这使其速度更快。 :) 尝试添加另一个将执行该函数的查询,因为第一个查询只是将其按原样保存在数据库中。 【参考方案1】:

PLS-00306 是编译错误。您使用|| 连接运算符的方式存在问题。错误消息包括行号,这将允许您确定哪一行是错误的,但这可能是罪魁祸首:|| V_value ||

这是无效的,因为V_value 是一个集合。连接需要一个标量变量。如果您定义了引用索引的循环将解决编译错误:|| V_value(idx) ||

【讨论】:

【参考方案2】:

如果您不想使用循环,则可以使用FORALL(不是循环),这是批量收集的完美组合。我假设您的 V_value 变量是 varchar2 的集合。也许您可以将其声明为记录集合?在您的声明部分,添加以下行:

           TYPE myrecord is RECORD(name table1.name%TYPE,
                                   value table1.VALUE%TYPE);
           TYPE tableofrecords is table of myrecord index by pls_integer;
           V_value tableofrecords;

然后在你的块的主体内,你可以把这些行:

          Select name,(substr(using_function, 1, instr(using_function, '(', -1) -1)) 
    || '(' || value || ')' 
        bulk collect into V_value 
        from table1 
        where using_function != 'N';
        forall a in 1..v_value.count
             insert into table2 (name,value) values (v_value(a).name,v_value(a).value);

【讨论】:

您好,通过使用 FORALL,我似乎无法在将其插入表之前执行该函数。如果调用 GET_FUNCTION(-3),它只会在列中插入 'GET_FUNCTION(-3)' 而不是 '20'。 你是对的,如果你要使用forall,你就不能执行你的函数。如果要在将函数插入表之前执行该函数,则必须循环遍历它。这指出,如果不使用任何循环,您将无法在此处实现您想要实现的目标。如果您能指出为什么要避免使用循环,也许我们可以进一步帮助您.. 它会,但它在你的情况下是不可避免的。如果这是您的原因,dbms_parallel_execute 可能会对您有所帮助。 Here's 让你开始了解它的东西【参考方案3】:

尝试添加此块。它将执行存储在 v_value 中的函数

execute immediate 'select '||v_value||' from dual ' into new_v_value

注意:new_v_value 应该是数组类型。

【讨论】:

以上是关于无法在立即执行中调用函数(存储在批量收集中)的主要内容,如果未能解决你的问题,请参考以下文章

如何实现一个批量获取数据的dataloader,合并多个操作

立即执行中的批量收集限制

如何在 PLSQL 中存储立即执行的结果?

立即执行批量收集限制

Javascript 自动执行函数(立即调用函数)

LR静态存储/动态存储/指针变量脚本说明