UPDATE a whole row in PL/pgSQL

前端 未结 3 1905
南旧
南旧 2021-01-19 06:33

I have plpgsql function:

CREATE OR REPLACE FUNCTION test() RETURNS VOID AS
$$
DECLARE
    my_row my_table%ROWTYPE;
BEGIN
    SELECT * INTO my_row FROM my_tab         


        
相关标签:
3条回答
  • 2021-01-19 07:02

    I would like to know if it's possible to directly update "my_row" record.

    It is.
    You can update columns of a row or record type in plpgsql - just like you have it. It should be working, obviously?

    This would update the underlying table, of course, not the variable!

    UPDATE my_table SET date=now() WHERE id='1';
    

    You are confusing two things here ...


    Answer to clarification in comment

    I don't think there is syntax in PostgreSQL that can UPDATE a whole row. You can UPDATE a column list, though. Consider this demo:

    Note how I use thedate instead of date as column name, date is a reserved word in every SQL standard and a type name in PostgreSQL.

    CREATE TEMP TABLE my_table (id serial, thedate date);
    INSERT INTO my_table(thedate) VALUES (now());
    
    CREATE OR REPLACE FUNCTION test_up()
      RETURNS void LANGUAGE plpgsql AS
    $func$
    DECLARE
        _r my_table;
    BEGIN
       SELECT * INTO _r FROM my_table WHERE id = 1;
       _r.thedate := now()::date + 5 ;
    
       UPDATE my_table t
        -- explicit list of columns to be to updated
       SET   (id, thedate) = (_r.id, _r.thedate)
       WHERE  t.id = 1;
    END
    $func$;
    
    SELECT test_up();
    SELECT * FROM my_table;
    

    However, you can INSERT a whole row easily. Just don't supply a column list for the table (which you normally should, but in this case it is perfectly ok, not to).

    As an UPDATE is internally a DELETE followed by an INSERT anyway, and a function automatically encapsulates everything in a transaction, I don't see, why you couldn't use this instead:

    CREATE OR REPLACE FUNCTION x.test_ delins()
      RETURNS void LANGUAGE plpgsql AS
    $func$
    DECLARE
        _r my_table;
    BEGIN
       SELECT * INTO _r
       FROM my_table WHERE id = 1;
       _r.thedate := now()::date + 10;
    
       DELETE FROM my_table t WHERE t.id = 1;
       INSERT INTO my_table SELECT _r.*;
    END
    $func$;
    
    0 讨论(0)
  • 2021-01-19 07:05

    I managed to get this working in PLPGSQL in a couple of lines of code.

    Given a table called table in a schema called example, and a record of the same type declared as _record, you can update all the columns in the table to match the record using the following hack:

    declare _record example.table;
    
    ...
    
    -- get the columns in the correct order, as a string
    select string_agg(format('%I', column_name), ',' order by ordinal_position)
      into _columns
      from information_schema.columns
      where table_schema='example' and table_name='table';
    
    execute 'update example.table set (' || _columns || ') = row($1.*) where pkey=$2'
      using _record, _record.pkey;
    

    In the above example, of course, _record.pkey is the table's primary key.

    0 讨论(0)
  • 2021-01-19 07:10

    yes, its possible to update / append the row-type variable,

    CREATE OR REPLACE FUNCTION test() RETURNS VOID AS $$
    DECLARE    
             my_row my_table%ROWTYPE;
    BEGIN
             SELECT * INTO my_row FROM my_table WHERE id='1';
             my_row.date := now(); 
             raise notice  'date  : %; ',my_row.date;
    END;
    $$ LANGUAGE plpgsql;
    

    here the raise notice will display the today's date only.

    but this will not update the column date in my_table.

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