从 jsonb 成员更新整数列失败:列的类型为整数,但表达式的类型为 jsonb
Updating integer column from jsonb member fails with: column is of type integer but expression is of type jsonb
在 PostgreSQL 9.5 中 table 我有一个 integer
列 social
。
当我尝试在给定以下 JSON 数据(包含 2 个对象的数组,每个对象都有一个 "social" 键)的存储过程中更新它时 in_users
变量输入 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 数字类型。
我最终使用了:
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;
单个基于集合的 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?
回答你原来的问题:
Why doesn't PostgreSQL recognize that the data is integer?
因为您试图将 jsonb
值转换为 integer
。在您的解决方案中,您已经发现需要 ->>
运算符而不是 ->
来提取 text
,它可以转换为 integer
.
您的第二次尝试添加了第二个错误:
t->'social'::int
除上述之外:operator precedence。转换运算符 ::
比 json 运算符 ->
绑定更强。就像您已经发现自己一样,您真的想要:
(t->>'social')::int
dba.SE 上的案例非常相似:
在 PostgreSQL 9.5 中 table 我有一个 integer
列 social
。
当我尝试在给定以下 JSON 数据(包含 2 个对象的数组,每个对象都有一个 "social" 键)的存储过程中更新它时 in_users
变量输入 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 数字类型。
我最终使用了:
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;
单个基于集合的 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?
回答你原来的问题:
Why doesn't PostgreSQL recognize that the data is integer?
因为您试图将 jsonb
值转换为 integer
。在您的解决方案中,您已经发现需要 ->>
运算符而不是 ->
来提取 text
,它可以转换为 integer
.
您的第二次尝试添加了第二个错误:
t->'social'::int
除上述之外:operator precedence。转换运算符 ::
比 json 运算符 ->
绑定更强。就像您已经发现自己一样,您真的想要:
(t->>'social')::int
dba.SE 上的案例非常相似: