使用从 Postgres 中其他列收集的值创建一个 JSONB 列

问题描述

@H_502_0@我有一个类似 Postgres 的表

 UserID   EmailFlag    PrintFlag SomeOtherField
 12       1            0         yes
 34       0            1         somecomment
@H_502_0@为了优化 sql 查询,我想像这样使用 JSONB 派生列:

 UserID   EmailFlag    PrintFlag SomeOtherField  JsonBDerivedColumn
 12       1            0         yes             {email: 1,print: 0,comment: "yes"}
 34       0            1         somecomment     {email: 0,print: 1,comment: "somecomment"}
@H_502_0@如何使用 Postgres sql 实现填充 JsonBDerivedColumn

解决方法

您可以使用 jsonb_build_object 函数从其他字段构建 jsonb 对象:

jsonb_build_object('email',EmailFlag_field,'print',PrintFlag_field,'comment',SomeOtherField_field)

每次在 your_table 中插入或更新行时,您都可以通过触发器自动填充 JsonBDerivedColumn 列:

CREATE OR REPLACE FUNCTION T_Before_Insert_Update_your_table()  
RETURNS trigger LANGUAGE plpgsql VOLATILE AS 
$BODY$
BEGIN
    NEW.JsonBDerivedColumn = jsonb_build_object('email',NEW.EmailFlag,NEW.PrintFlag,NEW.SomeOtherField)
    RETURN NEW ;
END ;
$BODY$

DROP TRIGGER IF EXISTS T_Before_Insert_Update_your_table ON your_table ;
CREATE TRIGGER T_Before_Insert_Update_your_table
BEFORE INSERT OR UPDATE OF EmailFlag,PrintFlag,SomeOtherField
ON your_table  
FOR EACH ROW
EXECUTE PROCEDURE T_Before_Insert_Update_your_table() ;

如果在您添加新的 JsonBDerivedColumn 列并创建触发器函数之前您的表已经存在行,则您需要为 your_table 的所有现有行填充一次新列。您可以通过启动全表的虚拟更新来实现,这将触发表的所有现有行的新触发器函数:

UPDATE your_table AS t    
   SET EmailFlag = t.EmailFlag
 WHERE TRUE ;

但是在这个故事的结尾,我不确定您是否会优化您的 SQL 查询......基于现有列的 simple indexmulticolumn indexcombining multiple indexes 怎么样? EmailFlag、PrintFlag、SomeOtherField ?