uns*_*age 2 postgresql database-design stored-procedures
我正在使用 Postgres 9.5,我想弄清楚如何使用 JSON 数组更新 postgres 表。我希望数组中的每个对象都对应一个新行,每个键对应一个列,每个值都是要插入到该列中的数据。我试图用一个函数来做到这一点。这里的数据格式:
[
{ col1: a, col2: 5, col3: 1, col4: one},
{ col1: b, col2: 6, col3: 2, col4: two},
{ col1: c, col2: 7, col3: 3, col4: three},
{ col1: d, col2: 8, col3: 4, col4: four},
]
Run Code Online (Sandbox Code Playgroud)
这是我的预期输出:
col1 (varchar)| col2 (integer) | col3 (integer) | col4 (varchar)
-----------------+----------------+--------------------+------------------
a | 5 | 1 | one
b | 6 | 2 | two
c | 7 | 3 | three
d | 8 | 4 | four
Run Code Online (Sandbox Code Playgroud)
是否有内置的 postgres JSON 函数或运算符可以为我执行此操作?或者我是否必须遍历数组并拉出每个值,然后将其作为输入传递?我知道下面的函数是错误的,但我的目标是使函数的行为类似于以下内容:
CREATE OR REPLACE FUNCTION UPDATE_TABLE_FUNC (
arrayOfValues TEXT[]
)
RETURN VOID AS $$
BEGIN
UPDATE table SET (col1, col2, col3, col4) = ($1)
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
如果您知道所需的列名(与 JSON 结构中的键相同或不同,您可以使用json[b]_to_recordset()
:
SELECT * FROM jsonb_to_recordset('[
{ "col1": "a", "col2": 1, "col3": 1, "col4": "one"},
{ "col1": "b", "col2": 2, "col3": 2, "col4": "two"},
{ "col1": "c", "col2": 3, "col3": 3, "col4": "three"},
{ "col1": "d", "col2": 4, "col3": 4, "col4": "four"}
]'::jsonb) AS t (col1 text, col2 integer, col3 integer, col4 text);
col1 ? col2 ? col3 ? col4
????????????????????????????
a ? 1 ? 1 ? one
b ? 2 ? 2 ? two
c ? 3 ? 3 ? three
d ? 4 ? 4 ? four
Run Code Online (Sandbox Code Playgroud)
正如文档告诉我们的那样,
注意:在
json_populate_record
、json_populate_recordset
、json_to_record
和 中json_to_recordset
,来自 JSON 的类型强制是“尽力而为”,对于某些类型可能不会产生所需的值。JSON 键与目标行类型中的相同列名匹配。未出现在目标行类型中的 JSON 字段将从输出中省略,不匹配任何 JSON 字段的目标列将简单地为NULL
.
如果您已经有一张桌子可以使用,这json_populate_recordset()
是一个更好的解决方案:
CREATE TABLE inputtable (col1 text, col2 integer, col3 integer, col4 text);
SELECT * FROM jsonb_populate_recordset(NULL::yourtable, '[
{ "col1": "a", "col2": 1, "col3": 1, "col4": "one"},
{ "col1": "b", "col2": 2, "col3": 2, "col4": "two"},
{ "col1": "c", "col2": 3, "col3": 3, "col4": "three"},
{ "col1": "d", "col2": 4, "col3": 4, "col4": "four"}
]'::jsonb);
col1 ? col2 ? col3 ? col4
????????????????????????????
a ? 1 ? 1 ? one
b ? 2 ? 2 ? two
c ? 3 ? 3 ? three
d ? 4 ? 4 ? four
Run Code Online (Sandbox Code Playgroud)
现在更新表本身可以这样完成:
WITH source AS (SELECT * FROM jsonb_populate_recordset [...])
UPDATE yourtable
SET col1 = s.col1, col2 = s.col2
FROM source AS s
WHERE col3 = s.col3;
Run Code Online (Sandbox Code Playgroud)
如果它看起来很慢,那么不使用 CTE,而是在FROM
子句中使用子查询可能是有意义的。
归档时间: |
|
查看次数: |
7230 次 |
最近记录: |