PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

PostgreSQL dynamicznie modyfikujący pola w NOWYM rekordzie w funkcji wyzwalacza

Nie ma prostych rozwiązań opartych na plpgsql. Niektóre możliwe rozwiązania:

  1. Korzystanie z hstore rozszerzenie.
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 funkcja może być bardzo prosta:

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. Kilka lat temu napisałem rozszerzenie pl toolbox . Istnieje funkcja 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)

Prawdopodobnie można znaleźć rozwiązania tylko dla plpgsql oparte na kilku sztuczkach z tabelami systemowymi i tablicami, takimi jak to , ale nie mogę tego sugerować. Jest zbyt mało czytelny, a dla niezaawansowanych użytkowników po prostu czarna magia. hstore jest prosty i prawie wszędzie, więc powinien być preferowany.

W PostgreSQL 9.4 (może 9.3) możesz spróbować czarnej magii za pomocą manipulacji JSON:

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)

Więc jestem w stanie napisać funkcję:

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)

Funkcja oparta na JSON nie powinna być strasznie szybka. hstore powinien być szybszy.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL:pętla aż do spełnienia warunku

  2. Jak znaleźć podciągi w SQL (Postgres)

  3. Zainicjuj bazę danych Postgres w Docker Compose

  4. Wywołanie polecenia psql pg_dump w skrypcie wsadowym

  5. Play Nie można połączyć się z bazą danych (PostgreSQL) [domyślnie]