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

问题描述:

我看到相当多的问题涉及从多个表格中插入单个表格。我试图做相反的事情,并只使用MySQLMySQL INSERT ...从1个表格中选择2个表格

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

  1. 迭代通过临时表的每一行
  2. 创建在主表中的新行与一些临时表
  3. 使用主表的自动递增ID字段行只是为了在辅助表上创建新行而将LAST_INSERT_ID()放入primary_id字段中。

我整明白LAST_INSERT_ID(),我很高兴运行一个交易:我只是不知道如何创建“外select循环”,通过临时表圈,然后运行2个后续插入。

+0

你寻求内的MySQL本身做到这一点,或使用其客户端API从其他语言? – eggyal

+0

@eggyal mySQL - 查看我的更新评论。感谢您提出这个问题! –

如果临时表中的值是唯一的这可以工作。我们的想法是插入件分成两个步骤,一个到主表中,其余的入辅助表:

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存储过程或应用代码的循环。

+0

谢谢戈登 - 这正指向了我正确的方向。你有存储过程方法中的循环的例子吗? –

由于@GordonLinoff said,在LAST_INSERT_ID()一个可以循环。如果临时表中每个组主列的可能是唯一的,基本上有完成这两种方法:

  1. 依靠了在主表中的相关列的唯一性约束,加上MySQL的ON DUPLICATE KEY UPDATE扩展INSERT

    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 
    
  2. 排序由(非唯一)主列临时表,然后保存最近看到价值的轨道,只有在遇到一个新的记录,当插入到主表:

    CREATE PROCEDURE foo() BEGIN 
        DECLARE done BOOLEAN DEFAULT FALSE; 
        DECLARE cur CURSOR FOR SELECT . . . FROM temp ORDER BY . . .; 
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE; 
    
        PREPARE ins1 FROM ' 
        INSERT INTO primary 
         (. . .) 
        VALUES 
         (. . .) -- use "?" placeholders 
        '; 
        PREPARE ins2 FROM ' 
        INSERT INTO secondary 
         (primaryid, . . .) 
        VALUES 
         (. . .) -- use "?" placeholders 
        '; 
    
        OPEN cur; 
        FETCH cur INTO @a, @b, . . .; 
        WHILE NOT done DO 
        SET @current_a := @a, . . .; -- (non-unique) primary cols 
        EXECUTE ins1 USING @a, . . .; 
        SET @primaryid := LAST_INSERT_ID(); 
    
        REPEAT 
         EXECUTE ins2 USING @primaryid, @b, . . .; 
         FETCH cur INTO @a, @b, . . .; 
        UNTIL done OR @a <> @current_a OR . . . END REPEAT; 
        END WHILE; 
        CLOSE cur; 
    
        DROP PREPARE ins1; 
        DROP PREPARE ins2; 
    END