如何防止在 PostgreSQL 的 JSON 列中插入“”或 [](空字符串)作为值
How to prevent inserting "" or [] (empty string) as value in JSON column in PostgreSQL
我想防止在 json 列中插入“”或 [](空 strings/array)。请考虑以下示例:-
{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","postCode":"","addressLine2":"PO Box 47854"}
那么输出应该删除 "postcode":"" 并且应该如下所示:-
{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","addressLine2":"PO Box 47854"}
谁能帮我解决这个问题?
您可以像这样删除这些空值:
with my_table(json_col) as (
values (
'{
"city": "LONDON",
"country": "UK",
"addressLine1": "PO Box 223456",
"postCode": "",
"addressLine2": "PO Box 47854",
"array_to_delete": []
}'::jsonb)
)
select jsonb_object_agg(key, value)
from my_table
cross join lateral jsonb_each(json_col)
where value not in ('""', '[]');
jsonb_object_agg
------------------------------------------------------------------------------------------------------
{"city": "LONDON", "country": "UK", "addressLine1": "PO Box 223456", "addressLine2": "PO Box 47854"}
(1 row)
更新。在 Postgres 9.3 中:
with my_table(json_col) as (
values (
'{
"city": "LONDON",
"country": "UK",
"addressLine1": "PO Box 223456",
"postCode": "",
"addressLine2": "PO Box 47854",
"array_to_delete": []
}'::json)
)
select format('{%s}',string_agg(format('"%s": %s', key, to_json(value)), ','))::json
from my_table
cross join lateral json_each_text(json_col)
where value not in ('', '[]');
format
---------------------------------------------------------------------------------------------------
{"city": "LONDON","country": "UK","addressLine1": "PO Box 223456","addressLine2": "PO Box 47854"}
(1 row)
更新。在这种情况下,无法应用检查约束,因为它只能接受或拒绝输入数据,而您要修改它。您可以使用上述算法创建一个函数并在触发器中使用它:
create or replace function filter_json_input()
returns trigger language plpgsql as $$
begin
select format('{%s}', string_agg(format('"%s": %s', key, to_json(value)), ','))::json
from json_each_text(new.json_col)
where value not in ('', '[]')
into new.json_col;
return new;
end $$;
使用 CTE 您可以通过以下查询来完成:
WITH j AS(
SELECT *
FROM json_each_text('{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","postCode":"","addressLine2":"PO Box 47854"}'::json)
WHERE value <> ''
) SELECT json_object_agg(j.key,j.value) FROM j
我也用PG 9.3。这是一个解决方案......也许太hacky了?但它有效,我们经常手动构建 JSON 对象,因为它更快:P
SELECT ('{' || STRING_AGG('"' || key || '":' || TO_JSON(value), ',') || '}')::JSON
FROM json_each_text('{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","postCode":"","addressLine2":"PO Box 47854"}'::JSON)
WHERE COALESCE(value, '') <> ''
结果:{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","addressLine2":"PO Box 47854"}
我想防止在 json 列中插入“”或 [](空 strings/array)。请考虑以下示例:-
{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","postCode":"","addressLine2":"PO Box 47854"}
那么输出应该删除 "postcode":"" 并且应该如下所示:-
{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","addressLine2":"PO Box 47854"}
谁能帮我解决这个问题?
您可以像这样删除这些空值:
with my_table(json_col) as (
values (
'{
"city": "LONDON",
"country": "UK",
"addressLine1": "PO Box 223456",
"postCode": "",
"addressLine2": "PO Box 47854",
"array_to_delete": []
}'::jsonb)
)
select jsonb_object_agg(key, value)
from my_table
cross join lateral jsonb_each(json_col)
where value not in ('""', '[]');
jsonb_object_agg
------------------------------------------------------------------------------------------------------
{"city": "LONDON", "country": "UK", "addressLine1": "PO Box 223456", "addressLine2": "PO Box 47854"}
(1 row)
更新。在 Postgres 9.3 中:
with my_table(json_col) as (
values (
'{
"city": "LONDON",
"country": "UK",
"addressLine1": "PO Box 223456",
"postCode": "",
"addressLine2": "PO Box 47854",
"array_to_delete": []
}'::json)
)
select format('{%s}',string_agg(format('"%s": %s', key, to_json(value)), ','))::json
from my_table
cross join lateral json_each_text(json_col)
where value not in ('', '[]');
format
---------------------------------------------------------------------------------------------------
{"city": "LONDON","country": "UK","addressLine1": "PO Box 223456","addressLine2": "PO Box 47854"}
(1 row)
更新。在这种情况下,无法应用检查约束,因为它只能接受或拒绝输入数据,而您要修改它。您可以使用上述算法创建一个函数并在触发器中使用它:
create or replace function filter_json_input()
returns trigger language plpgsql as $$
begin
select format('{%s}', string_agg(format('"%s": %s', key, to_json(value)), ','))::json
from json_each_text(new.json_col)
where value not in ('', '[]')
into new.json_col;
return new;
end $$;
使用 CTE 您可以通过以下查询来完成:
WITH j AS(
SELECT *
FROM json_each_text('{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","postCode":"","addressLine2":"PO Box 47854"}'::json)
WHERE value <> ''
) SELECT json_object_agg(j.key,j.value) FROM j
我也用PG 9.3。这是一个解决方案......也许太hacky了?但它有效,我们经常手动构建 JSON 对象,因为它更快:P
SELECT ('{' || STRING_AGG('"' || key || '":' || TO_JSON(value), ',') || '}')::JSON
FROM json_each_text('{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","postCode":"","addressLine2":"PO Box 47854"}'::JSON)
WHERE COALESCE(value, '') <> ''
结果:{"city":"LONDON","country":"UK","addressLine1":"PO Box 223456","addressLine2":"PO Box 47854"}