2012-02-20 69 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 ;