Postgres检查空JSONB字段

时间:2017-11-16 20:42:43

标签: sql json postgresql insert plpgsql

我希望能够ignore或阻止INSERT发生如果JSON对象带有键但没有来自Postgres函数的值。这是一个小的,人为的例子:< / p>

DROP TABLE IF EXISTS mytable;
create table mytable(
a text,
b text
);

CREATE OR REPLACE FUNCTION insert_to_table(
somedata JSONB
)
RETURNS VOID AS $$
BEGIN 
insert into mytable (a, b) select a,b from jsonb_populate_recordset(null::mytable, $1::jsonb);
END;
$$ LANGUAGE plpgsql;

select insert_to_table('[{"a":1,"b":2},{"a":3,"b":4}, {"a":null, "b": null}, {"a": null, "b": "some data"}]');

这将插入4条记录,第一行为1,2,下一行为3,4。第三行是"", "",第四行是"", some data

在此方案中,行1,2和4有效。我想忽略3并防止它被插入。

我不想要一个空行,我的数据/表格会比列出的大得多(表格中大约20个字段,JSON中有20个键/值对)。

我很可能需要遍历数组并选出JSON对象,其中所有键都为空,而不只是1或2。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

在Postgres中,您可以使用查询中的表名(别名)来引用完整的行,并将其与NULL进行比较。如果所有列为空,则记录被视为NULL。所以你可以这样做:

create or replace function insert_to_table(somedata jsonb)
returns void as $$
begin 
    insert into mytable (a, b) 
    select a, b 
    from jsonb_populate_recordset(null::mytable, somedata) as t
    where not (t is null);
end;
$$ language plpgsql;

请注意,where t is not nullwhere not (t is null)不同。无论列数或数据类型如何,这都可以正常工作。

可视化逻辑。以下内容:

select a,b,
       not (t is null) as "not (t is null)", 
       t is null as "t is null", 
       t is not null as "t is not null"
from jsonb_populate_recordset(null::mytable, 
       '[{"a":1,"b":2},
         {"a":3,"b":4}, 
         {"a":null, "b": null}, 
         {"a": null, "b": "some data"}]'::jsonb) as t(a,b)

返回:

a | b         | not (t is null) | t is null | t is not null
--+-----------+-----------------+-----------+--------------
1 | 2         | true            | false     | true         
3 | 4         | true            | false     | true         
  |           | false           | true      | false        
  | some data | true            | false     | false        

无关:

由于您已经声明了该类型的参数,因此强制转换$1::jsonb是无用的。