在Postgres DB中,我有一个定义用户的表(Users)。就像
|ID| meta |
|01| {"email" : "test1@gmail.com","importance" : "High"} |
|02| {"email" : "test2@gmail.com","importance" : "Medium"}|
正如您所看到的那样,' meta'列包含json,具体原因。 (不可更改)
我想创建一个函数,它接受3个参数:
然后它会搜索包含电子邮件的元组的记录,并将新的键值添加到json中。但!如果该值为空,则会删除键值(如果它们已经存在)。
示例:
功能(' test1@gmail.com','安全''真&#39)
会导致:
|ID| meta |
|01| {"email" : "test1@gmail.com","importance" : "High", "security":"true"} |
然后:
功能(' test1@gmail.com','安全''&#39)
会导致:
|ID| meta |
|01| {"email" : "test1@gmail.com","importance" : "High"}|
到目前为止,我已经到了搜索特定记录的位置,并且我给了json结果,但我不确定实现这个json修改的最佳方法是什么。
declare
ret json;
begin
select array_to_json(array_agg(u.meta)) into ret
from Users u
where meta::text LIKE ('%"email" : "' || inc_email || '%');
return ret;
end;
答案 0 :(得分:2)
CREATE OR REPLACE FUNCTION set_value(
inc_email text,
inc_key text,
inc_value text
) RETURNS void LANGUAGE plpgsql AS
$$DECLARE
r_id integer;
r_meta json;
BEGIN
/* loop through all matching rows */
FOR r_id, r_meta IN
SELECT id, meta
FROM users
WHERE meta::jsonb @> ('{ "email": "' || inc_email || '" }')::jsonb
LOOP
/* add, update or delete the key/value pair */
r_meta := CASE
WHEN inc_value IS NULL
OR inc_value = ''
THEN
/* remove key/value pair */
(r_meta::jsonb - inc_key)::json
ELSE
/* add or replace key/value pair */
jsonb_set(
r_meta::jsonb,
ARRAY[inc_key],
('"' || inc_value || '"')::jsonb
)::json
END;
/* write the result back to the database */
UPDATE users
SET meta = r_meta
WHERE id = r_id;
END LOOP;
END;$$;