mysql。存储过程错误 1328

Posted

技术标签:

【中文标题】mysql。存储过程错误 1328【英文标题】:mysql. Stored Procedure Error 1328 【发布时间】:2017-11-13 13:26:53 【问题描述】:

这真的让我很困惑。我正在将一个简单的过程从informix 转换为mysql。它的基本作用是告诉我事件表和日历表中的下一个事件是什么。在informix中,过程很简单。

FOREACH
SELECT  date,weekno,event
INTO    l_date,l_week,l_event
FROM    event,calendar
WHERE   dayno = dayno
AND     date = l_today
AND     start >= l_now
UNION
SELECT  date,weekno,event
FROM    event,calendar
WHERE   dayno = dayno
AND     date > l_today
UNION
SELECT  TODAY,9999,9999
FROM    event,calendar
WHERE   dayno   = dayno
AND     event = (SELECT MAX(event) FROM event)
ORDER BY 3

if l_event = 9999 then <error> end if;
EXIT FOREACH
END FOREACH

所以基本上查询会找到下一个事件并返回它。 l_today 和 l_event 是传递的参数。等到mysql版本。

looper: BEGIN
    DECLARE curs1 CURSOR FOR
        SELECT CONCAT("SELECT date, weekno, event FROM event INNER JOIN calendar ON dayno = dayno",
                " WHERE date = '", lv_today ,"' AND start >= '", lv_time ,"'",
                " UNION SELECT date, weekno, event FROM event INNER JOIN calendar ON dayno = dayno WHERE date > '", lv_today ,"'",
                " UNION SELECT DATE(NOW()) AS date, 9999 AS weekno, 9999 AS event FROM event INNER JOIN calendar ON dayno = dayno",
                " WHERE (SELECT MAX(event) FROM event) ORDER BY event ");

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE;

    OPEN curs1;
    loop1: LOOP
        FETCH curs1 INTO ldate, lweek, levent;
        SELECT ldate, lweek, levent;
        LEAVE looper;
    END LOOP loop1;
END;

我没有检查其余的方法是否有效,因为我收到了这个错误:

    FETCH 变量的数量不正确。

这是否意味着我为每个查询返回声明了不同的变量?我是mysql的新手。如果是这种情况,解决这个难题的最佳方法是什么?我也更改了列名和表名。

非常感谢

【问题讨论】:

SELECT CONCAT('SELECT 1, 2, 3 FROM DUAL');SELECT 1, 2, 3 FROM DUAL;是有区别的,见db-fiddle。 你在循环中有SELECT ldate, lweek, levent;。这些选定的值存储在哪里?或者那是在做什么?从 Informix 的角度来看,这对我来说似乎是最奇特的。 【参考方案1】:
looper: BEGIN
DECLARE curs1 CURSOR FOR
SELECT eve_date, dia_weekno, eve_event 
FROM game_event 
INNER JOIN stan_calendar ON eve_abs_dayno = dia_abs_dayno
WHERE eve_date = lv_today
AND eve_start >= lv_time
UNION 
SELECT eve_date, dia_weekno, eve_event 
FROM game_event 
INNER JOIN stan_calendar ON eve_abs_dayno = dia_abs_dayno 
WHERE eve_date > lv_today
UNION SELECT DATE(NOW()) AS eve_date, 9999 AS dia_weekno, 9999 AS eve_event 
FROM game_event 
INNER JOIN stan_calendar ON eve_abs_dayno = dia_abs_dayno
WHERE (SELECT MAX(eve_event) FROM game_event) ORDER BY eve_event;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE;

OPEN curs1;

curs_loop: LOOP
    FETCH curs1 INTO lv_date, lv_week, lv_event;

    SELECT lv_date, lv_week, lv_event;
    LEAVE looper;

    CLOSE curs1;
END LOOP curs_loop;

感谢您回答我的问题,我已将其恢复为我认为的样子......现在它可以工作了。这是完整的循环。

【讨论】:

这似乎是对问题的评论,因此应该编辑到问题中,而不是作为答案。您可以编辑自己的问题。不要破坏答案所依赖的任何东西——但我不确定这是一个问题。【参考方案2】:

https://dev.mysql.com/doc/refman/5.7/en/fetch.html SELECT 语句检索到的列数必须与 FETCH 语句中指定的输出变量数相匹配 所以是的,但实际上您只选择了 1 个连接字符串 - 我认为您的第一个问题是不需要连接、括号或引号的选择语法(除非您出于某种原因尝试创建准备好的语句 - 即使您怀疑代码是否正确)

简单光标

DROP PROCEDURE IF EXISTS EC;
DELIMITER $$

CREATE  PROCEDURE `EC`(
    IN `inemp_no` varchar(255)

)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
LOOPER:begin
DECLARE done INT DEFAULT FALSE;
declare ename varchar(20);
declare esalary int default 0;
declare emp_cursor CURSOR FOR 
 SELECT last_name,salary FROM employees where emp_no= inemp_no ;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

open emp_cursor;
read_loop: loop
        fetch emp_cursor into ename,esalary;
        if done then leave read_loop; end if;
        insert into debug_table (msg) values(concat('employee:',ename,' earns:',esalary));
end loop;
close emp_cursor;
end $$

DELIMITER ;



MariaDB [sandbox]> truncate table debug_table;
Query OK, 0 rows affected (0.22 sec)

MariaDB [sandbox]> call ec(2);
Query OK, 0 rows affected (0.03 sec)

MariaDB [sandbox]> select * from debug_table;
+----+--------------------------+------+
| id | msg                      | MSG2 |
+----+--------------------------+------+
|  1 | employee:BBB earns:39500 | NULL |
+----+--------------------------+------+
1 row in set (0.00 sec)

【讨论】:

您好,感谢您的回复。 concat 的原因是程序总是返回 9999。所以,我假设传递给循环查询的参数没有正常工作,就好像我在程序之外执行相同的查询一样,我得到了另一个答案。因为查询是在一个循环中,所以这似乎需要以一种特定的方式来准备,这就是我试图弄清楚的,因为语法与我习惯的完全不同。 你的程序一团糟。标签循环器:什么都不做,它只是一个标签。如果要在过程中执行许多语句,则需要 begin..end 块。 leave looper 语句不正确,因为您要离开的循环是 curs_loop。如果您使用变量(lv_date、lv_week、lv_event),那么您必须在开始语句之后立即声明它们。我在答案中添加了一个简单的程序。 感谢您的回复,这只是一个更大程序的sn-p。在此之上还有一个对另一个过程的调用,但这工作正常。外部循环“looper”是我想退出的循环,很抱歉造成混乱,这很好用。我真正的问题是 SQL 的准备工作,它看起来确实是一团糟。

以上是关于mysql。存储过程错误 1328的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 存储过程错误处理

错误创建存储过程 MySQL

MySQL 存储过程错误处理

MySql存储过程调用错误

MySQL存储过程错误处理

mysql插入存储过程抛出错误