Dmi*_*try 3 sql postgresql replace sql-update jsonb
我需要一种更有效的方法来更新 Postgres 9.5 中单个表的行。我目前正在使用 pg_dump 执行此操作,并在 Linux 操作系统环境中的搜索和替换操作后使用更新的值重新导入。
table_a有 300000 行,2 列:id bigint和json_col jsonb.
json_col有大约 30 个键:“C1”到“C30”,如本例所示:
Table_A
id,json_col
1 {"C1":"Paris","C2":"London","C3":"Berlin","C4":"Tokyo", ... "C30":"Dallas"}
2 {"C1":"Dublin","C2":"Berlin","C3":"Kiev","C4":"Tokyo", ... "C30":"Phoenix"}
3 {"C1":"Paris","C2":"London","C3":"Berlin","C4":"Ankara", ... "C30":"Madrid"}
...
Run Code Online (Sandbox Code Playgroud)
要求是批量搜索从 C1 到 C30 的所有键,然后在它们中查找值“柏林”并替换为“马德里”,并且仅当马德里不重复时。即 id:1 与密钥 C3,和 id:2 与 C2。id:3 将被跳过,因为 C30 已经存在这个值
它必须在 PostgreSQL 9.5 中的单个 SQL 命令中,一次并考虑jsonb列中的所有键。
最快最简单的方法是将列修改为文本:
update table_a
set json_col = replace(json_col::text, '"Berlin"', '"Madrid"')::jsonb
where json_col::text like '%"Berlin"%'
and json_col::text not like '%"Madrid"%'
Run Code Online (Sandbox Code Playgroud)
这是一个实用的选择。上面的查询与其说是修改对象属性,不如说是查找和替换操作(如在文本编辑器中)。第二种选择更复杂,而且肯定要贵得多。即使使用快速的 Javascript 引擎(下面的示例),更正式的解决方案也会慢很多倍。
你可以试试Postgres Javascript:
create extension if not exists plv8;
create or replace function replace_item(data jsonb, from_str text, to_str text)
returns jsonb language plv8 as $$
var found = 0;
Object.keys(data).forEach(function(key) {
if (data[key] == to_str) {
found = 1;
}
})
if (found == 0) {
Object.keys(data).forEach(function(key) {
if (data[key] == from_str) {
data[key] = to_str;
}
})
}
return data;
$$;
update table_a
set json_col = replace_item(json_col, 'Berlin', 'Madrid');
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1326 次 |
| 最近记录: |