當我堅持的問題的一大塊代碼,並不能找到問題的所在,我通常是在更小的塊分割我的代碼和測試他們一次一個:
測試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;
尋找一個在文檔INSERT和INSERT ... 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 ;
您可以將同樣的方法來調試許多複雜的編程問題:從簡單版本的代碼開始,對其進行測試。如果它再次用更多代碼進行測試,則在繼續之前未找到並修復錯誤。
完全看過去,謝謝你的幫助,一切都很好 –