2017-12-02 183 views
0

我收到一個奇怪的結果,其中更新方法(http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html#update)調用激活/停用mySQL數據庫中的站點用戶帳戶有時不更新並返回0.這裏是代碼:Symfony2 DBAL更新方法返回0

$user_id = '198'; 
$sqlSetStmnt= [ 'activation_code' => NULL, 'active' => 0 ]; 
$conn = $this->get('database_connection'); 

try { 

    $result = $conn->update('users', $sqlSetStmnt,[ 'id' => (int)$user_id ]); 

} 
catch(Exception $e) { 

    $error = $e->getMessage(); 
    throw new \Exception('update user account data function -- ' . 
         'error: ' . $error . ' - ' . 
         'unable to update your account!'); 

} // End of catch(Exception) block. 

if(($result === FALSE) || ($result !== 1)) { 

    throw new \Exception('update user account data function -- ' . 
         'update return value: ' . $result . ' - ' . 
         'unable to update your account!'); 

} // if(($result === FALSE) || ($result !== 1)) ... 

用戶表具有ID INT(11)柱,其是主密鑰,活性 TINYINT(1)柱,和activation_code VARCHAR(40)NULL列。

請注意$ USER_ID變量包含的「198」的字符串值,但在創建$ sqlSetStmnt值時,它被轉換爲int。

檢查的用戶表證實,有一個在用戶表中的一行與198在更新呼叫的時間ID列值。

帳戶運行更新呼叫時使用具有足夠的權限更改行活躍activation_code列值。

系統中沒有其他用戶或訪問數據庫,因此行上沒有任何鎖。

我使用X-調試檢查代碼,和的$ USER_ID$ sqlSetStmnt變量的值已正確設置爲我的預期值,即$結果設置爲0更新方法,並且更新方法調用不拋出異常。

順便說一句,有沒有必要使用變量綁定,因爲在$ USER_ID$ sqlSetStmnt變量的值不輸入由用戶,所以沒有可能性SQL注入的,或緩衝區溢出。

是否有某種方式從DBAL獲取有關爲什麼update方法返回0的信息?

謝謝。

+0

update返回實際更新的記錄數。你是說它實際上正在改變記錄並返回0嗎? – Cerad

+0

不,記錄似乎沒有更新。但是,由於有一行具有匹配的id列值,並且id列是該表的主鍵,所以我預計應該更新一行並將結果設置爲1而不是零。 –

+0

只有當activation_code不爲空和/或活動值不爲零時,該行纔會更新。基本的SQL數據庫東西。 – Cerad

回答

0

解決這個問題之前,我切換來自:

$result = $conn->update('users', $sqlSetStmnt, [ 'id' => (int)$user_id ]); 

到:

$sqlUpdateStmnt = 'UPDATE `users` SET field = value ' . 
        'WHERE `id` = ' . $user_id; 
$result = $conn->executeUpdate($sqlUpdateStmnt); 

,並得到完全相同的結果,其中一些更新將返回0行時有絕對是排在用戶表的id與$ user_id的值匹配。

我通過獲取現有行,然後只在set-clause中的字段與表中的同一列不同時更新行來解決此問題。

這告訴我,0返回值不是沒有匹配的行,而是更新沒有任何行的影響。

所以這個問題不是一個錯誤,就像誤解結果一樣。但是,如果使用update()方法來確定何時由於沒有匹配的行以及何時不做更改而導致更新失敗,那麼問題仍然存在。

我最終解決的方案是以預取爲代價來解決此問題,以驗證更新是否會影響行。就我而言,對於多用戶數據庫應用程序,預取實際上不成問題,因爲在更新嘗試進行更改之前,要更新的行可能已被其他用戶刪除。但是,如果兩個更新方法都更清楚地解釋了這一點,並且返回不同的值:0表示沒有受到影響的行,而FALSE表示沒有找到行。