sql >> Database teknologi >  >> RDS >> PostgreSQL

PostgreSQL ændrer felter dynamisk i NEW record i en triggerfunktion

Der er ikke simple plpgsql-baserede løsninger. Nogle mulige løsninger:

  1. Brug af hstore udvidelse.
CREATE TYPE footype AS (a int, b int, c int);

postgres=# select row(10,20,30);
    row     
------------
 (10,20,30)
(1 row)

postgres=# select row(10,20,30)::footype #= 'b=>100';
  ?column?   
-------------
 (10,100,30)
(1 row)

hstore baseret funktion kan være meget enkel:

create or replace function update_fields(r anyelement,
                                         variadic changes text[])
returns anyelement as $$
select $1 #= hstore($2);
$$ language sql;

postgres=# select * 
             from update_fields(row(10,20,30)::footype, 
                                'b', '1000', 'c', '800');
 a  |  b   |  c  
----+------+-----
 10 | 1000 | 800
(1 row)
  1. For nogle år siden skrev jeg en udvidelse pl værktøjskasse . Der er en funktion record_set_fields :
pavel=# select * from pst.record_expand(pst.record_set_fields(row(10,20),'f1',33));
 name | value |   typ   
------+-------+---------
 f1   | 33    | integer
 f2   | 20    | integer
(2 rows)

Sandsynligvis kan du finde nogle plpgsql only-løsninger baseret på nogle tricks med systemtabeller og arrays som dette , men jeg kan ikke foreslå det. Det er for mindre læsbart og for ikke avancerede brugere kun sort magi. hstore er enkel og næsten overalt, så det bør foretrækkes.

På PostgreSQL 9.4 (måske 9.3) kan du prøve at lave sort magi med JSON-manipulationer:

postgres=# select json_populate_record(NULL::footype, jo) 
              from (select json_object(array_agg(key),
                                       array_agg(case key when 'b' 
                                                          then 1000::text
                                                          else value 
                                                 end)) jo
       from json_each_text(row_to_json(row(10,20,30)::footype))) x;
 json_populate_record 
----------------------
 (10,1000,30)
(1 row)

Så jeg er i stand til at skrive funktion:

CREATE OR REPLACE FUNCTION public.update_field(r anyelement, 
                                               fn text, val text, 
                                               OUT result anyelement)
 RETURNS anyelement
 LANGUAGE plpgsql
AS $function$
declare jo json;
begin
  jo := (select json_object(array_agg(key), 
                            array_agg(case key when 'b' then val
                                               else value end)) 
            from json_each_text(row_to_json(r)));
  result := json_populate_record(r, jo);
end;
$function$

postgres=# select * from update_field(row(10,20,30)::footype, 'b', '1000');
 a  |  b   | c  
----+------+----
 10 | 1000 | 30
(1 row)

JSON-baseret funktion burde ikke være forfærdelig hurtig. hstore burde være hurtigere.



  1. Hvordan taber man mange (men ikke alle) borde i ét hug?

  2. Hvordan skriver/opdaterer man Oracle blob på en pålidelig måde?

  3. Hvordan overføres tabelværdiparametre fra Java til sql server lagret procedure?

  4. Gruppering efter dato, med 0, når count() ikke giver nogen linjer