2013-07-11 89 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不會是唯一的,因此可能有很多值。如果它是唯一的,那麼重複密鑰工作正常(因爲代碼似乎暗示通過更新,如果不止一個) –