Assign value to a field of rowtype where `field name` is a string
execute-immediate, plsql
Solution
Ok, I solved it !
Short answer : Using a global variable does the trick
Answer Development
Let us consider two facts about dynamic PL/SQL blocks (i.e., PL/SQL blocks written as strings, to be executed trough an `EXECUTE IMMEDIATE` statement)
[1] There is no such thing as variable scope when you create a dynamic PLSQL block. What I mean by that is, if you do something like this :
CREATE OR REPLACE PROCEDURE DynamicVariableAssignment(
theString IN VARCHAR2
)
IS
BEGIN
EXECUTE IMMEDIATE 'BEGIN theString := ''test''; END; ';
END;
it will simply not work because the scope of `theString` is not transfered to the dynamic PL/SQL block. In other words, the dynamic PL/SQL block doesn't "inherit" of any variable, wherever it is executed.
[2] You might say "OK, no panic, I can give input/output arguments to my dynamic PL/SQL block, right ?". Sure you can, but guess what : you can only give SQL types as in/out ! True PL/SQL types on the other hand, such as a `myTable%rowtype`, are not accepted as an input for a dynamic PL/SQL block. So the answer of hmmftg won't work either :
-- 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` is of MyTable%ROWTYPE, it is not a valid SQL type and is therefore not valid as an input to the dynamic PL/SQL block.
The Solution Who would have thought that global variables would come and save the day ? As we said in [1], we have no reference to any variable outside the dynamic PL/SQL block. BUT we can still access global variables defined in package headers !
Let us assume that I have a package `kingPackage` in which I define the following :
tempVariable myTable%ROWTYPE;
Then I can do this :
FINAL CODE (body only)
-- 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;
There you go, fellas ! Have a nice day
Problem
I want to assign a value to a rowtype's field but I don't know how to do it. Suppose that I have a table X inside my database. Suppose also that I have the following variables - `a` ( `X%ROWTYPE` ), representing a row of the table X - `b` ( `VARCHAR2` ), containing a column name of the table X - `c` ( `VARCHAR2` ), containing what I want to store inside a.b What I want to do : something like `a.b := c`. I've come up with something like this : ``` EXECUTE IMMEDIATE 'SELECT '|| c || ' INTO a.' || b || ' FROM DUAL'; ``` Apparently, this isn't the right way to go. I get a ORA-0095: missing keyword error. Can anyone help me with this ? Here is the complete code : ``` 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; ```