Reputation: 8734
Here is my stored procedure:
CREATE DEFINER=`root`@`localhost` PROCEDURE `User_Confirm`(id INT)
BEGIN
UPDATE
`User`
SET
ConfirmedAt = UTC_TIMESTAMP()
WHERE `Id` = id ;
END$$
If I run
`CALL `User_Confirm`(19);`
I get this message saying the whole table has been updated:
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
User 19 does exist, why is this happening
If I run this extraction from the stored procedure only one row gets updated as expect, so it definitely has something to do with the stored procedure:
UPDATE
`User`
SET
ConfirmedAt = UTC_TIMESTAMP()
WHERE `Id` = 19 ;
Upvotes: 3
Views: 1414
Reputation: 108380
I think MySQL is ignoring your input argument, because the name matches the name of a column in one of the tables referenced in the UPDATE statement.
Let me rephrase that...
you think your predicate is of the form:
WHERE col = input_argument
But MySQL is actually seeing your predicate as:
WHERE col = col
or, as
WHERE input_argument = input_argument
The latter will be true for EVERY row in the table, the former will be true for every row that has a a non-null value stored in col. (A simple test will reveal whether it's the column reference takes precedence, or a variable reference takes precedence. I do know that in Oracle, DML statements in PL/SQL blocks, column references take precedence over PL/SQL variables, and there is NO warning.)
A quick test would be rename the input argument, so that it doesn't match any column name.
Another workaround may be to use a MySQL user variable, (be careful of implicit datatype conversions), e.g.
CREATE PROCEDURE `User_Confirm`(parameterId INT)
BEGIN
SET @argId := parameterId;
UPDATE `User`
SET ConfirmedAt = UTC_TIMESTAMP()
WHERE `Id` = @argId ;
END$$
Upvotes: 1
Reputation: 1269613
Your problem is that the parameter name to the stored procedure is the same as the column name. It is a good idea to prefix parameter names with something obvious. Try this:
CREATE DEFINER=`root`@`localhost` PROCEDURE `User_Confirm`(param_id INT)
BEGIN
UPDATE `User`
SET ConfirmedAt = UTC_TIMESTAMP()
WHERE `Id` = param_id ;
END$$
Upvotes: 4
Reputation: 11096
probably self referencing on id, try:
.... WHERE `USER`.`Id` = id ;
Upvotes: 3