PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

PostgreSQL sửa đổi động các trường trong bản ghi MỚI trong một hàm kích hoạt

Không có giải pháp dựa trên plpgsql đơn giản. Một số giải pháp khả thi:

  1. Sử dụng hstore phần mở rộng.
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 hàm dựa có thể rất đơn giản:

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. Vài năm trước, tôi đã viết một tiện ích mở rộng hộp công cụ pl . Có một hàm 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)

Có thể bạn có thể tìm thấy một số giải pháp chỉ plpgsql dựa trên một số thủ thuật với các bảng và mảng hệ thống như cái này , nhưng tôi không thể đề xuất nó. Nó quá khó đọc và đối với những người dùng không chuyên sâu thì chỉ có ma thuật đen. hstore rất đơn giản và hầu như ở mọi nơi, vì vậy nó nên được ưu tiên hơn.

Trên PostgreSQL 9.4 (có thể là 9.3), bạn có thể thử sử dụng phép thuật đen với các thao tác 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)

Vì vậy, tôi có thể viết hàm:

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)

Chức năng dựa trên JSON không được nhanh khủng khiếp. hstore sẽ nhanh hơn.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách cho phép truy cập từ xa vào cơ sở dữ liệu PostgreSQL

  2. psycopg2 không thể tìm thấy bất kỳ bảng nào sau khi kết nối

  3. Tắt kết nối gộp trong Rails để sử dụng PgBouncer

  4. Phần 2:Cách lấy Tổng của một truy vấn dựa trên phân vùng mà không thực sự xoay vòng

  5. Cách hiểu một PHÂN TÍCH GIẢI THÍCH