如何避免创建重复的行?

时间:2012-11-20 18:30:46

标签: php duplicate-removal mysql

我搜索和找到的所有东西都还没有工作,因为我通过PHP脚本访问表格,而不是我看到的所有内容。无论如何, 我正在将Feeds从网站导入到mysql表中。我的表就是这样创建的......

$query2 = <<<EOQ
CREATE TABLE IF NOT EXISTS `Entries` (
`feed_id` int(11) NOT NULL,
`item_title` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_link` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_date` varchar(40) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
EOQ;
$result = $db_obj->query($query2);

我输入数据......

foreach($rss->channel->item as $Item){
$query5 = <<<EOQ
INSERT INTO Entries (feed_id, item_title, item_link, item_date)
VALUES ('$get_id','$Item->title','$Item->link','$Item->pubDate')
EOQ;
$result = $db_obj->query($query5);
}

现在,每次从网站导入新的Feed时,我都要确保删除可能已存在的任何重复项。我尝试的所有东西,尤其是DISTINCT,都没有为我效劳。有谁知道我可以用什么类型的查询来创建临时表,复制任何不同的行(整个行,如果标题相同但日期不同我想保留它),删除旧表,然后重命名夯台到我想要的......还是类似的东西?

3 个答案:

答案 0 :(得分:1)

首先避免使用重复的行。将任何唯一值设为键。向数据库添加新值时,请使用

REPLACE INTO Entries (feed_id, item_title, item_link, item_date)
VALUES ('$get_id','$Item->title','$Item->link','$Item->pubDate')
EOQ;

重复项将被自动覆盖。替换是很方便的,因为它在键中没有冲突时就像插入一样工作,但是当它存在时它将更新记录并提升任何自动递增键。

修改

我已经打了一段时间。这就是我想出来的。

在(feed_id,item_title,item_link,item_date)上创建多列键的问题在于它将超过MySQL中1000字节的密钥长度限制。所以改为改变你的架构:

CREATE TABLE IF NOT EXISTS `Entries` (
`hash` varchar(32),
`feed_id` int(11) NOT NULL,
`item_title` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_link` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_date` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
 PRIMARY KEY (hash)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

现在,当您存储新值时,请同时获取值的哈希值:

$hash = md5($get_id . $Item->title . $Item->link . $Item->pubDate);

对于insert语句,请使用以下命令:

REPLACE INTO Entries (hash, feed_id, item_title, item_link, item_date)
VALUES ('$hash', '$get_id','$Item->title','$Item->link','$Item->pubDate')
EOQ;

散列将是整个记录的唯一表示形式,并且易于比较以避免重复。现在,当您尝试多次添加同一条记录时,它只会替换现有条目,您的查询不会失败。作为替代方案,您可以继续使用insert,并且查询将返回错误,您可以根据需要处理该错误。

答案 1 :(得分:0)

删除重复记录的最快速最简单的方法是发出一个非常简单的命令。

ALTER IGNORE TABLE [TABLENAME]添加唯一索引UNIQUE_INDEX([FIELDNAME])

这样做是在字段上创建一个您不希望有任何重复项的唯一索引。 ignore语法指示MySQL在遇到重复时不会停止并显示错误。这比转储和重新加载表容易得多。它还将添加唯一索引,以便不添加新的重复项。只需将INSERT更改为INSERT IGNORE。

这也可以,但不是那么优雅:

从[tablename]中删除wherename in(从中选择一个。[fieldname] (从[tablename]组中选择[fieldname] by [fieldname] have count(*)&gt; 1)a)

答案 2 :(得分:0)

也许做这样的事情:

$query2 = 'CREATE TABLE entries_new LIKE entries';
$result = $db_obj->query($query2);

$query5 = 'INSERT INTO entries_new (feed_id, item_title, item_link, item_date) VALUES ';
foreach($rss->channel->item as $Item){
    $query5 .= '('$get_id','$Item->title','$Item->link','$Item->pubDate'),';
}
$query5 = rtrim($query5, ',');
$result = $db_obj->query($query5);

$query6 = "RENAME TABLE entries TO entries_backup, entries_new TO entries";
$result = $db_object->query($query6);

这将创建一个名为entries_new的表,就像您的条目表一样。将一个数据插入到entries_new中,然后将旧表重命名为entries_backup,将新表重命名为entries。

您可能还想考虑在事务中包装整个序列。