Assign value to a field of rowtype where `field name` is a string

前端 未结 2 1344
遥遥无期
遥遥无期 2021-02-06 13:23

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 hav

相关标签:
2条回答
  • 2021-02-06 13:30

    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

    0 讨论(0)
  • 2021-02-06 13:45

    try this:

    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;
    

    this is because in your EXECUTE IMMEDIATE the tRow MyTable%ROWTYPE is not defined,

    so we defined it with using statement.

    0 讨论(0)
提交回复
热议问题