问题描述
我有一个带有 GENERATED ALWAYS AS IDENTITY
列 id
的非空 Postgresql 表。我使用 C++ 绑定 pqxx::stream_to 进行批量插入,我假设它使用 copY FROM
。我的问题是我想知道新创建的行的 id
,但 copY FROM
没有 RETURNING
子句。我看到了几种可能的解决方案,但我不确定它们中是否有任何一个是好的,或者哪个最不坏:
通过
id
手动提供copY FROM
,注意提供身份序列将提供的值,然后将序列与setval(...)
同步。>-
首先将数据流式传输到带有自定义索引列的临时表以进行排序。然后做类似
并取决于身份序列产生升序数字以将它们与INSERT INTO foo (col1,col2) SELECT ttFoo.col1,ttFoo.col2 FROM ttFoo ORDER BY ttFoo.idx RETURNING foo.id
ttFoo.idx
相关联的事实(我也不能做RETURNING ttFoo.idx
,因为只有插入的行可用于不包含idx
的行) -
在插入前查询身份序列的当前值,然后检查哪些行是新的。
我认为这是一种常见情况,但我没有看到明显正确的解决方案。你有什么推荐?
解决方法
您可以使用 system columns 找出哪些行受到当前事务的影响。 xmin
列包含插入事务的 ID,因此要返回您刚刚复制的 id
值,您可以:
BEGIN;
COPY foo(col1,col2) FROM STDIN;
SELECT id FROM foo
WHERE xmin::text = (txid_current() % (2^32)::bigint)::text
ORDER BY id;
COMMIT;
WHERE
子句来自 this answer,它解释了其背后的推理。
我认为没有任何方法可以使用索引对其进行优化,因此在大表上可能会太慢。如果是这样,我认为你的第二个选择是要走的路,即流入临时表和 INSERT ... RETURNING
。