sql >> Databáze >  >> RDS >> PostgreSQL

PostgreSQL dynamicky upravuje pole v NEW záznamu ve spouštěcí funkci

Neexistují jednoduchá řešení založená na plpgsql. Některá možná řešení:

  1. Pomocí hstore rozšíření.
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 založená funkce může být velmi jednoduchá:

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. Před několika lety jsem napsal rozšíření pl toolbox . Existuje funkce 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)

Pravděpodobně můžete najít nějaká řešení pouze plpgsql založená na některých tricích se systémovými tabulkami a poli jako toto , ale nemohu to navrhnout. Je příliš hůře čitelný a pro méně pokročilé uživatele jen černá magie. hstore je jednoduchý a téměř všude, takže by měl být preferován.

Na PostgreSQL 9.4 (možná 9.3) můžete zkusit černou magii s manipulacemi 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)

Takže jsem schopen napsat funkci:

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)

Funkce založená na JSON by neměla být strašně rychlá. hstore by měl být rychlejší.



  1. mysql extra sloupce se stejným názvem ze dvou tabulek

  2. Jak vyladit výkon SQL Server, Azure SQL Database a Amazon RDS

  3. Cizí znaky/znaky s diakritikou v dotazu SQL

  4. 9 zásadních úkolů, za které jsou odpovědní správci databází