【问题标题】:How to handle mysql #1062 - Duplicate entry error when creating a large table如何处理 mysql #1062 - 创建大表时出现重复条目​​错误
【发布时间】:2012-02-20 13:15:34
【问题描述】:

我正在处理一张有大约 500 万条记录的表。我正在从 csv 文件加载记录。

有一个独特的列,url

在插入时,如果url 已经在表中,我想更改新的url 值,然后进行插入。

示例:

  • 尝试插入具有url"book" 的记录。如果"book" 已经存在,则新记录应该有url"book-1"(然后是"book-2" 等等)

  • 结果:除了初始值book之外,url"book-1","book-2"...也在表中

我发现有 2 种方法可以这样做。

  1. 在插入每条记录之前:检查url值是否已经存在;如果确实如此,则在新的url 值中进行所需的更改并插入。恐怕这会导致性能不佳。

  2. 插入记录而不检查url 值是否已存在。如果url 值已经存在,则处理“mysql #1062 - Duplicate entry error”并在url 值中进行必要的更改;重试插入。

这可能吗?如果有,怎么做?

【问题讨论】:

  • 您将使用什么来导入 csv ?我会编写一个 php 文件来插入记录,使用 try/catch 块来获取 1064/1062 重复条目,并相应地更改 url。
  • 我正在编写一个 ruby​​ 脚本并使用 Sequel ORM。
  • Ruby 不是我的领域 :) 但我确信存在相同的机制,对 CSV 中的每条记录运行查询,如果遇到重复键异常,请更改值并再次插入

标签: mysql sql


【解决方案1】:

如果这是一次性问题,我想推荐一种临时 MySQL 解决方案:

  1. 如果您的表不是 MyISAM,请转换为 MyISAM。
  2. 临时创建一个名为 auto_increment 的整数列 url_suffix
  3. 暂时删除url列上的唯一约束。
  4. 创建多列索引(urlurl_suffix)并确保没有其他索引使用url_suffix
  5. 插入所有行,允许重复的 URL。您会注意到 auto_increment url_suffix 列现在在 url 上键入。因此,第一个特定的 url 将具有 url_suffix1 以及下一个 2,依此类推。
  6. 执行如下更新,然后删除您的临时 url_suffix 列并放回您的唯一约束。

查询更新所有行:

UPDATE urls
SET url = if (url_suffix = 1, url, CONCAT(url, '-', url_suffix - 1))

事实上,您可以跳过第 6 步,保留 auto_increment 字段,以便您以后可以轻松添加重复的 URL,然后像这样简单地获取您的 URL:

SELECT (if (url_suffix = 1, url, CONCAT(url, '-', url_suffix - 1))) AS url
FROM urls

您的数据将如下所示:

url     url_suffix
---------------------------
that    1
that    2
this    1
this    2
this    3
those   1

【讨论】:

    【解决方案2】:

    您在这里遇到的问题是,由于您说它们将从“book”变为“book-1”、“book-2”等,因此插入时简单的触发器将证明效率低下。最简单的方法是这将是有一个新列,其中包含一个默认为 0 的数值。这可以在存储过程中完成,即

    CREATE PROCEDURE `insertURL`(inURL VARCHAR(255))
    
    BEGIN
        DECLARE thisSuffix INT UNSIGNED DEFAULT 0;
        // We have to get this ID first, as MySQL won't let you select from the table you are inserting to
        SELECT COALESCE(MAX(url_suffix)+1,0) INTO thisSuffix FROM urls WHERE url_column = inURL;
        // Now the ID is retrieved, insert
        INSERT INTO urls (
            url_column,
            url_suffix
        ) VALUES (
            inURL,
            thisSuffix
        );
        // And then select the generated URL
        SELECT IF(thisSuffix>0,CONCAT(inURL,'-',thisSuffix),inURL) AS outURL;
    END
    

    然后使用

    调用
    CALL insertURL('book');
    

    如果后缀 = 0,则返回“book”,如果后缀大于 0,则返回“book-1”。

    为了测试我的表格设计是

    CREATE TABLE `urls` (
    `url_column`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
    `url_suffix`  tinyint(3) UNSIGNED NOT NULL ,
    PRIMARY KEY (`url_column`, `url_suffix`)
    );
    

    【讨论】:

      猜你喜欢
      • 2013-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-01
      • 1970-01-01
      • 2021-09-01
      • 2011-07-13
      相关资源
      最近更新 更多