我有一个存储过程,它应该只检查电子邮件是否已经存在,并根据是否找到ID返回布尔值TRUE或FALSE
结果如下:
这是非常不正确的
这是程序:
CREATE PROCEDURE `EmailExists` (email VARCHAR(255), OUT output BOOL)
email_exists_proc:BEGIN
DECLARE existing_id CHAR(36);
DECLARE existing_email2 varchar(255);
DECLARE found_name varchar(255);
SELECT
`id`, `email`, `display_name` INTO existing_id, existing_email2, found_name
FROM `account`
WHERE `email` = email
LIMIT 1;
SELECT "EMail Exists", existing_email2, " == ", email, " ? ", existing_id, "name: ", found_name, existing_id IS NOT NULL;
SELECT existing_id IS NOT NULL INTO output;
END$$
这是非常基本的查询,这是电话:
CALL EmailExists("something@something.com", @exists);
SELECT @exists; # this returns 1 right now, it should be 0, but it's "finding" the provided email, somehow.
我错过了什么,我在这里做错了什么?为什么existing_email2
最终会镜像email
?该值不存在于表中。
答案 0 :(得分:1)
限定对查询中列的引用,因此用于引用列的标识实际上是引用列,而不是过程变量。
反引号用于转义标识符。反引号不能识别哪些标识符引用列以及哪些引用过程变量。
将表别名a
分配给帐户表,并使用a.
SELECT a.`id`
, a.`email`
, a.`display_name`
FROM `account` a
WHERE a.`email` = email
LIMIT 1
INTO existing_id
, existing_email2
, found_name
;
最佳做法是使用与列名称不同的过程变量的名称。
我个人的偏好是为程序值使用不同的名称
... PROCEDURE `EmailExists` (as_email VARCHAR(255), ...
^^
然后这个
WHERE a.`email` = as_email
对人类读者来说不那么模棱两可。
然后,为了获得原始代码中的行为,我们会写:
WHERE as_email = as_email
这使accounts
中的每一行都满足as_email
提供的任何非NULL值的条件更为明显。
参考:https://dev.mysql.com/doc/refman/5.7/en/stored-program-restrictions.html
存储例程中的名称冲突
相同的标识符可用于例程参数,局部变量和表列。此外,可以在嵌套块中使用相同的局部变量名称。例如:
在这种情况下,标识符不明确,并且适用以下优先规则:
局部变量优先于例程参数或表列。
常规参数优先于表格列。