MySQL游标无法使用存储过程

时间:2016-03-28 04:10:37

标签: mysql

我在mysql中编写了存储过程。本网站遵循了步骤http://www.mysqltutorial.org/mysql-cursor/ 但它不起作用。这是代码

DELIMITER $$

USE `hr`$$

DROP PROCEDURE IF EXISTS `at_getShift`$$

CREATE DEFINER=`root`@`%` PROCEDURE `at_getShift`()

BEGIN

    DECLARE finished BOOLEAN DEFAULT FALSE;
    DECLARE employeeID VARCHAR(255);-- Default "";

    -- declare cursor for employee email
    DECLARE hrEmployee CURSOR FOR SELECT EmployeeID FROM h_employees WHERE EmployeeID IN ('100013', '100014');

    -- declare NOT FOUND handler
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = TRUE;

    DROP TABLE IF EXISTS temp;
    CREATE TABLE IF NOT EXISTS temp(
      `Code` VARCHAR(255)
    );  

    OPEN hrEmployee;

    get_employee: LOOP
    FETCH hrEmployee INTO employeeID;
    INSERT INTO temp(`Code`) VALUE (employeeID);
    -- If no any row, leave loop
    IF finished THEN 
        INSERT INTO temp(`Code`) VALUE ("112");
        CLOSE hrEmployee;
        LEAVE get_employee;
    END IF;

    -- insert temp
    INSERT INTO temp(`Code`) VALUE ("111");
    END LOOP get_employee;

    SELECT * FROM temp;
END$$

DELIMITER ;

执行:CALL at_getShift();

结果是:

  

临时表中有2行(1为空,1为112)

请帮助我解决这个问题。

1 个答案:

答案 0 :(得分:2)

在MySQL存储程序的SQL语句中,对过程变量的引用优先于对列的引用。

也就是说,当SQL语句中的标识符与过程变量匹配时,SQL语句引用过程变量。

使用表中的表名或表别名引用列限定的引用,即使存在具有相同名称的过程变量。

演示:

 CREATE TABLE emp (id INT);
 INSERT INTO emp (id) VALUES (101),(102);

 DELIMITER $$


 CREATE PROCEDURE foo()
 BEGIN
   DECLARE id INT DEFAULT 3;

   -- this query returns 3 for all rows in emp
   -- because "id" is a reference to the procedure variable
   SELECT id FROM emp WHERE id = 3;

   -- this query returns no rows
   -- because "id" is a reference to the procedure variable
   SELECT id FROM emp WHERE id = 101;

   -- this query references columns in the table because
   -- references to "id" are qualified
   SELECT t.id FROM emp t WHERE t.id = 101;

 END$$

 DELIMITER ;


 CALL foo;

第一个查询返回emp

中所有行的过程变量值
    id
 -----
     3
     3

第二个查询不返回任何行

    id
 -----

第三个查询返回引用" id"表中的列:

    id
 -----
   101 

外卖是两个"最佳实践":

  • 限定过程中SQL语句中的所有列引用

  • 过程变量名称应与列名称不同,通常的模式是在变量上使用区别前缀。作为一个简单的例子:v_idv_name

这两种做法都使人类读者更容易破译程序。

过程变量的独特命名确实可以减少冲突的可能性,但不会使最佳实践无效#34;限定SQL语句中的所有列引用。这两者都有助于使作者的意图对人类读者更清楚。

编辑:

我试图回答我认为你问的问题......"为什么我的程序没有按照我的期望去做?"。

除了您提出的问题的答案之外......您的程序似乎正在执行的操作(使用一组行填充临时表),该操作可以更快地执行等等高效通过将行作为一个集处理,而不是为每一行发出痛苦低效的单个插入语句。在性能方面,游标循环处理RBAR(逐行排列)会吃掉你的午餐。还有你的午餐盒。

DELIMITER $$

CREATE PROCEDURE `at_getShift_faster`()
BEGIN
   -- ignore warning message when dropping a table that does not exist
   DECLARE CONTINUE HANDLER FOR 1305 BEGIN END;
   DROP TABLE IF EXISTS temp;
   CREATE TABLE IF NOT EXISTS temp(`Code` VARCHAR(255));  

   INSERT INTO temp (`Code`)  
     SELECT h.EmployeeID 
       FROM h_employees h
      WHERE h.EmployeeID IN ('100013', '100014')
   ;

   SELECT * FROM temp;
END$$

DELIMITER ;