确定。所以缺点是,我试图做一个INSERT SELECT,如:
START TRANSACTION;
INSERT INTO dbNEW.entity (commonName, surname)
SELECT namefirst, namelast
FROM dbOLD.user;
SET @key = LAST_INSERT_ID();
INSERT INTO dbNEW.user (userID, entityID, other)
SELECT user_id, @key, other
FROM dbOLD.user;
COMMIT;
当然@key不会从每个插入返回每个后续的LAST_INSERT_ID(),而是仅从最后一个插入返回ID。
基本上,我将旧的USER表拆分为ENTITY和USER,如:
dbOLD.user
+-------------+---------------------+------+-----+------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------------+------+-----+------------+----------------+
| user_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| namefirst | varchar(20) | NO | | | |
| namelast | varchar(20) | NO | | | |
| other | varchar(10) | NO | | | |
+-------------+---------------------+------+-----+------------+----------------+
dbNEW.user
+-------------+---------------------+------+-----+------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------------+------+-----+------------+----------------+
| userID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| entityID | int(10) unsigned | NO | MUL | 0 | |
| other | varchar(10) | NO | | | |
+-------------+---------------------+------+-----+------------+----------------+
dbNEW.entity
+--------------+---------------------+------+-----+------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------------+------+-----+------------+----------------+
| entityID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| commonName | varchar(20) | NO | | | |
| surname | varchar(20) | NO | | | |
+--------------+---------------------+------+-----+------------+----------------+
为什么我要这样做?基本上,我有一个“STORE”实体,它将具有“USERS”共有的字段,例如地址和电话号码。因此,任何“ENTITY”可能没有多个地址(运输,计费,邮寄),也没有多个电话号码(传真,主要,计费,小区,家庭)可能有其他方法可以实现这一点,但这是我的解决方案结束了。
来自旧数据库的商店和用户需要保留旧的PK并获得额外的ENTITY fk。如何在不进行转储和手动编辑的情况下执行此操作?
答案 0 :(得分:5)
对于上一个查询,请使用此
INSERT INTO dbNEW.`user` (userID, entityID, other)
SELECT user_id, entityID, other
FROM
(
SELECT user_id, @key + @rn entityID, other, @rn := @rn + 1
FROM (select @rn:=0) x, dbOLD.`user`
order by user_id
) y;
MySQL中的LAST_INSERT_ID()是批处理中创建的第一个ID,与SQL Server中的SCOPE_IDENTITY()不同,后者是最后一个ID。由于它是第一行,我们使用变量@rn递增每一行,从addition=0
开始为第一行。
答案 1 :(得分:1)
这种情况可能需要一个基于游标的解决方案,您可以循环遍历旧用户,并执行2个单独的插入。这不会进行批量插入,但最好是手动更新行。
DELIMITER $$
DROP PROCEDURE IF EXISTS MigrateUsers $$
CREATE PROCEDURE MigrateUsers ()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE user_id INT;
DECLARE namefirst VARCHAR(20);
DECLARE namelast VARCHAR(20);
DECLARE other VARCHAR(10);
DECLARE lid INT;
/*Cursor looping over old users*/
DECLARE cur CURSOR FOR
SELECT user_id, namefirst, namelast, other
FROM dbOLD.user;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
START TRANSACTION;
read_loop: LOOP
FETCH cur INTO user_id, namefirst, namelast, other;
IF done THEN
LEAVE read_loop;
END IF;
/*Insert entity part*/
INSERT INTO dbNEW.entity (commonName, surname)
VALUES (namefirst, namelast);
SET lid = LAST_INSERT_ID();
/*Insert user part*/
INSERT INTO dbNEW.user (userID, entityID, other)
VALUES (user_id, lid, other);
END LOOP;
COMMIT;
CLOSE cur;
END$$
DELIMITER ;
我建议您阅读Procedures和Cursors
上的文档