3

PostgreSQL 9.5 テーブルには、integer列がありますsocial

in_userstype の変数に次の JSON データ (それぞれが「social」キーを持つ 2 つのオブジェクトを含む配列) が指定されたストアド プロシージャで更新しようとすると、次のようになりますjsonb

'[{"sid":"12345284239407942","auth":"ddddc1808197a1161bc22dc307accccc",**"social":3**,"given":"Alexander1","family":"Farber","photo":"https:\/\/graph.facebook.com\/1015428423940942\/picture?type=large","place":"Bochum,
Germany","female":0,"stamp":1450102770},
  {"sid":"54321284239407942","auth":"ddddc1808197a1161bc22dc307abbbbb",**"social":4**,"given":"Alxander2","family":"Farber","photo":null,"place":"Bochum,
Germany","female":0,"stamp":1450102800}]'::jsonb

次に、次のコードは失敗します。

    FOR t IN SELECT * FROM JSONB_ARRAY_ELEMENTS(in_users)
    LOOP
            UPDATE words_social SET
                    social = t->'social',
            WHERE sid = t->>'sid';
    END LOOP;

エラーメッセージとともに:

ERROR:  column "social" is of type integer but expression is of type jsonb
LINE 3:                         social = t->'social',
                                         ^
HINT:  You will need to rewrite or cast the expression.

私はその行を次のように変更しようとしました:

social = t->'social'::int,

しかし、その後エラーが発生します:

ERROR:  invalid input syntax for integer: "social"
LINE 3:                         social = t->'social'::int,
                                            ^

PostgreSQL がデータが であることを認識しないのはなぜintegerですか?

JSON-TYPE-MAPPING-TABLEから、 JSON数値が PostgreSQL 数値型に自動変換されるという印象を受けました。

4

2 に答える 2

6

単一のセットベースの SQL コマンドは、ループよりもはるかに効率的です。

UPDATE words_social w
SET    social = (iu->>'social')::int
FROM   JSONB_ARRAY_ELEMENTS(in_users) iu  -- in_user = function variable
WHERE  w.sid = iu->>'sid';                -- type of sid?

元の質問に答えるには:

PostgreSQL がデータが整数であることを認識しないのはなぜですか?

jsonb値をに変換しようとしていたためですinteger。あなたのソリューションでは、にキャストできる抽出する->>代わりに演算子が必要であることがすでにわかりました。->textinteger

2 回目の試行で 2 番目のエラーが追加されました:

t->'social'::int

上記に加えて: operator precedence。キャスト演算子::は、json 演算子よりも強力にバインドし->ます。あなたがすでに自分自身を見つけたように、あなたは本当に欲しい:

(t->>'social')::int

dba.SE での非常によく似たケース:

于 2016-02-13T09:08:39.117 に答える
1

私は最終的に使用しました:

FOR t IN SELECT * FROM JSONB_ARRAY_ELEMENTS(in_users)
LOOP
        UPDATE words_social SET
                social = (t->>'social')::int
        WHERE sid = t->>'sid';

        IF NOT FOUND THEN
                INSERT INTO words_social (social)
                VALUES ((t->>'social')::int);
        END IF;
END LOOP;
于 2016-02-05T18:35:48.753 に答える