MySQL INSERT ...从1个表格中选择2个表格
问题描述:
我看到相当多的问题涉及从多个表格中插入单个表格。我试图做相反的事情,并只使用MySQL。MySQL INSERT ...从1个表格中选择2个表格
我有一个包含非标准化数据的临时表。我需要
- 迭代通过临时表的每一行
- 创建在主表中的新行与一些临时表
- 使用主表的自动递增ID字段行只是为了在辅助表上创建新行而将
LAST_INSERT_ID()
放入primary_id字段中。
我整明白LAST_INSERT_ID()
,我很高兴运行一个交易:我只是不知道如何创建“外select循环”,通过临时表圈,然后运行2个后续插入。
答
如果临时表中的值是唯一的这可以工作。我们的想法是插入件分成两个步骤,一个到主表中,其余的入辅助表:
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()
一个可以循环。如果临时表中每个组主列的可能不是唯一的,基本上有完成这两种方法:
-
依靠了在主表中的相关列的唯一性约束,加上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
-
排序由(非唯一)主列临时表,然后保存最近看到价值的轨道,只有在遇到一个新的记录,当插入到主表:
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
你寻求内的MySQL本身做到这一点,或使用其客户端API从其他语言? – eggyal
@eggyal mySQL - 查看我的更新评论。感谢您提出这个问题! –