更新json的数据库函数

时间:2017-01-24 14:51:00

标签: database postgresql function

在Postgres DB中,我有一个定义用户的表(Users)。就像

|ID|                    meta                               |
|01|  {"email" : "test1@gmail.com","importance" : "High"}  |
|02|  {"email" : "test2@gmail.com","importance" : "Medium"}|

正如您所看到的那样,' meta'列包含json,具体原因。 (不可更改)

我想创建一个函数,它接受3个参数:

  • 电子邮件(inc_email)
  • A键(inc_key)
  • 值(inc_value)

然后它会搜索包含电子邮件的元组的记录,并将新的键值添加到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;

1 个答案:

答案 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;$$;