【问题标题】:Using SELECT resultset to run UPDATE query with MySQL Stored Procedures使用 SELECT 结果集通过 MySQL 存储过程运行 UPDATE 查询
【发布时间】:2010-12-26 13:37:52
【问题描述】:

我正在尝试了解 MySQL 存储过程,我想检查用户登录凭据是否有效,如果有效,请更新用户在线状态:

-- DROP PROCEDURE IF EXISTS checkUser;
DELIMITER //
CREATE PROCEDURE checkUser(IN in_email VARCHAR(80), IN in_password VARCHAR(50))
BEGIN
    SELECT id, name FROM users WHERE email = in_email AND password = in_password LIMIT 1;
    -- If result is 1, UPDATE users SET online = 1 WHERE id = "result_id";
END //
DELIMITER ;

如何根据结果集的行数 == 1 或 id IS NOT NULL 来制作这个 if 语句?

【问题讨论】:

    标签: sql mysql stored-procedures resultset


    【解决方案1】:
    DELIMITER //
    CREATE PROCEDURE checkUser(IN in_email VARCHAR(80), IN in_password VARCHAR(50))
    BEGIN
        DECLARE tempId INT DEFAULT 0;
        DECLARE tempName VARCHAR(50) DEFAULT NULL;
        DECLARE done INT DEFAULT 0;
    
        DECLARE cur CURSOR FOR 
            SELECT id, name FROM users WHERE email = in_email AND password = in_password;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    
        OPEN cur;
    
        REPEAT
            FETCH cur INTO tempId, tempName;
            UPDATE users SET online = 1 WHERE id = tempId;
        UNTIL done  = 1 END REPEAT;
        CLOSE cur;
    
        SELECT tempName;
    END //
    DELIMITER ;
    

    注意:我没有测试过这个。 MySQL 可能不喜欢对当前打开游标的表进行 UPDATE。

    PS:你应该重新考虑how you're storing passwords


    重新评论RETURN vs. OUT vs. 结果集:

    RETURN 仅用于存储函数,不用于存储过程。当您想在另一个 SQL 表达式中调用例程时,使用存储函数。

    SELECT LCASE( checkUserFunc(?, ?) );
    

    您可以使用OUT 参数,但您必须先声明一个用户变量才能作为该参数传递。然后你必须选择那个用户变量来获取它的值。

    SET @outparam = null;
    CALL checkUser(?, ?, @outparam);
    SELECT @outparam;
    

    从存储过程返回结果集时,最简单的方法是使用SELECT 查询。

    【讨论】:

    • @Bill:使用 SELECT 与 RETURN 或 OUT 参数有什么好处吗?
    • 此答案中的第一个代码效果很好,谢谢您的回答。花了一段时间才明白,但现在我明白了。 :-) 现在我正在加密我的密码(不是 MD5 和一种方式)三次,其中两次使用不同的盐和不同的加密方法,所以我的想法是这就足够了。这样的字符串对我来说似乎很难暴力破解。这些东西也似乎是您给我的链接的摘要。你还有什么别的想法吗?
    • 不,如果您使用强大的哈希函数和每个用户的随机盐,那就足够了。我担心您以纯文本形式存储密码,因为您只是将in_password= 运算符的数据库字段进行比较。干杯!
    【解决方案2】:

    如果你有一个返回 1 的结果,你可以试试 if 语句 我查看了你的代码,似乎没有返回 true,所以你必须重构它, 如上所述,omg 写的确实如此,为什么您的选择查询中有一个限制 1,其中只有一个电子邮件地址可以存在? 像这样的

    update users set if(result==1,online=1,online=0) where email=emailadress
    

    【讨论】:

      【解决方案3】:

      用途:

      UPDATE USERS
         SET online = 1
       WHERE EXISTS(SELECT NULL
                      FROM USERS t
                     WHERE t.email = IN_EMAIL
                       AND t.password = IN_PASSWORD
                       AND t.id = id)
         AND id = 'result_id'
      

      为什么您的 SELECT 中有LIMIT 1?您真的希望电子邮件和密码不止一次地出现在数据库中吗?

      【讨论】:

      • 感谢您的快速回答,是的,LIMIT 1 没用,我将删除那个。还有一件事,我想将用户名(来自 SELECT 子查询)返回给 PHP 脚本。如何设置“返回”变量或创建子查询的返回结果集?
      • @Tirithen:您可以使用 RETURN 子句,也可以使用 IN OUT 参数。 OUT 参数意味着您向查询提供一个参数,它将/应该在其中填充,并且您可以在之后使用该参数。我稍后会更新更多信息,但现在请参阅:dev.mysql.com/doc/refman/5.0/en/create-procedure.html
      猜你喜欢
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      • 2013-05-19
      • 1970-01-01
      • 2010-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多