sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLがトリガー関数のNEWレコードのフィールドを動的に変更する

    単純なplpgsqlベースのソリューションはありません。考えられる解決策:

    1. hstoreを使用する 拡張機能。
    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 ベースの関数は非常に単純です:

    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. 数年前、拡張機能plツールボックス を作成しました。 。関数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)
    

    おそらく、これ 、しかし私はそれを提案することはできません。それはあまりにも読みにくく、上級ユーザーにとっては黒魔術だけです。 hstore シンプルでほとんどどこにでもあるので、好ましい方法です。

    PostgreSQL 9.4(おそらく9.3)では、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)
    

    だから私は関数を書くことができます:

    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ベースの関数はひどい速さであってはなりません。 hstore もっと速くする必要があります。



    1. SQL Serverのマルチステートメントテーブル値関数(MSTVF)の概要

    2. SQLServerクエリでNULLを0に置き換える

    3. パラメータをmysqlに渡す方法

    4. OracleDBに接続するときにdbplyrを介してEXTRACTを使用する方法