【问题标题】:Assign value to a field of rowtype where `field name` is a string为“字段名称”为字符串的行类型字段赋值
【发布时间】:2014-02-06 15:39:38
【问题描述】:

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

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

还假设我有以下变量

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

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

我想出了这样的东西:

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

显然,这不是正确的方法。我收到 ORA-0095: missing keyword 错误。

谁能帮我解决这个问题?

这是完整的代码:

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;

【问题讨论】:

  • 你为什么要使用立即执行?那是行不通的。
  • 你有什么建议?
  • 请提供更多关于您尝试做什么的背景信息。 PL/SQL 代码的其余部分在哪里?
  • 抱歉,原帖已编辑。
  • 抱歉,仍然不确定您要做什么。只需使用“trow.length := nValue;”动态地对变量进行赋值的目的是什么?你已经有右手边的价值了吗?祝你好运。

标签: plsql execute-immediate


【解决方案1】:

好的,我解决了!

简答:使用全局变量就可以了

答案开发

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

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

你们去吧,伙计们! 祝你有美好的一天

【讨论】:

    【解决方案2】:

    试试这个:

    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 声明来定义它。

    【讨论】:

    • 请说明您的代码的作用以及它如何回答问题。如果您得到一个代码 sn-p 作为答案,您可能不知道如何处理它。答案应为 OP 提供有关如何调试和解决问题的指导。指出您的代码背后的想法是什么,对理解问题以及应用或修改您的解决方案有很大帮助。
    • 我觉得这不起作用,我收到“PLS-00457:表达式必须是 SQL 类型”错误
    • 好吧,事实上USING IN参数只能是SQL类型的。由于TROWROWTYPE,因此不接受这种技术。
    猜你喜欢
    • 2015-07-23
    • 2013-02-12
    • 2016-02-06
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    相关资源
    最近更新 更多