使用PDO搜索重复条目


Searching for duplicate entries with PDO

我遇到了一点麻烦,因为有一些代码是为了在平台上查找名称的重复项。这也将适用于以后查找唯一ID。

因此,例如,如果Xbox上有一个名为"Apple"的服务器,并且你试图在同一平台上插入一个名称为"Apple"的记录,它会拒绝它。然而,允许使用另一个名称相同的平台,例如PS3的"Apple"。

我试着想出主意并寻找答案,但我有点不知道检查重复项的最佳方法是什么。

到目前为止,这就是我所拥有的:

$nameDuplicate_sql = $db->prepare("SELECT * FROM `servers` WHERE name=':name' AND platform=':platform'");
$nameDuplicate_sql->bindValue(':name', $name);
$nameDuplicate_sql->bindValue(':platform', $platform);
$nameDuplicate_sql->execute();

我尝试了很多不同的解决方案,有些来自这里,有些来自PHP手册等等。但似乎都不起作用。

我试着坚持PDO,然而,这是一个我不知道该转向哪里的例子。如果这是在mysql_*中,我可能只需要使用mysql_affected_rows,但对于PDO,我一无所知。rowCount看起来很有希望,但它总是返回0,因为这既不是INSERT、UPDATE,也不是DELETE语句。

哦,我在phpMyAdmin中尝试过SQL语句,它很有效;我用一个简单的名称/平台进行了尝试,它正确地找到了行。

如果有人能在这里帮我,我将不胜感激。

对于大多数数据库,PDOStatement::rowCount()不会返回受SELECT语句影响的行数。相反,使用PDO::query()发出一个SELECT COUNT(*)语句,该语句具有与预期SELECT语句相同的谓词,然后使用PDOStatement::fetchColumn()以检索将被退回。然后,您的应用程序可以执行正确的操作。

与其检查重复项,为什么不直接在数据库表上强制执行呢?创建一个复合密钥,如果条目已经存在,则禁止进行输入?

CREATE TABLE servers (
    serverName varchar(50),
    platform varchar(50),
    PRIMARY KEY (serverName, platform)
) 

通过这种方式,您将永远不会获得重复,而且它还允许您使用mysql insert... on duplicate key update...语法,这听起来可能非常方便。

如果你已经有了主键,或者你不想制作一个新表,你可以使用以下方法:

ALTER TABLE servers DROP PRIMARY KEY, ADD PRIMARY KEY(serverName, platform);

编辑:主键可以是单行,也可以是具有以具有唯一数据的多行。一行不能有两次相同的值,但复合键(这就是我在这里建议的)意味着在两列之间,不能出现相同的数据。

在这种情况下,您要做的是,添加一个服务器名称,并将其与一个平台关联-该表将允许您添加尽可能多的包含相同服务器名称的行-只要每个行都有一个唯一的平台与之关联-反之亦然,只要所有服务器名称都是唯一的,您就可以随心所欲地列出一个平台。

如果你试图在存在相同服务器名/平台组合的地方插入一条记录,数据库根本不允许你这样做。不过还有另一个黄金好处。由于这个关键约束,mysql允许使用一种特殊类型的查询。它是insert... on duplicate key update语法。这意味着,如果您尝试两次插入相同的数据(即,数据库拒绝),您可以捕获它并更新表中已有的行。例如:

您与serverName=Fluffeh有一行,它在platform=Boosh上,但您现在不知道它,所以您尝试插入一条记录,以更新服务器IP地址。

通常你会简单地写这样的东西:

insert into servers (serverName, platform, IPAddress) 
values ('$serverName', '$platform', '$IPAddy')

但有了一个很好的主键,你就可以做到这一点:

insert into servers (serverName, platform, IPAddress) 
values ('$serverName', '$platform', '$IPAddy') 
on duplicate key update set IPAddress='$IPAddy';

第二个查询将插入包含所有数据的行(如果该行不存在)。如果真的发生了,砰!它将更新服务器的IP地址,这是您一直以来的意图。

从参数标记的查询中删除单引号。。。它们一旦绑定就会被引用。。。这也是发表事先准备好的声明的部分原因。

$nameDuplicate_sql = $db->prepare("SELECT * FROM `servers` WHERE name= :name AND platform= :platform");