【问题标题】:Best way to avoid duplicate entry into mysql database避免重复进入mysql数据库的最佳方法
【发布时间】:2011-01-14 06:08:36
【问题描述】:

我有一个包含 3 列的表 - id (pk)、pageId (fk)、名称。我有一个 php 脚本,它将大约 5000 条记录转储到表中,其中大约一半是重复的,具有相同的 pageId 和名称。 pageId 和 name 的组合应该是唯一的。当我在 php 中循环脚本时,防止将重复项保存到表中的最佳方法是什么?

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    您可以将 PageID 和 Name 设置为 MySQL 数据库中的唯一索引。这样插入行时会报错,PHP可以忽略,直接进入下一行即可。

    这假设您正在单独插入行。又名:

    foreach($large_data as $fields)
    {
        mysql_query("INSERT INTO TABLE (`Something`) VALUES('".$fields['something']."');
    }
    

    【讨论】:

    • 故意让 mysql_query() 在遇到重复行时抛出 PHP 警告有点麻烦(它会使您的日志变得混乱,相对占用大量资源等)。尤其是当首先防止它们就像使用其他解决方案中提到的 MySQL 的 INSERT IGNORE 功能一样简单时。此外,当大容量插入语法可用时,在循环中插入效率很低。
    【解决方案2】:

    从mysql的角度来看你可以做

    alter table YOURTABLE add unique index(pageId, name);
    

    如果你的措辞是正确的,并且你想用 php 来做,你可以做

    $already_done = array();
    foreach ($records as $record)
    {
       $unique_hash = md5($record['name'].$record['pageId']);
       if (!in_array($unique_hash, $already_done))
       {
          $already_done[] = $unique_hash;
          // sql insert here
       }
    }
    

    无论哪种方式,你都应该做得很好。

    【讨论】:

    • 当然,如果在脚本开始之前表中已有记录,则$already_done中不会出现这些记录。
    【解决方案3】:

    您也可以使用 mysql 忽略错误:INSERT IGNORE INTO TABLE ...它将忽略关键错误,跳过该插入并继续下一个。

    【讨论】:

      【解决方案4】:

      第一步是在表上设置一个唯一键:

      ALTER TABLE thetable ADD UNIQUE INDEX(pageid, name);
      

      然后你必须决定当有重复时你想做什么。你应该:

      1. 忽略它?

        INSERT IGNORE INTO thetable (pageid, name) VALUES (1, "foo"), (1, "foo");
        
      2. 覆盖之前输入的记录?

        INSERT INTO thetable (pageid, name, somefield)
        VALUES (1, "foo", "first")
        ON DUPLICATE KEY UPDATE (somefield = 'first')
        
        INSERT INTO thetable (pageid, name, somefield)
        VALUES (1, "foo", "second")
        ON DUPLICATE KEY UPDATE (somefield = 'second')
        
      3. 更新一些计数器?

        INSERT INTO thetable (pageid, name)
        VALUES (1, "foo"), (1, "foo")
        ON DUPLICATE KEY UPDATE (pagecount = pagecount + 1)
        

      【讨论】:

      • 非常感谢,这是我在 Stack Overlow 上研究了一段时间的一个问题的绝佳答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多