代码之家  ›  专栏  ›  技术社区  ›  Thomas David Baker

将具有duples的mysql表迁移到具有唯一约束的另一个表的最佳方法

  •  2
  • Thomas David Baker  · 技术社区  · 16 年前

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

    我正在从这样的表中迁移一些数据(~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;
    

    保留主键并不重要。

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

    最后一个location2表应该为location中的每个唯一addr条目都有一个条目。如果纬度/经度有多个可能的值,则应使用最新的(最高位置\u 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方法。

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

    INSERT INTO location2 SELECT ... ;
    

    迁移数据。

    谢谢!

    1 回复  |  直到 16 年前
        1
  •  4
  •   martin clayton egrunin    16 年前

    可以直接使用insert-ignore,或者 REPLACE -我假设这是一个一次性的过程,或者至少是一个性能不是主要考虑因素的过程。

    在这种情况下,位置最高的记录将获胜:

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

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

    您需要禁用严格的SQL模式,否则对addr字段的截断将导致错误。