好的,我解决了!
简短回答:使用全局变量可以解决问题
答案发展
让我们考虑关于动态 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 类型,例如 a 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)
因为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;
给你,伙计们!祝你今天过得愉快