sql >> データベース >  >> RDS >> PostgreSQL

PL / pgSQLを使用してJSONにキーが存在するかどうかを確認しますか?

    user_info->>'username'をテストできることはすでにわかっています。 NULLの場合。しかし、あなたの機能はまだ非常に非効率的 。そして、まだあいまいさがあります 。

    Postgres9.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が1つしかないため、これは複数の列で大幅に高速になります。 (せいぜい)実行されます。 WHEREの場合 句はtrueと評価されません 、更新はまったく行われず、'{"success":false}'が表示されます。 結果として。

    • テーブル内の値がすでに変更されている場合は、別の最適化が可能です。この関連する回答の最後の段落を検討してください:

    • 変数/パラメーターuser_id オリジナルにありません。

    • まだコーナーケースがありますあいまいさ 。要素が存在し、 JSON nullに設定されている場合 、SQL NULLも取得します 結果として。検討してください:

      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 ...


    Postgres9.4の優れたソリューション

    クリーンがあります Postgres 9.4のシンプルなソリューション 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);
    


    1. インストールなしのPostgreSQLはWindowsで実行されていますが、サーバーはCentOSLinuxで起動していません

    2. MySQLで1時間ごとにデータを取得する方法

    3. fe_sendauth:パスワードが提供されていません

    4. Knex.jsは、次の4つのクエリでセッションの再利用を強制します