2013-07-11 93 views
0

嗨,我想知道是否有可能只在一个查询中执行此操作。计数并执行插入或更新

$qryString="SELECT * FROM votes WHERE userID='$userID' AND messageID='$messageID'"; 

$qry = $pdo->prepare($qryString); 
$qry->execute(); 

$resultArray=$qry->fetchAll(); 
$num=count($resultArray); 

if ($num==0) 
{$qryString= "INSERT INTO Votes (userID, value, messageID) VALUES ('$id', '$value', '$messageID')" } 

else 
{ $qryString = "UPDATE votes SET value='$value', WHERE userID='$id' AND messageID='$messageID' " } 

这样做,我会执行至少两个查询。这是一种“怪诞”的方法(带来性能的影响),或者这是正确的方式?

+0

它不仅具有性能影响,但是具有争用条件,其中另一种方法插入相同的记录(或删除它)中的时间跨度那些2之间sql查询,导致第二个查询失败。一个交易可以解决这个问题,但是'重复密钥更新'在这里更好。 – goat

+0

uhm,在最坏的情况下,它只是检索一个错误,或者它会阻碍整个数据库? – Sonia

回答

3

Assumine userID具有唯一索引:

INSERT INTO Votes (userID, value) VALUES (:id, :value) 
ON DUPLICATE KEY UPDATE value = VALUES(value); 

此外,由于您使用的PDO,你应该使用占位符在准备好的声明,不插变量,如我上面显示。

+0

userID不是唯一的,因为一个用户可以执行很多投票。我对上面的代码进行了简化,确实检查是在userID和messageID上进行的。我现在更新问题 – Sonia

+0

对于占位符问题,它只是为了避免SQL注入,对吧? – Sonia

+0

@AnnaLica **否**。这是让您的查询运行没有错误。 –

0

我想提出以下建议:

获取计数
使用MySQL的计数功能:

SELECT COUNT(*) FROM votes WHERE UserID='$id'; 

这将返回一个标量(记录数),从节省PHP获取整个结果集

其次,您在决定更新或插入代码时是完全正确的。逻辑属于代码,而不属于数据库。这可以用Barmar的答案完成,并且是一个风格问题。

参考
http://dev.mysql.com/doc/refman/5.0/en/if.html
http://dev.mysql.com/doc/refman/5.1/en/counting-rows.html

+0

所以你不会使用'Insert ... on duplicate key ...'? – 2013-07-11 02:02:46

+0

在单个语句中进行操作可以避免竞争条件(也可以使用事务来解决)。 – Barmar

+0

我认为,因为Votes是一个投票表,而不是用户表,所以UserID不会是唯一的,因此可能有很多值。如果它是唯一的,那么重复密钥工作正常(因为代码似乎暗示通过更新,如果不止一个) –