Symfony2 DBAL更新方法返回0

Symfony2 DBAL更新方法返回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

解决这个问题之前,我切换来自:

$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表示没有找到行。