【问题标题】:Insert multiple rows from a select and put the generated IDs into other table从选择中插入多行并将生成的 ID 放入其他表中
【发布时间】:2021-06-15 13:38:09
【问题描述】:

给定类似这样的 MySQL 表1

alpha (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, beta_id INT NULL
, type_info INT NOT NULL
, CONSTRAINT fk_alpha_beta FOREIGN KEY (beta_id) REFERENCES beta (id)
) ENGINE=InnoDB;

beta (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, type_info INT NOT NULL
) ENGINE=InnoDB;

我的 alpha 表包含很多行,我想在表 beta 中创建相应的行,并将 ID 存储在 alpha.beta_id 列中。

我可以像这样一次性在 beta 中创建行:

INSERT INTO beta (type_info)
SELECT type_info FROM alpha
WHERE beta_id IS NULL;

如何才能将生成的 beta id 放入 alpha 中相应行的 beta_id 列?

测试版中的行没有独特的特征,无法让我回顾性地识别它们。

如果我只创建一行,我可以使用类似的东西:

UPDATE alpha
SET beta_id=LAST_INSERT_ID()
WHERE beta_id IS NULL;

但这似乎不能推广到多行。

This question 有点相似,但它使用的是INSERT ... VALUES,不适用于INSERT ... SELECT 的用例。

This question 有类似的要求,我知道我可以使用ROW_COUNT 查看插入了多少行,但这并没有给我添加的行和它们创建的 alpha 行之间的对应关系为。

我只剩下编写一个非 SQL 脚本,该脚本将提取所有信息,一次创建一个 beta 行,然后单独更新 alpha 中的行。但我更愿意在 SQL 中执行此操作,这似乎是一个相当明显的用例。


1.显然我们的实际模式要复杂一些,但我试图将其归结为演示问题所需的信息。

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    您可以假设多行 INSERT 生成连续的自动增量 ID,除非 innodb_auto_inc_lock_mode=2。见https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html

    LAST_INSERT_ID() 将告诉您插入生成的第一个 id,其他的每个都会大 1,与插入的行数一样多。

    然后你可以 UPDATE alpha 来设置这些,但一定要使用 ORDER BY 来指定复制的顺序和 UPDATE 的顺序,所以它们保持不变。

    INSERT INTO beta (type_info)
    SELECT type_info FROM alpha
    WHERE beta_id IS NULL
    ORDER BY id;
    
    SET @id = LAST_INSERT_ID()-1;
    
    UPDATE alpha
    SET beta_id=(@id := @id + 1)
    WHERE beta_id IS NULL
    ORDER BY id;
    

    【讨论】:

    • 我不会在更新中想到(@id := @id + 1)。但这似乎有效?。
    • 请注意,在 MySQL 8.0 中,他们不鼓励以这种方式使用 :=,并且他们声称他们可能会在未来的 MySQL 版本中删除该功能。有关注意事项,请参阅 dev.mysql.com/doc/refman/8.0/en/user-variables.html
    【解决方案2】:

    如果有一对一的映射,可以join返回使用类型栏:

    update alpha a join
           beta b 
           on a.type_info = b.type_info
        set a.beta_id = b.id;
    

    编辑:

    MySQL 没有很好的功能。但是您可以添加一个alpha_id(可能是暂时的)并执行以下操作:

    alter table beta add column alpha_id int;
    
    INSERT INTO beta (alpha_id, type_info)
        SELECT a.id, a.type_info
        FROM alpha a
        WHERE beta_id IS NULL;
    
    update alpha a join
           beta b 
           on a.id = b.alpha_id
        set a.beta_id = b.id;
    

    如果需要,您可以在更新后删除该列。

    【讨论】:

    • 谢谢,但不,type_info 列在 beta 中不是唯一的。
    • @khelwood 。 . .我的建议是将alpha.id 添加到beta——即使只是暂时的——这样你就可以完成这项工作。
    • 好的。我不能这样做,但这是个好主意。
    猜你喜欢
    • 2021-01-09
    • 2011-07-31
    • 1970-01-01
    • 2021-07-11
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多