【问题标题】:MYSQL stored procedure select statement select incorrect IDMYSQL存储过程select语句select不正确的ID
【发布时间】:2012-03-11 03:50:52
【问题描述】:

在存储过程方面,我不是知识最渊博的人,这个问题让我大吃一惊!

基本上我只是想运行一个简单的更新语句,但是当我在过程中运行它时,我选择更新行的用户 ID 不正确,但是如果我在过程之外运行相同的选择语句,它返回预期的结果。

DELIMITER $$
CREATE PROCEDURE catchUpBbs_Users()
  BEGIN
    DECLARE done INT DEFAULT 0;
    DECLARE deleteUser, keepUser VARCHAR(255);
    DECLARE id INT;
    DECLARE cur1 CURSOR FOR SELECT u.username, b.username, b.id from users u RIGHT     JOIN bbs_users b ON u.username = b.username WHERE u.username IS NULL;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;     
    OPEN cur1;
        allusers: LOOP 
            FETCH cur1 INTO keepUser, deleteUser, id;
            IF done THEN 
                LEAVE allusers; 
            END IF;
IF deleteUser != 'anonymous' THEN 

-- This is where the problems start

-- Just for test purposes, returns correct id and username 
SELECT id, username FROM bbs_users WHERE username = deleteUser; 

-- Just for test purposes, return INCORRECT id, but the CORRECT username  
SELECT id, username FROM bbs_users WHERE username = 'anonymous'; 

-- The update statement that does not work as I want it to, sets the user_id to be what it already it, so no updates occur
UPDATE bbs_posts SET user_id = (SELECT id FROM bbs_users WHERE username = 'anonymous') WHERE user_id = (SELECT id FROM bbs_users WHERE username = deleteUser);

-- delete the user from the bbs_users table
DELETE FROM bbs_users WHERE username = deleteUser;

END IF;
    END LOOP allusers;
    CLOSE cur1;
END;

$$
DELIMITER ;

当我调用该过程时,两个测试选择语句返回:

1) 这些结果都是正确的

 SELECT id, username FROM bbs_users WHERE username = deleteUser;
 +------+----------+
 | id   | username |
 +------+----------+
 |   13 | deleteme |
 +------+----------+

2) ID不正确,但是用户名不正确,ID应该是1

 SELECT id, username FROM bbs_users WHERE username = 'anonymous'; 
 +------+-----------+
 | id   | username  |
 +------+-----------+
 |   13 | anonymous |
 +------+-----------+

当我运行相同的程序时,减去变量,过程外的 select 语句都返回正确的结果

1) 这些结果都是正确的

SELECT id, username FROM bbs_users WHERE username = 'deleteme';
+----+----------+
| id | username |
+----+----------+
| 13 | deleteme |
+----+----------+

2) 这些结果都是正确的

SELECT id, username FROM bbs_users WHERE username = 'anonymous';
+----+-----------+
| id | username  |
+----+-----------+
|  1 | anonymous |
+----+-----------+

我做错了什么?在使用存储过程时,在选择和变量方面有什么我错过的吗?

任何帮助或建议将不胜感激

【问题讨论】:

    标签: mysql database stored-procedures select


    【解决方案1】:

    问题是您在游标中定义了一个名为 id 的标量变量,并且您正在选择它,因此游标内的两个 select 语句都使用该存储的标量值来引用 id .

    为了获得“正确”的值,您需要消除所有歧义:

    -- Just for test purposes, returns correct id and username 
    SELECT b.id, b.username FROM bbs_users b WHERE b.username = deleteUser; 
    
    -- Just for test purposes, return INCORRECT id, but the CORRECT username  
    SELECT b.id, b.username FROM bbs_users b WHERE b.username = 'anonymous'; 
    

    【讨论】:

    • 谢谢!这解决了我的问题,你教会了我一些新东西。
    【解决方案2】:

    你有没有试过在 end if 和 end 循环之前重复句子“FETCH cur1 INTO keepUser, deleteUser, id”...

    【讨论】:

      【解决方案3】:

      以下工作是否更好。清理了您多次有效执行相同查询的位置。抱歉,如果我误解了这个问题 - 但如果我理解正确,那么下面的查询应该会更有效地运行。还会删除所有不明确的字段名称。

      DELIMITER $$
      CREATE PROCEDURE catchUpBbs_Users()
        BEGIN
          DECLARE done INT DEFAULT 0;
          DECLARE oldID INT;
          DECLARE newID INT;
          DECLARE cur1 CURSOR FOR 
              SELECT b.id 
              FROM users u 
              RIGHT JOIN bbs_users b 
              ON u.username = b.username 
              WHERE u.username IS NULL;
      
          DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;     
      
          // Get the new id
          SELECT id INTO newID FROM bbs_users WHERE username = 'anonymous';
      
          OPEN cur1;
              allusers: LOOP 
                  FETCH cur1 INTO oldID;  // b.id
      
                  IF done THEN 
                      LEAVE allusers; 
                  END IF;
      
                  IF deleteUser != 'anonymous' THEN 
      
                      -- Just for test purposes, returns correct id and username 
                      SELECT id, username FROM bbs_users WHERE id = oldID; 
      
                      -- Just for test purposes, return INCORRECT id, but the CORRECT username  
                      SELECT id, username FROM bbs_users WHERE id = newID; 
      
                      UPDATE bbs_posts SET user_id = newID WHERE user_id = oldID;
      
                      -- delete the user from the bbs_users table
                      DELETE FROM bbs_users WHERE id = oldID;
      
                  END IF;
              END LOOP allusers;
          CLOSE cur1;
      END;
      
      $$
      DELIMITER ;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-16
        • 1970-01-01
        • 2019-01-14
        相关资源
        最近更新 更多