我正在尝试在 PostgreSQL 12-beta2 中以特定顺序将数据从一个表批量复制到另一个表。该表未使用序列,但包含复合唯一主键 ( user_id, object_id
)。
为了确定下一批从哪里开始,我想从最后插入的行 ( WHERE user_id >= last_user_id AND object_id > last_object_id
) 开始。
从这个开始:
INSERT INTO dest_table
SELECT (user_id, object_id, object_type, colN, ...)
FROM source_table
ORDER BY user_id, colN, object_id -- this is indexed
LIMIT 1000 -- batch size
RETURNING user_id, object_id;
... 返回一个包含 1000 个元组的表。我想从中获取最后插入的元组。
我试图围绕它做一个 SELECT ,如下所示:
SELECT user_id, object_id FROM (
INSERT INTO dest_table
SELECT (user_id, object_id, object_type, colN, ...)
FROM source_table
ORDER BY user_id, colN, object_id -- this is indexed
LIMIT 1000 -- batch size
RETURNING user_id, object_id
)
ORDER BY user_id DESC, colN DESC, object_id DESC
LIMIT 1
RETURNING user_id, object_id;
但这会返回语法错误:
ERROR: syntax error at or near "INTO"
LINE 2: INSERT INTO dest_table
^
我也尝试RETURNING ... INTO variable
过这里描述的,但这也失败了:
ERROR: syntax error at or near "INTO"
LINE 23: RETURNING user_id, object_id INTO my_variable;
^
我是否需要为此创建一个函数(例如 plpgsql),或者我是否在普通 SQL 中遗漏了一些明显的东西让我这样做?那将是非常有利的。
似乎您只需要最后插入的最大值(user_id,object_id)作为一对。第一个 INSERT 可能是:
为方便起见,此表格使用一行来指代
(user_id,object_id)
这对夫妇。根据您的情况需要从左到右比较行元素,以使用这两个值作为边界。请参阅 文档中的行构造函数比较。使用此解决方案,随后的 INSERT 将注入最后一个先前插入返回的值。这样可以避免在
dest_table
.在纯 SQL 中,您将在一个步骤中执行单个 INSERT,而无需任何批处理。由于您想将其分成批次,因此必须有一些循环驱动这些带有停止条件的 INSERT,并且此过程逻辑超出了纯 SQL 的范围。
如果您不想通过变量重新注入边界,则可以将其保留在专用的单行表中。
如果除了您自己之外没有其他人正在写信
dest_table
,请在所有后续批次的子查询中获取最后插入的 ID,例如: