简体   繁体   中英

MySQL Stored Procedure select statement finding inaccurate result

I have a stored procedure that's supposed to simply check if an email already exists and return a boolean TRUE or FALSE based on if an ID is found

The table looks like this: 在此处输入图片说明

The result is this:

在此处输入图片说明

Which is wildly incorrect

Here's the procedure:

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$$

It's pretty basic query, here's the call:

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. 

What I missing, what am I doing wrong here? Why does existing_email2 end up mirroring email ? The value doesn't exist in the table.

Qualify the references to columns in the queries, so identifiers meant to reference a column are actually referencing a column, rather than a procedure variable.

The backticks are used to escape identifiers. The backticks do not identify which identifiers reference columns and which reference procedure variables.

Assigning table alias a to the account table, and qualifying all column references with 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
  ;

Best practice is to use names for procedure variables that differ from column names.

My personal preference would be to use a different name for the procedure value

... PROCEDURE `EmailExists` (as_email VARCHAR(255), ...
                             ^^

And then this

   WHERE a.`email` = as_email

is less ambiguous to the human reader.

Then, to get the behavior in the original code, we would have written:

   WHERE as_email = as_email

which makes it a little more obvious why every row in accounts satisfies that condition for any non-NULL value provided for as_email .


Reference: https://dev.mysql.com/doc/refman/5.7/en/stored-program-restrictions.html

Name Conflicts within Stored Routines

The same identifier might be used for a routine parameter, a local variable, and a table column. Also, the same local variable name can be used in nested blocks. For example:

In such cases, the identifier is ambiguous and the following precedence rules apply:

  • A local variable takes precedence over a routine parameter or table column.

  • A routine parameter takes precedence over a table column.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM