当我的mysql存储过程没有找到任何结果时,我想抛出一个异常

Posted

技术标签:

【中文标题】当我的mysql存储过程没有找到任何结果时,我想抛出一个异常【英文标题】:I want to throw an exception when my mysql stored procedure doesn't find any results 【发布时间】:2021-05-21 19:45:37 【问题描述】:

如果找不到数据,我很难找到从存储过程中引发异常的方法。

我需要一种方法来检查 if 语句中的查询结果。

如果计数为 0,则抛出异常。如果有数据则返回数据。

CREATE DEFINER=`adminHC`@`%` PROCEDURE `find_user_with_credentials`(
    IN `usernameIN` VARCHAR(45)
    , IN `encryptedpwIN` VARCHAR(45)
)
BEGIN
    SELECT *
    FROM (SELECT distinct
            userid
            ,firstname
            ,lastname
            ,publicname
            ,email
            ,addressid
            ,create_date
            ,update_date
            ,active
        FROM dev_users
        WHERE (email = usernameIN OR (
                publicname IS NOT null AND
                publicname = usernameIN
            ))
            AND encryptedpw = encryptedpwIN
            AND active = 1) user;

    IF count(user) > 0 THEN
        SELECT user;
    ELSE
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = "Invalid username or password",
        mysql_ERRNO = 403;  
    END IF;

END

【问题讨论】:

什么是@user 那是我不知道自己在做什么。我希望@user 引用名为 user 的查询的结果。 一个变量只能保存一个值,不能保存整个结果表。 加密密码的良好做法是将随机盐作为密码的一部分。这意味着您可以读取加密的密码,并使用它来加密输入的明文密码并查看它们是否匹配,但是您不能做您在这里似乎拥有的事情,加密明文密码然后查看它是否与密码中的内容匹配数据库。 我在服务器上使用了盐。用户输入的密码经过加密,并与数据库中保存的加密密码进行核对。 【参考方案1】:

SELECT COUNT(*) 查询开始并检查其结果。

CREATE DEFINER=`adminHC`@`%` PROCEDURE `find_user_with_credentials`(
    IN `usernameIN` VARCHAR(45)
    , IN `encryptedpwIN` VARCHAR(45)
)
BEGIN
    IF (SELECT COUNT(*)
        FROM dev_users
        WHERE (email = usernameIN OR (
                publicname IS NOT null AND
                publicname = usernameIN
            ))
            AND encryptedpw = encryptedpwIN
            AND active = 1) > 0
    THEN SELECT
            userid
            ,firstname
            ,lastname
            ,publicname
            ,email
            ,addressid
            ,create_date
            ,update_date
            ,active
        FROM dev_users
        WHERE (email = usernameIN OR (
                publicname IS NOT null AND
                publicname = usernameIN
            ))
            AND encryptedpw = encryptedpwIN
            AND active = 1;
    ELSE
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = "Invalid username or password",
        MYSQL_ERRNO = 403;  
    END IF;
END

也不需要SELECT * 包装器。而且我怀疑您是否需要SELECT DISTINCT,因为我假设您不能有多个具有相同userid 的行,并且查询中没有任何内容会重复行。

如果查询过于昂贵而无法执行两次,您可以执行一次并将结果保存在临时表中。然后可以使用SELECT COUNT(*) FROM temp_table查看是否有结果,最后SELECT * FROM temp_table返回数据。

【讨论】:

我喜欢这个。将整个事情放在 if 语句中更有意义。我正在尝试使用临时表方法,但我无法弄清楚。我试图避免两次运行查询。我会试试看。非常感谢您的快速回复。 我工作得很好。再次感谢。最终制作了一个临时表并在随后的 if 语句中检查该计数。

以上是关于当我的mysql存储过程没有找到任何结果时,我想抛出一个异常的主要内容,如果未能解决你的问题,请参考以下文章

错误创建存储过程 MySQL

MySQL 过程将空结果返回给 PHP

将@@ rowcount分配给SQL Server存储过程中的变量

无法从 mysql 存储过程中看到任何值

ERROR 1172 (42000): 结果在 mysql 存储过程中包含多于一行

MySQL存储过程没有值检索