为啥 MySQL WorkBench 在使用游标时忽略了我的 SIGNAL SQLSTATE?

Posted

技术标签:

【中文标题】为啥 MySQL WorkBench 在使用游标时忽略了我的 SIGNAL SQLSTATE?【英文标题】:Why MySQL WorkBench is ignoring my SIGNAL SQLSTATE when using cursors?为什么 MySQL WorkBench 在使用游标时忽略了我的 SIGNAL SQLSTATE? 【发布时间】:2021-12-31 03:10:49 【问题描述】:

首先,代码有点乱,但我不能帮它分配。回到问题,如果 aux SIGNAL SQLSTATE '02000' SET MESSAGE_TEXT = 'Error: Algún integrante del escuadrón no tiene desbloqueados los dragones necesarios para matar a este dragón'; 时它不起作用。即使我把它放在其他任何东西之前,它也会把它当作什么都没有。我检查了代码,它似乎正在完全执行(它没有退出游标,而是进入了所有的 if),除了 SIGNAL SQLSTATE 之外,一切都在完美执行。

我一直在搜索,但没有发现任何关于 SIGNAL SQLSTATE 与游标一起使用时不起作用的信息。但是每次我在触发器中声明一个游标(即使我不使用它)它都会忽略我的 SIGNAL SQLSTATE。有没有我遗漏的 sintaxis 东西?

这是我必须为分配做的触发器:

CREATE TRIGGER check_if_unlocked BEFORE INSERT ON mata
FOR EACH ROW
BEGIN
    DECLARE done INT DEFAULT FALSE; 
    DECLARE nDragonesNecesarios INT; #El numero de dragones necesarios a matar para poder matar al siguiente
    DECLARE nombrePersonajeAux VARCHAR(250);
    DECLARE aux INT; #albergará el numero de dragones que ha matado un personaje
    DECLARE curMagos CURSOR FOR 
            SELECT DISTINCT magoCompone.nombreMago
            FROM magoCompone
            WHERE magoCompone.idEscuadron = NEW.idEscuadron;
    DECLARE curGuerreros CURSOR FOR
            SELECT DISTINCT guerreroCompone.nombreGuerrero
            FROM guerreroCompone
            WHERE guerreroCompone.idEscuadron = NEW.idEscuadron;
    DECLARE curTanques CURSOR FOR
            SELECT DISTINCT tanqueCompone.nombreTanque
            FROM tanqueCompone
            WHERE tanqueCompone.idEscuadron = NEW.idEscuadron;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
    SET nDragonesNecesarios = (SELECT COUNT(*)
                                FROM dragon
                                WHERE dragon.vida < (SELECT dragon.vida
                                                    FROM dragon
                                                    WHERE dragon.nombreDragonDesbloqueador = NEW.nombreDragon));
    
    
    #Recorro los magos que pertenezcan al escuadrón
    OPEN curMagos;
    read_loop_mago: LOOP
    FETCH curMagos INTO nombrePersonajeAux;
    IF done THEN
        LEAVE read_loop_mago;
    END IF;
    
    SET aux = (SELECT COUNT(*)
                FROM magoCompone inner join mata on magoCompone.idEscuadron = mata.idEscuadron
                WHERE magoCompone.nombreMago = nombrePersonajeAux);
                
    IF aux < nDragonesNecesarios THEN # Ha matado a menos dragones de los necesarios
        SET done = true;
        SIGNAL SQLSTATE '02000'
        SET MESSAGE_TEXT = 'Error: Algún integrante del escuadrón no tiene desbloqueados los dragones necesarios para matar a este dragón';
    END IF;
    END LOOP;
    CLOSE curMagos;
    
    SET done = FALSE;
    #Recorro los guerreros que pertenezcan al escuadrón    
    OPEN curGuerreros;
    read_loop_guerrero: LOOP
    FETCH curGuerreros INTO nombrePersonajeAux;
    IF done THEN
        LEAVE read_loop_guerrero;
    END IF;
    
    SET aux = (SELECT COUNT(*)
                FROM guerreroCompone inner join mata on guerreroCompone.idEscuadron = mata.idEscuadron
                WHERE guerreroCompone.nombreGuerrero = nombrePersonajeAux);
                
    IF aux < nDragonesNecesarios THEN # Ha matado a menos dragones de los necesarios
        SET done = true;
        SIGNAL SQLSTATE '02000'
        SET MESSAGE_TEXT = 'Error: Algún integrante del escuadrón no tiene desbloqueados los dragones necesarios para matar a este dragón';
    END IF;
    END LOOP;
    CLOSE curGuerreros;
    
    SET done = FALSE;            
    #Recorro los tanques que pertenezcan al escuadrón    
    OPEN curTanques;
    read_loop_tanque: LOOP
    FETCH curTanques INTO nombrePersonajeAux;
    IF done THEN
        LEAVE read_loop_tanque;
    END IF;
    
    SET aux = (SELECT COUNT(*)
                FROM tanqueCompone inner join mata on tanqueCompone.idEscuadron = mata.idEscuadron
                WHERE tanqueCompone.nombreTanque = nombrePersonajeAux);
                
    IF aux < nDragonesNecesarios THEN # Ha matado a menos dragones de los necesarios
        SET done = true;
        SIGNAL SQLSTATE '02000'
        SET MESSAGE_TEXT = 'Error: Algún integrante del escuadrón no tiene desbloqueados los dragones necesarios para matar a este dragón';
    END IF;
    END LOOP;
    CLOSE curTanques;
END$$
DELIMITER ;

感谢您的关注。

【问题讨论】:

【参考方案1】:

您需要在缩短的示例中像这里一样声明一个退出处理程序

  DECLARE EXIT HANDLER FOR SQLSTATE '02000' 
  BEGIN SET @a := 23; 
          SIGNAL SQLSTATE '02000'
         SET MESSAGE_TEXT = 'Error: Algún integrante del escuadrón no tiene desbloqueados los dragones necesarios para matar a este dragón';
 
  END;
CREATE Table A ( A1 int , A2 int);
INSERT INTO A VALUES( 5,2),(7,1);

CREATE Table B ( B1 int, B2 int, B3 int, B4 int, B5 int, B6 int);
INSERT INTO B VALUES(5,4,6,1,2,0)
CREATE TRIGGER abdtrg  Before INSERT ON A
FOr EACH ROW
BEGIN
 DECLARE done INT DEFAULT FALSE;
 DECLARE nombrePersonajeAux INTEGER;
 DECLARE nombrePersonajeAux2 INTEGER;
 DECLARE curMagos CURSOR FOR SELECT A1,A2 FROM A;
 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
 DECLARE EXIT HANDLER FOR SQLSTATE '02000' 
 BEGIN SET @a := 23; 
         SIGNAL SQLSTATE '02000'
        SET MESSAGE_TEXT = 'Error: Algún integrante del escuadrón no tiene desbloqueados los dragones necesarios para matar a este dragón';

 END;
     OPEN curMagos;
    read_loop_mago: LOOP
        FETCH curMagos INTO nombrePersonajeAux,nombrePersonajeAux2;
        SET @a := -1;
    IF done THEN
        LEAVE read_loop_mago;
    END IF;
        IF nombrePersonajeAux  > nombrePersonajeAux2 THEN # Ha matado a menos dragones de los necesarios
        SIGNAL SQLSTATE '02000'
        SET MESSAGE_TEXT = 'Error: Algún integrante del escuadrón no tiene desbloqueados los dragones necesarios para matar a este dragón';
        SET done := true;
        LEAVE read_loop_mago;
    END IF;
    END LOOP read_loop_mago;
    CLOSE curMagos;
  END
INSERT INTO A VALUES(1,1)
错误:Algún integrante del escuadrón no tiene desbloqueados los dragones necesarios para matar a este dragon
SELECT *,@a FROM A
A1 | A2 | @一种 -: | -: | -: 5 | 2 | 23 7 | 1 | 23

db小提琴here

【讨论】:

您好,信号 sqlstate 现在可以工作了,但它现在不允许我在表中插入任何内容,即使条件为 false 也总是弹出错误 你问我怎么做,我告诉过你,你要id调试什么,你必须自己做。如果你想对行为做一个 dbfiddle,我可以看看它。

以上是关于为啥 MySQL WorkBench 在使用游标时忽略了我的 SIGNAL SQLSTATE?的主要内容,如果未能解决你的问题,请参考以下文章

请问为啥MySQL使用游标进行insert操作时,末行会被插入两次?下附代码

mysql workbench在建表以后想把已有的字段设置为AI,但设不了。为啥的

为啥 MySQL Workbench 表数据导入向导会导入 0 条记录?

在mysql workbench中,通过查询语句,为啥无法修改表中的数据?需要改啥设置吗?

MYSQL游标循环,多跑一圈,为啥?

centos下MySQL Workbench连接时崩溃的解决方法