sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL-velden dynamisch wijzigen in NIEUW record in een triggerfunctie

Er zijn geen simpele op plpgsql gebaseerde oplossingen. Enkele mogelijke oplossingen:

  1. Gebruik hstore extensie.
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 gebaseerde functie kan heel eenvoudig zijn:

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. Enkele jaren geleden schreef ik een extensie pl toolbox . Er is een functie 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)

Waarschijnlijk kun je enkele plpgsql-oplossingen vinden op basis van enkele trucs met systeemtabellen en arrays zoals dit , maar ik kan het niet aanraden. Het is te minder leesbaar en voor niet gevorderde gebruikers alleen maar zwarte magie. hstore is eenvoudig en bijna overal, dus het zou de voorkeur moeten hebben.

Op PostgreSQL 9.4 (misschien 9.3) kun je zwarte magie proberen met JSON-manipulaties:

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)

Dus ik kan een functie schrijven:

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)

Op JSON gebaseerde functie zou niet verschrikkelijk snel moeten zijn. hstore zou sneller moeten zijn.



  1. Splits één kolom in meerdere kolommen, maar de gegevens zullen variëren SQL

  2. Geautomatiseerd testen van het upgradeproces voor MySQL/MariaDB/Percona Server

  3. MySQL RAND() hoe vaak kan het worden gebruikt? gebruikt het /dev/random?

  4. Hoe vind je rijen>kolommencombinaties met Cross Join? [SQL]