使用dupes将MySQL表迁移到具有UNIQUE约束的另一个表的最佳方法

时间:2010-09-03 00:58:36

标签: sql mysql cursor database-migration

我正在努力找出数据迁移的最佳方法。

我正在从这样的表中迁移一些数据(~8000行):

CREATE TABLE location (
    location_id INT NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY,
    addr VARCHAR(1000) NOT NULL,
    longitude FLOAT(11),
    latitude FLOAT(11)
) Engine = InnoDB, DEFAULT CHARSET=UTF8;

到这样的表:

CREATE TABLE location2 (
    location_id INT NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY,
    addr VARCHAR(255) NOT NULL UNIQUE,
    longitude FLOAT(11),
    latitude FLOAT(11)
) Engine = InnoDB, DEFAULT CHARSET=UTF8;

保留主键并不重要。

“位置”中的地址重复多次。在大多数情况下具有相同的纬度和经度。但在某些情况下,addr具有相同值的行,但纬度和经度具有不同的值。

对于位置中的每个唯一地址条目,最终的location2表应该有一个条目。如果纬度/经度有多个可能的值,则应使用最新的(最高location_id)。

我创建了一个程序来执行此操作,但它不喜欢addr相同但纬度/经度不同的行。

DROP PROCEDURE IF EXISTS migratelocation;
DELIMITER $$
CREATE PROCEDURE migratelocation()
BEGIN
    DECLARE done INT DEFAULT 0;
    DECLARE a VARCHAR(255);
    DECLARE b, c FLOAT(11);
    DECLARE cur CURSOR FOR SELECT DISTINCT addr, latitude, longitude FROM location;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    OPEN cur;
    REPEAT
        FETCH cur INTO a, b, c;
        IF NOT done THEN
            INSERT INTO location2 (addr, latitude, longitude) VALUES (a, b, c);
        END IF;
    UNTIL done END REPEAT;
    CLOSE cur;
END $$
DELIMITER ;
CALL migratelocation();

这样做有好办法吗?我一直想放弃并编写一些PHP编程来完成它,但如果可以的话,我宁愿学习正确的SQL方法。

可能我只需要从第一张表中找到正确的SELECT,我可以使用:

INSERT INTO location2 SELECT ... ;

迁移数据。

谢谢!

1 个答案:

答案 0 :(得分:4)

您可以直接使用INSERT IGNORE,或REPLACE - 我假设这是一次性过程,或至少一次性能不是主要考虑因素。

在这种情况下,location_id最高的记录获胜:

INSERT IGNORE
INTO   location2
SELECT *
FROM   location
ORDER BY
       location_id DESC

具有相同主键值的后续记录将被插入丢弃。

您需要禁用严格的SQL模式,否则截断addr字段会出错。