Symfony2 DBAL Update方法返回0

时间:2017-12-02 23:01:02

标签: mysql symfony sql-update dbal

我得到一个奇怪的结果,其中一个更新方法(http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html#update)调用激活/停用我的mySQL数据库中的站点用户帐户有时不会更新并返回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。

检查用户表格确认用户表格中有一行,其中 id 列值为198时更新电话。

运行更新调用时使用的帐户具有足够的权限来更改行活动 activation_code 列值。

系统中没有其他用户或访问数据库,因此该行上没有任何锁定。

我使用x-debug检查了代码,并且 $ user_id $ sqlSetStmnt 变量的值已正确设置为我预期的值,即更新方法将> $ result 设置为0,并且更新方法调用没有抛出异常。

顺便说一下,不需要使用变量绑定,因为 $ user_id $ sqlSetStmnt 变量中的值不是由用户输入的,所以没有可能SQL注入或缓冲区溢出。

有没有办法从DBAL获取有关更新方法返回0的原因的信息?

谢谢。

1 个答案:

答案 0 :(得分:1)

在解决此问题之前,我改用:

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

为:

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

并得到完全相同的结果,其中一些更新将返回0行,当在users表中肯定有一行,其id与$ user_id的值匹配时。

我通过获取现有行来解决这个问题,然后只在set-clause中的字段与表中的相同列不同时才更新行。

这告诉我0返回值并不是没有匹配的行,但是更新的对任何行都没有影响。

所以这个问题不是一个错误,而是对结果的误解。但是,使用update()方法时,如果由于没有匹配的行以及未进行任何更改而确定更新失败的时间,则问题仍然存在。

我最终的解决方案是以预取为代价来解决这个问题,以验证更新是否会影响行。在我的情况下,对于多用户数据库应用程序,预取实际上并不是一个问题,因为在更新尝试进行更改之前,另一个用户可能已删除了要更新的行。但是,如果两个更新方法更清楚地解释了这一点并返回不同的值,那将是很好的:0表示没有受影响的行,FALSE表示没有找到行。