数以千计的记录
1. 创建输入行的临时表,包括你的价值观
$1,
$2,
$3。最快的上传方法是
COPY
-或
copypsql的meta命令(如果数据不在同一台计算机上)。让我们假设这个表:
CREATE TEMP TABLE tmp(id int PRIMARY KEY, val1 text, val2 text);
我添加了一个PK约束,它完全是可选的,但可以确保我们处理的是唯一的非null int值。如果您可以保证输入数据,则不需要约束。
2.
将您的命令与修改数据的CTE链接在一起。正如我们在您之前的问题中所确定的那样,在此特定操作中没有任何比赛条件需要照顾。
WITH ins1 AS ( INSERT INTO table1 AS t1 (id, val1, val2) SELECt id, val1, val2 FROM tmp ON ConFLICT DO NOTHING RETURNING t1.id, t1.val1, t1.val2 -- only actually inserted rows returned ), ins2 AS ( INSERT INTO table2 (table1_id, val1) SELECt id, val1 FROM ins1 )UPDATe table3 t3SET val2 = i.val2 , time = now()FROM ins1 iWHERe t3.table1_id = i.id;
步骤1和2.必须必须在 _ 同一会话中_ 运行(不一定是同一事务),因为临时表的范围绑定到同一会话。
注意,
UPDATe唯一取决于1号
INSERT,
INSERT保证2号成功,因为没有
ON ConFLICT DONOTHING,如果2号中有任何冲突,整个操作将回滚
INSERT。
仅作几笔记录
有多种选择方式。将JSON数组传递给函数的想法就是其中之一。如果对象与目标表匹配,则可以json_populate_recordset()
在单个
INSERT查询中使用。或者只使用
INSERT(作为准备好的语句)不带函数包装器。
INSERT INTO target_tbl -- it's ok to omit target columns hereSELECT *FROM json_populate_recordset(null::target_tbl, -- use same table type json '[{ "id": "1", "val1": "1-val1", "val2": "1-val2" }, { "id": "2", "val1": "2-val1", "val2": "2-val2" }, { "id": "3", "val1": "3-val1", "val2": "3-val2" }, { "id": "4", "val1": "4-val1", "val2": "4-val2" }]');对于少数几个列,您还可以为每个列传递一个数组,并并行地遍历它们。您可以通过对数组索引进行简单循环来完成此操作。从Postgres
9.4开始,
unnest()使用多个参数也很方便在单个查询中完成所有操作:
最佳解决方案取决于您 拥有 的数据格式。



