好吧,我解决了!
简短回答:使用全局变量可以解决问题
答案开发
让我们考虑关于动态 PL/SQL 块的两个事实(即,以字符串形式编写的 PL/SQL 块,通过EXECUTE IMMEDIATE
陈述)
[1]创建动态 PLSQL 块时,不存在变量范围之类的东西。我的意思是,如果你做这样的事情:
CREATE OR REPLACE PROCEDURE DynamicVariableAssignment(
theString IN VARCHAR2
)
IS
BEGIN
EXECUTE IMMEDIATE 'BEGIN theString := ''test''; END; ';
END;
它根本行不通,因为范围theString
不传输到动态 PL/SQL 块。换句话说,动态 PL/SQL 块无论在何处执行,都不会“继承”任何变量。
[2]您可能会说“好吧,不用惊慌,我可以为我的动态 PL/SQL 块提供输入/输出参数,对吗?”。当然可以,但你猜怎么着:你只能将 SQL 类型指定为 in/out !另一方面,真正的 PL/SQL 类型,例如myTable%rowtype
、 不被接受作为动态 PL/SQL 块的输入。所以答案是hmmftg也不起作用:
-- I've reduced the code to the interesting part
dynamic_request := 'BEGIN :t_row.' || col_name || ':= 0.001; END;';
EXECUTE IMMEDIATE dynamic_request USING IN OUT tRow;
-- (where tRow is of type myTable%ROWTYPE)
since tRow
属于 MyTable%ROWTYPE,它不是有效的 SQL 类型,因此作为动态 PL/SQL 块的输入无效。
解决方案谁会想到全局变量会来拯救世界呢?正如我们在[1],我们没有引用动态 PL/SQL 块之外的任何变量。但我们仍然可以访问包头中定义的全局变量!
假设我有一个包裹kingPackage
我在其中定义了以下内容:
tempVariable myTable%ROWTYPE;
然后我可以这样做:
最终代码(仅主体)
-- Copy tRow into temp variable
kingPackage.tempVariable := tRow;
-- We modify the column of the temp variable
vString := 'BEGIN kingPackage.tempVariable.' || col_val || ' := ' || TO_CHAR(vNumber) ||'; END;';
EXECUTE IMMEDIATE vString;
-- The column value has been updated \o/
tRow := kingPackage.tempVariable;
好了,伙计们!
祝你今天过得愉快