【问题标题】:Recover Generated Ids from Multiple Insert Query从多个插入查询中恢复生成的 ID
【发布时间】:2011-03-22 23:34:43
【问题描述】:

我要执行表单的查询:

INSERT INTO table(field1, field2) SELECT field1, field2 FROM table WHERE id IN (4, 8, 15, 16, 23, 42)

其中 id 是 table 的自动增量主键。

执行此语句后,我想知道刚刚生成的所有新 id 是什么。我怎样才能恢复这些信息?我有兴趣(也许)在存储过程中执行此操作并将新生成的 id 列表返回到我的应用程序代码(比如说 PHP),我希望该列表与 IN 子句中出现的顺序相关SELECT 子查询。我认为这会在我的应用程序代码中节省大量的顺序插入。这是可以实现的吗?

【问题讨论】:

    标签: php sql mysql stored-procedures


    【解决方案1】:

    如果您可以控制该表(或可以创建另一个表)如何存储“transaction_id”?

    如果你把它添加到你的表中,你可以这样做:

    Declare @tranId int
    Select @tranId = Max(transaction_id) + 1 from [table]
    Insert Into [table] (field1, field2, transactionId)
    Select field1, field2, @tranId
    From //the rest of your query
    

    然后您将取出新的 ID:

    Select Id from [table] where transaction_id = @tranId
    

    请注意,您要么需要立即运行该查询作为存储过程的一部分,要么需要将您使用的 transactionId 存储在某处,这样您就可以提取正确的行而不必担心多个并发插入。

    【讨论】:

    • 该死,完全错过了 MySql 标签。不知道如何......虽然唯一对大多数 Sql 品种不通用的就是对 Max() 的调用,但我认为......
    • 尽管如此,这是一个有趣的答案...如果我只保留一个只有 id 字段的虚拟表,那么希望执行此类查询的人可以先插入虚拟表,他们可以从中恢复插入 id,因此它成为他们的 transaction_id “票证”。然后我可以在我的 INSERT INTO ... SELECT 语句中选择它作为常量。只要插入是“按顺序”发生的,我随后就应该能够通过对我按 id 排序的交易票执行 SELECT 来恢复它们......想法?
    • 我们实际上必须在工作的过程中做这样的事情,而且它工作得比较好。我们将它实现为一个单独的表,它所包含的只是这些 id 的列表(并设置为在 99 之后翻转)。将“transaction_id”列添加到您的基表中,并从辅助表中获取最新的“id”,您可能会没事。您可能还想存储 DateTime 以防在返回新 id 之间进行了多次插入。
    • 我接受这个答案作为尝试的灵感。
    【解决方案2】:

    我不这么认为。至少不是以可靠的方式。 LAST_INSERT_ID() 将从扩展插入返回第一个自动生成的 id。您可以假设在此插入过程中也插入了所有高于此值的内容,但在许多情况下这可能是错误的(尤其是当有多个人同时在数据库上工作时)。

    【讨论】:

    • 确实不能可靠地工作。在存储过程中,可以只用光标在选择上进行循环,进行单次插入。
    • @Wrikken - 是的,如果他们是 Eeeeevillll! ;)
    • 这会比从我的应用程序代码(即通过网络)顺序发出查询快得多吗?
    • 如果我在 TRANSACTION 中发出 INSERT INTO ... SELECT 怎么办?
    • 在事务中执行此操作将消除大部分障碍。我能想到的唯一其他可能破坏它的是多主复制设置中的非顺序自动 ID 生成。
    【解决方案3】:

    您只能获取 LAST 插入 id 但您可以获取受影响的行...

    所以 id 将是

      $ids = range($lastID - (--$rows), $lastID);
    

    --$rows 因为你也想维护最后一个 id。

    例如。最后插入是 18 并且 3 行受到影响,因此 16,17, 18 将成为您的 id,但 18 - 3 将产生 15,因此给 id 15,16,17,18 这是错误的!

    【讨论】:

    • 我认为问题是你不能保证插入不会中断......所以我不能保证连续自动增量 id 没有中断生成。
    • PHP 不是多线程的,因此如果通过 php 执行,任何数据库查询都将被“排队”。如果您连接了 200 个人,则无关紧要 - 任何其他查询都将在此查询完成后运行。另一种方法是在您的表上获得一个写锁,然后什么都不会干扰,因此您可以确信 lastinsert id 和受影响的行计算将提供正确的结果。
    猜你喜欢
    • 2019-09-06
    • 2017-10-15
    • 2021-03-16
    • 2014-01-26
    • 2015-09-04
    • 2012-09-28
    • 2013-04-29
    • 1970-01-01
    • 2019-02-03
    相关资源
    最近更新 更多