【问题标题】:PostgreSQL: Return auto-generated ids from COPY FROM insertionPostgreSQL:从 COPY FROM 插入返回自动生成的 id
【发布时间】:2021-07-31 23:59:28
【问题描述】:

我有一个带有GENERATED ALWAYS AS IDENTITYid 的非空PostgreSQL 表。我使用 C++ 绑定 pqxx::stream_to 进行批量插入,我假设它使用 COPY FROM。我的问题是我想知道新创建的行的ids,但是COPY FROM 没有RETURNING 子句。我看到了几种可能的解决方案,但我不确定它们中的任何一个是否是好的,或者哪个是最不坏的:

  • 通过COPY FROM手动提供ids,注意提供身份序列将提供的值,然后将序列与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 的行)
  • 在插入之前查询标识序列的当前值,然后检查哪些行是新的。

我认为这是一种常见情况,但我没有看到明显正确的解决方案。你有什么推荐的?

【问题讨论】:

    标签: postgresql libpqxx


    【解决方案1】:

    您可以使用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

    【讨论】:

    • 令人着迷的解决方案,我不知道系统列。我选择了临时表解决方案,因为它也为我解决了一些其他问题,但我确信我最终会使用 xmin 来解决一些问题。
    猜你喜欢
    • 2016-10-08
    • 1970-01-01
    • 2011-11-18
    • 2017-10-10
    • 2013-12-25
    • 2013-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多