使用PL / pgSQL检查密钥是否存在于JSON中?

死眼

我正在尝试检查在PL / pgSQL函数中作为参数发送的JSON中是否存在密钥。

这是功能。

CREATE FUNCTION sp_update_user(user_info json) RETURNS json
    LANGUAGE plpgsql
    AS $$
    BEGIN
    PERFORM user_info->>'lastname';
    IF FOUND
    THEN
      UPDATE users SET lastname = user_info->>'lastname' WHERE id = sp_update_user.user_id;
    END IF;

    PERFORM user_info->>'firstname';
    IF FOUND
    THEN
      UPDATE users SET firstname = user_info->>'firstname' WHERE id = sp_update_user.user_id;
    END IF;

    RETURN row_to_json(row) FROM (SELECT true AS success) row;
END;$$;

我尝试使用PERFORM-clause,但是即使json键不存在,该IF FOUND子句中的语句也会执行。

我试图PERFORM user_info->>'firstname' INTO myvar;检查变量内容,但会触发错误ERROR: query "SELECT user_info->>'firstname' INTO myvar" is not a SELECT

如何使用PL / pgSQL检查JSON中是否存在JSON密钥?

欧文·布兰德斯特

您已经发现可以测试表达式user_info->>'username'为NULL。但是您的功能仍然非常低效而且仍然存在歧义

Postgres 9.3中更好的解决方案

对于多列重复更新一行是昂贵的。Postgres为每次更新编写一个新的行版本。使用一个单一的 UPDATE,如果在所有可能的:

CREATE OR REPLACE FUNCTION sp_update_user(_user_id int, _user_info json)
  RETURNS json AS
$func$
BEGIN
   UPDATE users u
   SET    firstname = COALESCE(_user_info->>'firstname', u.firstname)
        , lastname  = COALESCE(_user_info->>'lastname' , u.lastname)
   WHERE  id = sp_update_user._user_id
   AND   ((_user_info->>'firstname') IS NOT NULL OR
          (_user_info->>'lastname')  IS NOT NULL);

   IF FOUND THEN
      RETURN '{"success":true}'::json;
   ELSE
      RETURN '{"success":false}'::json;
   END IF;
END
$func$  LANGUAGE plpgsql;

呼叫:

SELECT sp_update_user(123, '{"firstname": "jon", "lastname": "doe"}')
  • 对于多列,这实际上要快得多,因为仅执行一次UPDATE(最多)。如果该WHERE子句的结果不为true则根本不会进行任何更新,您将得到'{"success":false}'结果。

  • 如果有时表中的值已经是要更改的值,则可以进行另一种优化。考虑以下相关答案的最后一段:

  • user_id原始变量中缺少变量/参数

  • 仍然存在一个极端的模棱两可的情况如果该元素存在并将其设置为JSONnull,则还将得到一条SQLNULL作为结果。考虑:

    SELECT ('{"b": null}'::json->>'b') IS NULL AS b_is_null
         , ('{"c": 2}'::json->>'b')    IS NULL AS b_missing;
    
  • 不知道为什么要将数据类型json用作返回类型,我只是保留了这一点。但是,如果函数未更新,则无法确定为什么得到false可能没有与给定id键名的行,'firstname'并且'lastname'可能会丢失-或者是null...


Postgres 9.4中的高级解决方案

Postgres 9.4中有一个干净简单的解决方案,带有“ existence”运算符-甚至可以为更大的表使用索引(与您的函数无关):jsonb?

SELECT ('{"b": null}'::jsonb ? 'b') AS b_is_null
     , ('{"c": 2}'::jsonb ? 'b')    AS b_missing;

?|?&变体可以一次检查多个键。
这样我们就可以实现:

CREATE OR REPLACE FUNCTION sp_update_user(_user_id int, _user_info jsonb)
  RETURNS jsonb AS
$func$
BEGIN
   UPDATE users u
   SET    firstname = CASE WHEN _user_info ? 'firstname' THEN _user_info->>'firstname' ELSE u.firstname END
        , lastname  = CASE WHEN _user_info ? 'lastname'  THEN _user_info->>'lastname'  ELSE u.lastname  END
   WHERE  id = sp_update_user._user_id
   AND    _user_info ?| '{firstname,lastname}';

   IF FOUND THEN
      RETURN '{"success":true}'::jsonb;
   ELSE
      RETURN '{"success":false}'::jsonb;
   END IF;
END
$func$  LANGUAGE plpgsql;

这些调用现在可以正常工作:

SELECT sp_update_user(123, '{"firstname": null, "lastname": "doe1"}'::jsonb);
SELECT sp_update_user(123, '{"firstname": "doris"}'::jsonb);

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何访问 Json 属性并检查(密钥)是否存在于有效负载中或不使用 python

如何使用JSON检查对象是否存在于JSON中

PL/SQL 检查输入的值是否存在于不同的表中

如何使用空手道框架检查属性值是否存在于JSON模式中

如何使用Rspec来测试密钥是否存在于包含哈希数组的哈希中

如何检查密钥是否存在于json中

使用Jquery检查该类是否存在于Page上

使用Laravel检查值是否已经存在于数据库中

如何使用javascript检查子对象是否存在于对象数组中?

使用AWS Lambda Java检查用户是否存在于组中

如何使用lodash js检查字符串是否存在于数组中?

如何使用Java检查指定对象是否存在于给定对象列表中

如何匹配字母并检查值是否存在于数组中或不使用 PHP

使用C#检查文本是否已存在于SQL Server中

如何使用angularfire2检查孩子是否存在于firebase列表中

使用Google Apps脚本检查YouTube视频是否存在于播放列表中

如何使用Mule表达式语言检查属性是否存在于值中

检查 id 是否存在于数组字段中或不使用 script_fields

使用 where 子句检查文档是否存在于集合中。Firestore/颤振

如何使用SQL检查一个表中存在的json值数组是否存在于另一个表中?

如何使用空手道中驱动的数据检查来自arraylist的所有对象是否存在于json中

检查字符串是否存在于使用 csv 文件中的数据创建的列表中

如何使用自定义策略检查用户是否存在于AD B2C中?

在尝试使用ForEach调用键之前,请先检查其是否存在于动作词典中

Ansible-使用正则表达式检查字符串是否存在于文件中

如何使用JS检查对象是否存在于另一个对象中

angular 5 和 firebase/angularfire,使用键检查键是否存在于另一个表中

如何使用循环检查输入的内容是否已存在于Python的文件中,并追加新的内容?

使用 asp.net 时,如何检查我的 pin 是否存在于 SQL 数据库中?