2012-02-20 68 views
3

当我谈到存储过程时,我不是最懂得知识的人,而这个问题正在让我大跌眼镜!MYSQL存储过程选择语句选择不正确的ID

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

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

当我运行相同的,减去变量,选择语句之外该过程都返回正确的结果

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

我在做什么错?在使用存储过程时,在选择和变量时是否会漏掉某些东西?

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

回答

2

的问题是,你有你的光标定义了一个名为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'; 
+0

谢谢!这解决了我的问题,并且你教了我新的东西。 – letsgettechnical 2012-02-20 19:52:46

0

你tryed重复了一句“Fetch CUR1 INTO keepUser,deleteUser,ID”结束后,当且在结束循环之前...

0

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

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 ;