结束while循环缺少分号

时间:2016-07-21 17:48:26

标签: mysql stored-procedures while-loop

我创建了一个简单的存储过程,它循环遍历一个表的行并将它们插入另一个表中。由于某种原因,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 个答案:

答案 0 :(得分:1)

当我遇到大块代码中的问题并且无法找到问题的位置时,我通常会将我的代码拆分为较小的块并一次测试一个:

测试1:

DELIMITER $$

DROP PROCEDURE IF EXISTS `testLoop`$$

CREATE PROCEDURE testLoop()
BEGIN
END $$

DELIMITER ;

没有错误:程序声明和分隔符的使用是可以的。

测试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查询和变量赋值都可以。

测试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部分,不应该有{{1如果要从另一个表中插入值,则部分:

VALUES

现在,程序创建完成且没有错误。

测试6:

但是,执行该过程时,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 ; 查询会出现语法错误:MySQL不接受将SELECT与变量一起使用。
要使其工作,您需要使用prepared statement

LIMIT

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

  

因为局部变量仅在存储程序期间在范围内   执行,准备好的陈述中不允许引用它们   在存储的程序中创建。准备好的声明范围是   当前会话,而不是存储的程序,所以声明可以   程序结束后执行,此时变量不会   更长的范围。例如,SELECT ... INTO local_var不能   用作准备好的声明。此限制也适用于存储   程序和功能参数。

要解决此问题,请使用会话变量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; 而不是本地变量@i

程序的最终版本

i

您可以应用相同的方法来调试许多复杂的编程问题:从简单版本的代码开始,对其进行测试。如果它再次使用更多代码进行测试,如果没有在继续之前找到并修复错误。