2016-07-21 84 views
0

我創建了一個簡單的存儲過程,循環遍歷一個表的行並將它們插入到另一個表中。由於某些原因,END WHILE循環丟失了一個分號錯誤。所有的代碼看起來都是正確的,所有的分隔符都設置正確。我只是不知道爲什麼它會拋出這些錯誤,谷歌搜索這個問題只指出我不適當使用分隔符的答案,但沒有更多。你能幫忙的話,我會很高興!End while循環缺少分號

USE test; 
DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
DECLARE i INT DEFAULT 0; 
SELECT COUNT(*) FROM `test_dropship_upload` INTO n; 
SET i=0; 
WHILE i<n DO 
    INSERT INTO `test_2` (sku, qty) VALUES(sku, qty) FROM `test_dropship_upload` LIMIT i,1; 
    SET i = i + 1; 
END WHILE; 

END $$ 

DELIMITER ; 

回答

1

當我堅持的問題的一大塊代碼,並不能找到問題的所在,我通常是在更小的塊分割我的代碼和測試他們一次一個:

測試1:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE testLoop() 
BEGIN 
END $$ 

DELIMITER ; 

沒有錯誤:過程聲明和使用分隔符的是OK。

測試2:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
DECLARE i INT DEFAULT 0; 
END $$ 

DELIMITER ; 

沒有錯誤:變量的過程內聲明確定。

測試3:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
DECLARE i INT DEFAULT 0; 
SELECT COUNT(*) FROM `test_dropship_upload` INTO n; 
SET i=0; 
END $$ 

DELIMITER ; 

沒有錯誤:在SELECT查詢和變量賦值都OK。

測試4:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
DECLARE i INT DEFAULT 0; 
SELECT COUNT(*) FROM `test_dropship_upload` INTO n; 
SET i=0; 
WHILE i<n DO 
    SET i = i + 1; 
END WHILE; 

END $$ 

DELIMITER ; 

沒有錯誤:在WHILE循環正常。

測試5:

現在唯一的未經測試部分是INSERT查詢:

INSERT INTO `test_2` (sku, qty) VALUES(sku, qty) FROM `test_dropship_upload` LIMIT i,1; 

尋找一個在文檔INSERTINSERT ... SELECT,我們可以看到,您的查詢是無效的:它顯然缺少SELECT部分,如果要插入另一個表中的值,則不應有VALUES部分:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
DECLARE i INT DEFAULT 0; 
SELECT COUNT(*) FROM `test_dropship_upload` INTO n; 
SET i=0; 
WHILE i<n DO 
    INSERT INTO `test_2` (sku, qty) SELECT sku, qty FROM `test_dropship_upload` LIMIT i, 1; 
    SET i = i + 1; 
END WHILE; 

END $$ 

DELIMITER ; 

程序創建現在完成而沒有錯誤。

測試6:

但是,你會在執行過程時,得到的SELECT查詢語法錯誤:MySQL不接受使用LIMIT一個變量。
要使其工作,您需要使用prepared statement

PREPARE stmt FROM "INSERT INTO `test_2` (sku, qty) SELECT sku, qty FROM `test_dropship_upload` LIMIT ?, 1"; 
EXECUTE stmt using @i; 
DEALLOCATE PREPARE stmt; 

It is also not allowed to used local variables in prepared statements

因爲局部變量只在存儲程序 執行的範圍,對它們的引用在存儲程序中創建的預處理語句 是不允許的。準備報表範圍是 當前會話,而不是存儲的程序,這樣的聲明可能是 執行的程序結束後,此時變量將不 再範圍。例如,SELECT ... INTO local_var不能是 用作預準備語句。這一限制也適用於存儲的程序和功能參數 。

爲了解決這個問題,使用一個會話變量@i而不是局部變量i的:

程序的最終版本

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `testLoop`$$ 

CREATE PROCEDURE `testLoop`() 
BEGIN 
DECLARE n INT DEFAULT 0; 
SELECT COUNT(*) FROM `test_dropship_upload` INTO n; 
SET @i=0; 
WHILE @i<n DO 
    PREPARE stmt FROM "INSERT INTO `test_2`(sku, qty) SELECT sku, qty FROM `test_dropship_upload` LIMIT ?, 1"; 
    EXECUTE stmt USING @i; 
    DEALLOCATE PREPARE stmt; 
    SET @i = @i + 1; 
END WHILE; 

END $$ 

DELIMITER ; 

您可以將同樣的方法來調試許多複雜的編程問題:從簡單版本的代碼開始,對其進行測試。如果它再次用更多代碼進行測試,則在繼續之前未找到並修復錯誤。

+0

完全看過去,謝謝你的幫助,一切都很好 –