这是我的存储过程:
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 ;
答案 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$$