【问题标题】:Updating integer column from jsonb member fails with: column is of type integer but expression is of type jsonb从 jsonb 成员更新整数列失败:列是整数类型,但表达式是 jsonb 类型
【发布时间】:2016-05-15 15:48:20
【问题描述】:

在 PostgreSQL 9.5 表中,我有一个 integersocial

当我尝试在存储过程中更新它时,在 in_users 类型为 jsonb 的变量中给定以下 JSON 数据(一个包含 2 个对象的数组,每个对象都有一个“社交”键):

'[{"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 数字类型。

【问题讨论】:

  • 我回滚了您上次有效添加新问题的编辑。如果仍然不清楚,请发布一个新问题。

标签: json postgresql plpgsql postgresql-9.5 postgresql-json


【解决方案1】:

单个基于集合的 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。在您的解决方案中,您已经发现需要->> 运算符而不是-> 来提取text,它可以转换为integer

您的第二次尝试添加了第二个错误:

t->'social'::int

除上述之外:operator precedence。转换运算符 :: 的绑定比 json 运算符 -> 更强。就像你已经找到自己一样,你真的想要:

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

dba.SE 上的情况非常相似:

【讨论】:

  • Erwin,感谢您的指导,但我不确定如何将您的建议应用到我的案例中 - 我循环遍历 jsonb 数组并执行 UPDATE - IF NOT FOUND THEN - INSERT。请查看我的words_merge_users() function 了解更多信息。
  • @AlexanderFarber:在 Postgres 9.5 中使用新的 INSERT ... ON CONFLICT ... DO UPDATE 可能有一个非常优雅的解决方案。但请将您的新问题作为新问题发布。
  • Erwin,我已经发布了 a new question,但对于某些 JSON 数据,它似乎不适用于 ON CONFLICT
【解决方案2】:

我最终使用了:

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;

【讨论】:

    猜你喜欢
    • 2017-03-28
    • 2018-10-09
    • 1970-01-01
    • 2023-03-30
    • 2018-05-03
    • 2015-04-22
    • 2011-12-18
    • 1970-01-01
    • 2022-08-22
    相关资源
    最近更新 更多