6

好的。所以简而言之,我试图做一个 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”共同的字段,例如地址和电话号码。因此,任何“实体”都可能没有多个地址(运输、帐单、邮寄),也没有多个电话号码(传真、主要、帐单、手机、家庭)可能有其他方法可以实现这一点,但这是我的解决方案结束了。

旧数据库中的 STORE 和 USERS 需要保留其旧 PK 并获得额外的 ENTITY fk。如何在不进行转储和手动编辑的情况下做到这一点?

4

2 回答 2

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() 是 LAST id 不同。因为它是第一行,所以我们使用变量@rn 递增每一行,从addition=0第一行开始。

于 2011-02-20T03:49:13.923 回答
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 ;

我建议您阅读有关过程游标的文档

于 2011-02-20T00:41:12.220 回答