5

我想为行类型的字段分配一个值,但我不知道该怎么做。

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

还假设我有以下变量

  • a ( X%ROWTYPE),代表表 X 的一行
  • b ( VARCHAR2 ),包含表 X 的列名
  • c ( VARCHAR2 ),包含我要存储在 ab 中的内容

我想做的事:类似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;
4

2 回答 2

3

好的,我解决了!

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

答案发展

让我们考虑关于动态 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;

给你,伙计们!祝你今天过得愉快

于 2014-02-07T12:36:57.230 回答
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的 thetRow MyTable%ROWTYPE中没有定义,

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

于 2014-02-07T02:07:23.800 回答