MySQL更新where子句被忽略

时间:2014-01-16 22:52:34

标签: mysql

这是我的存储过程:

CREATE DEFINER=`root`@`localhost` PROCEDURE `User_Confirm`(id INT)
BEGIN
  UPDATE 
    `User` 
  SET
    ConfirmedAt = UTC_TIMESTAMP() 
  WHERE `Id` = id ;
END$$

如果我跑

`CALL `User_Confirm`(19);`

我收到此消息说整个表已更新:

1 queries executed, 1 success, 0 errors, 0 warnings

Query: call `User_Confirm`(19)

11 row(s) affected

Execution Time : 0.040 sec
Transfer Time  : 0.145 sec
Total Time     : 0.186 sec

用户19确实存在,为什么会发生这种情况


更新

如果我从存储过程中运行此提取,只有一行按预期更新,所以它肯定与存储过程有关:

 UPDATE 
    `User` 
  SET
    ConfirmedAt = UTC_TIMESTAMP() 
  WHERE `Id` = 19 ;

4 个答案:

答案 0 :(得分:3)

可能在id上自我引用,请尝试:

.... WHERE `USER`.`Id` = id ;

答案 1 :(得分:3)

您的问题是存储过程的参数名称与列名称相同。为参数名称添加明显的前缀是个好主意。试试这个:

CREATE DEFINER=`root`@`localhost` PROCEDURE `User_Confirm`(param_id INT)
BEGIN
  UPDATE `User` 
      SET ConfirmedAt = UTC_TIMESTAMP() 
      WHERE `Id` = param_id ;
END$$

答案 2 :(得分:1)

MySQL是某些事情*不区分大小写,这是原因吗?

答案 3 :(得分:1)

我认为MySQL忽略了您的输入参数,因为该名称与UPDATE语句中引用的其中一个表中的列名匹配。

让我重新说一下......

您认为您的谓词具有以下形式:

WHERE col = input_argument 

但MySQL实际上将您的谓词视为:

WHERE col = col

或,如

WHERE input_argument = input_argument

后者对于表中的每一行都是正确的,前者对于存储在col中的非空值的每一行都是如此。 (一个简单的测试将揭示它是列引用优先,还是变量引用优先。我知道在Oracle中,PL / SQL块中的DML语句,列引用优先于PL / SQL变量,并且没有警告。)

快速测试会重命名输入参数,因此它与任何列名都不匹配。

另一种解决方法可能是使用MySQL用户变量,(注意隐式数据类型转换),例如。

CREATE PROCEDURE `User_Confirm`(parameterId INT)
BEGIN
  SET @argId := parameterId;
  UPDATE `User` 
     SET ConfirmedAt = UTC_TIMESTAMP()
   WHERE `Id` = @argId ;
END$$