Det finns inga enkla plpgsql-baserade lösningar. Några möjliga lösningar:
- Använda
hstore
förlängning.
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
baserad funktion kan vara mycket 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)
- För några år sedan skrev jag ett tillägg pl toolbox
. Det finns 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)
Förmodligen kan du hitta några plpgsql-lösningar baserade på några knep med systemtabeller och arrayer som detta
, men jag kan inte föreslå det. Det är för mindre läsbart och för inte avancerade användare bara svart magi. hstore
är enkelt och nästan överallt så det bör vara att föredra.
På PostgreSQL 9.4 (kanske 9.3) kan du prova svart 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å jag kan skriva 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-baserad funktion borde inte vara fruktansvärt snabb. hstore
borde vara snabbare.