将值赋给rowtype字段,其中`field name`是一个字符串

时间:2014-02-06 15:39:39

标签: plsql execute-immediate

我想为rowtype的字段赋值,但我不知道该怎么做。

假设我的数据库中有一个表 X

假设我还有以下变量

  • aX%ROWTYPE),代表表格X的一行
  • bVARCHAR2),包含表格X的列名称
  • cVARCHAR2),包含我要存储在a.b中的内容

我想做什么:类似a.b := c

我想出了类似的东西:

EXECUTE IMMEDIATE 'SELECT '|| c || ' INTO a.' || b || ' FROM DUAL';

显然,这不是正确的方法。我收到 ORA-0095:缺少关键字错误。

任何人都可以帮我吗?

以下是完整的代码:

DECLARE
    tRow            MyTable%ROWTYPE;
    col_name        VARCHAR(10) := 'Length';
    nValue          NUMBER(12,4) := 0.001;
    dynamic_request VARCHAR(300);
BEGIN 
    dynamic_request := 'SELECT '|| nValue || ' INTO tRow.' || col_name || ' FROM DUAL';
    EXECUTE IMMEDIATE dynamic_request;
END;

2 个答案:

答案 0 :(得分:2)

好的,我解决了!

简答:使用全局变量可以解决问题

回答开发

让我们考虑两个关于动态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类型!另一方面,真正的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)

由于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;

你去,伙计们! 祝你有愉快的一天

答案 1 :(得分:1)

试试这个:

CREATE OR REPLACE PROCEDURE ROW_CHANGER(
    tRow            IN MyTable%ROWTYPE,
    col_name        IN VARCHAR,
    nValue          IN NUMBER) 
   AS
    dynamic_request VARCHAR(300);
BEGIN 
    dynamic_request := 'BEGIN  :t_row.'||COL_NAME ||':= :n_value; END;';
    EXECUTE IMMEDIATE dynamic_request
         USING IN OUT  TROW, IN nValue;
END;

这是因为在EXECUTE IMMEDIATE tRow MyTable%ROWTYPE未定义,

所以我们用using语句定义它。