2009-07-27 97 views
3

我有一個名爲user_ips的表來跟蹤用戶,以防他們刪除他們的cookie或更改瀏覽器。無論如何,下面的代碼很簡單。它更新user_ips中與用戶ID和IP相同的條目。如果查詢沒有更新任何行,那麼這意味着該用戶的IP不在表中,因此它會插入它。奇怪的行爲與PHP中的mysql_affected_rows()

$site->query('UPDATE `user_ips` SET `last_time` = UNIX_TIMESTAMP(), `user_agent` = \''.$this->user_agent.'\' WHERE `ip` = '.$this->ip.' AND `userid` = '.$this->id); 
if(mysql_affected_rows() == 0) 
{ 
    $site->query('INSERT INTO `user_ips` SET `userid` = '.$this->id.', `ip` = '.$this->ip.', `first_time` = UNIX_TIMESTAMP(), `last_time` = UNIX_TIMESTAMP(), `user_agent` = \''.$this->user_agent.'\''); 
} 

問題是mysql_affected_rows()有時會返回0,即使用戶當前的ID和IP存在一行。那麼代碼會向表中添加相同IP的另一行。

如果你想知道,$ site是我爲我的網站做的mysql類,它執行的唯一查詢是通過query()傳遞給它的唯一查詢,沒有其他,因此這不是類問題。哦,IP被存儲爲長IP,所以它不需要引號。

回答

7

我直接在這裏引用的PHP文件:

當使用UPDATE查詢,MySQL不會更新,其中新價值是一樣的舊值列。這會造成mysql_affected_rows()實際上可能不等於匹配的行數的可能性,而只是實際上受查詢字面影響的行數。

所以在你的情況下,當UNIX_TIMESTAMP()返回相同的值(例如,來自同一客戶端的兩個請求在同一秒內)時,mysql_affected_rows()將返回0。

+0

這很有道理謝謝。 – fent 2009-07-27 14:00:10

1

要建立在slipbull的答案上​​,處理這個問題的最簡單方法可能是簡單地執行一個SELECT查詢來評估是否需要INSERT。另一個解決方案是在創建用戶時簡單地插入記錄,因爲這將保證有效的記錄。

+0

我以前正在做另一個SELECT COUNT(*)查詢來檢查,但我將其更改爲保存一個查詢。但我想我應該回去。 – fent 2009-07-27 14:01:11

1

你可以設置你的主鍵跨度userid和ip。這樣可以確保您沒有重複條目,但是如果您不打算添加select來檢查記錄存在,則必須在插入查詢中禁止出現錯誤。

+0

我不認爲這是可能的在MySQL中。用戶可以有很多IP,一個IP可能屬於多個用戶。因此,用戶ID和IP的組合必須是唯一的。 – fent 2009-07-27 14:05:43