MySQL INSERT ...从1个表中选择2个表

时间:2014-03-04 21:04:56

标签: mysql database last-insert-id

我看到了很多关于从多个表中插入单个表的问题。我正在尝试相反,并仅使用MySQL

我有一个包含非规范化数据的临时表。我需要

  1. 遍历临时表的每一行
  2. 在主表上创建一个新行,其中包含临时表中的一些字段
  3. 使用刚创建的主表行的自动增量ID在辅助表上创建一个新行,将LAST_INSERT_ID()放入primary_id字段。
  4. 我理解整个LAST_INSERT_ID()并且我很高兴运行一个事务:我只是不知道如何创建循环临时表的“外部选择循环”,然后运行2个后续插入。

2 个答案:

答案 0 :(得分:1)

如果临时表中的值是唯一的,则可以使用此方法。我们的想法是将插入分成两个步骤,一个进入主表,其余进入二级表:

insert into primary( . . .)
    select . . .
    from temp;

insert into secondary(primaryid, . . . )
    select p.PrimaryId, t.col . . .
    from temp t join
         primary p
         on t.col1 = p.col1 and . . .;

有一些警告。例如,您将需要更复杂的逻辑来处理连接。并且,它假定临时表中的每组主要列都是唯一的。

最常见的方法是使用LAST_INSERT_ID的存储过程或应用程序代码中的循环。

答案 1 :(得分:0)

作为@GordonLinoff said,可以循环LAST_INSERT_ID()。如果临时表中的每组主列可能都是唯一的,那么基本上有两种方法可以实现此目的:

  1. 依靠主表中相关列的唯一性约束,以及MySQL ON DUPLICATE KEY UPDATE的{​​{1}}扩展名:

    INSERT
  2. 按(非唯一)主列的临时表排序,然后跟踪最后看到的值,并仅在遇到新记录时插入主表:

    CREATE PROCEDURE foo() BEGIN
      DECLARE done BOOLEAN DEFAULT FALSE;
      DECLARE cur CURSOR FOR SELECT . . . FROM temp;
      DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE;
    
      PREPARE ins1 FROM '
        INSERT INTO primary
          (. . .)
        VALUES
          (?, . . .)
        ON DUPLICATE KEY UPDATE
          PrimaryId = LAST_INSERT_ID(PrimaryId)
      ';
      PREPARE ins2 FROM '
        INSERT INTO secondary
          (primaryid, . . .)
        VALUES
          (LAST_INSERT_ID(), ?, . . .)
      ';
    
      OPEN cur;
      read_loop: LOOP
        FETCH cur INTO @a, @b, . . .;
        IF done THEN
          LEAVE read_loop;
        END IF;
    
        EXECUTE ins1 USING @a, . . .;
        EXECUTE ins2 USING @b, . . .;
      END LOOP;
      CLOSE cur;
    
      DROP PREPARE ins1;
      DROP PREPARE ins2;
    END