为什么游标返回null INTO变量但查询返回行?

时间:2018-06-17 09:15:38

标签: mysql stored-procedures mysql-error-1064 isnull stored-functions

我在MySQL中有这个存储过程,它应该有用,但它没有。我放了一个名为logs的表来记录值,看看那里发生了什么:

DELETE FROM LOGS;
CALL fixRegistrationsGroups;
SELECT * FROM LOGS;

这将在日志表中返回:

BEFORE LOOP registrationsIds NULL
registrationsIds NULL
nextRegistrationId NULL

正如我在这个问题的标题中所说,游标registrationsWithSameGroupId中的查询返回行,但是当我从游标中获取时,这不是它返回的行的示例:

countRepeated   registrationsIds    groupId
2               11,1017             6
4               33,35,3463,4363     7
2               32,54               10
7               10,39,40,41,47,48,  51  

存储过程(出了什么问题?):

DELIMITER $$

USE `database-name`$$

DROP PROCEDURE IF EXISTS `fixRegistrationsGroups`$$

CREATE DEFINER=`root`@`%` PROCEDURE `fixRegistrationsGroups`()
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE participantRegistration INT(11);
    DECLARE newAgreementSignatureId INT(11);
    DECLARE countRepeated INT;
    DECLARE registrationsIds VARCHAR(255);
    DECLARE currentGroupId INT;
    DECLARE nextRegistrationId INT(11);
    DECLARE strLen    INT DEFAULT 0;
    DECLARE SubStrLen INT DEFAULT 0;


    DECLARE registrationsWithSameGroupId CURSOR FOR 
        SELECT COUNT(groupId) AS countRepeated, 
                GROUP_CONCAT( registrations.id )  AS registrationsIds, 
                groupId 
            FROM registrations 
            GROUP BY groupId 
            HAVING countRepeated > 1;

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    OPEN registrationsWithSameGroupId;
    READ_LOOP: LOOP
        FETCH NEXT FROM registrationsWithSameGroupId INTO countRepeated, registrationsIds, currentGroupId;      
        INSERT INTO LOGS(line) VALUES (CONCAT('BEFORE LOOP registrationsIds ',IF (registrationsIds IS NULL,'NULL',registrationsIds)) );
        createAndAssignGroups: LOOP             
            SET strLen = LENGTH(registrationsIds);      
            INSERT INTO LOGS(line) VALUES (CONCAT('registrationsIds ',IF (registrationsIds IS NULL,'NULL',registrationsIds)) );
            SET nextRegistrationId = SUBSTRING_INDEX(registrationsIds, ',', 1);
            INSERT INTO LOGS(line) VALUES (CONCAT('nextRegistrationId ',IF (nextRegistrationId IS NULL,'NULL',nextRegistrationId)) );

            INSERT INTO groups (NAME, administratorIdentificationNumber, numberOfParticipants, lastRegistrationDate, lastEventName, eventId)
             SELECT 
                groups.name, 
                administratorIdentificationNumber, 
                numberOfParticipants, 
                lastRegistrationDate, 
                (SELECT eventName FROM registrations WHERE id = nextRegistrationId) AS  lastEventName, 
                eventId 
                FROM groups WHERE id = currentGroupId;

            UPDATE registrations SET groupId = (SELECT MAX(id) FROM groups) WHERE id = nextRegistrationId;

            SET SubStrLen = LENGTH(SUBSTRING_INDEX(registrationsIds, ',', 1));
            SET registrationsIds = MID(registrationsIds, SubStrLen, strLen);            

            IF registrationsIds IS NULL THEN
                LEAVE createAndAssignGroups;
            END IF;         
        END LOOP;

        IF done THEN
            LEAVE READ_LOOP;
        END IF;
    END LOOP;

    CLOSE registrationsWithSameGroupId;

END$$

DELIMITER ;

2 个答案:

答案 0 :(得分:0)

您需要检查您的继续处理程序是否在FETCH之后立即触发

FETCH NEXT FROM registrationsWithSameGroupId INTO countRepeated, registrationsIds, currentGroupId;       
IF done THEN
    LEAVE READ_LOOP;
END IF;
INSERT INTO LOGS(line) VALUES ...

答案 1 :(得分:0)

我不认为你要退出createAndAssignGroups:LOOP。假设你的选择光标工作,我已经从你的结果集

创建了一个表
MariaDB [sandbox]> SELECT * FROM T;
+---------------+-------------------+---------+
| countRepeated | registrationsIds  | groupId |
+---------------+-------------------+---------+
|             2 | 11,1017           |       6 |
|             4 | 33,35,3463,4363   |       7 |
|             2 | 32,54             |      10 |
|             7 | 10,39,40,41,47,48 |      51 |
+---------------+-------------------+---------+
4 rows in set (0.00 sec)

我已修改你的程序,将调试信息写入debug_table,注释掉INSERT INTO组并更新registartions代码,添加一些代码来运行你的代码或我的,移动光标退出测试,这是在错误的地方,&# 39; 固定' SET registrationsIds代码部分和mycode中已经测试了一个空字符串而不是null。 所以这是修改后的程序。

DROP PROCEDURE IF EXISTS P;
DELIMITER $$
CREATE PROCEDURE `p`(INCODE VARCHAR(8))
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE participantRegistration INT(11);
    DECLARE newAgreementSignatureId INT(11);
    DECLARE countRepeated INT;
    DECLARE registrationsIds VARCHAR(255);
    DECLARE currentGroupId INT;
    DECLARE nextRegistrationId INT(11);
    DECLARE strLen    INT DEFAULT 0;
    DECLARE SubStrLen INT DEFAULT 0;
     declare i int default 0;

    DECLARE registrationsWithSameGroupId CURSOR FOR 
        SELECT * from t;

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    OPEN registrationsWithSameGroupId;
    READ_LOOP: LOOP
        FETCH NEXT FROM registrationsWithSameGroupId INTO countRepeated, registrationsIds, currentGroupId;      
      IF done THEN
            LEAVE READ_LOOP;
        END IF;


        INSERT INTO debug_table(msg) VALUES (CONCAT('BEFORE LOOP registrationsIds ',IF (registrationsIds IS NULL,'NULL',registrationsIds)) );
        set I = 0;
          createAndAssignGroups: LOOP             
            SET strLen = LENGTH(registrationsIds);      
            INSERT INTO debug_table(msg) VALUES (CONCAT('registrationsIds ',IF (registrationsIds IS NULL,'NULL',registrationsIds)) );
            SET nextRegistrationId = SUBSTRING_INDEX(registrationsIds, ',', 1);
            INSERT INTO debug_table(msg) VALUES (CONCAT('nextRegistrationId ',IF (nextRegistrationId IS NULL,'NULL',nextRegistrationId)) );
/*
            INSERT INTO groups (NAME, administratorIdentificationNumber, numberOfParticipants, lastRegistrationDate, lastEventName, eventId)
             SELECT 
                groups.name, 
                administratorIdentificationNumber, 
                numberOfParticipants, 
                lastRegistrationDate, 
                (SELECT eventName FROM registrations WHERE id = nextRegistrationId) AS  lastEventName, 
                eventId 
                FROM groups WHERE id = currentGroupId;

            UPDATE registrations SET groupId = (SELECT MAX(id) FROM groups) WHERE id = nextRegistrationId;
*/
            IF INCODE = 'YOURCODE' THEN
            SET SubStrLen = LENGTH(SUBSTRING_INDEX(registrationsIds, ',', 1));
            SET registrationsIds = MID(registrationsIds, SubStrLen, strLen);            

            IF registrationsIds IS NULL THEN
                LEAVE createAndAssignGroups;
            END IF;   
            ELSE 
            SET SubStrLen = LENGTH(SUBSTRING_INDEX(registrationsIds, ',', 1)) + 1;
            #insert into debug_table(msg) values (concat('substrlen:',substrlen,' strlen:', strlen)); 
            SET registrationsIds = MID(registrationsIds, SubStrLen + 1, strLen - substrlen + 1);  

                set i = i + 1;
            IF # > 6 or 
                    length(registrationsIds) = 0 THEN
                LEAVE createAndAssignGroups;
            END IF; 

            END IF;        
        END LOOP;


        #IF done THEN
        #    LEAVE READ_LOOP;
        #END IF;
    END LOOP;

    CLOSE registrationsWithSameGroupId;

END $$

DELIMITER ;

当我运行它时,mycode表现得像预期的那样,你的进入无限循环

TRUNCATE TABLE DEBUG_TABLE;

insert into debug_table(msg) values ('***mycode start***');
call p('mycode');
insert into debug_table(msg) values ('***yourcode start***');
CALL P('YOURCODE');
SELECT * FROM DEBUG_TABLE;

MariaDB [sandbox]> select * from debug_table limit 100;
+-----+------------------------------------------------+------+
| id  | msg                                            | MSG2 |
+-----+------------------------------------------------+------+
|   1 | ***mycode start***                             | NULL |
|   2 | BEFORE LOOP registrationsIds 11,1017           | NULL |
|   3 | registrationsIds 11,1017                       | NULL |
|   4 | nextRegistrationId 11                          | NULL |
|   5 | registrationsIds 1017                          | NULL |
|   6 | nextRegistrationId 1017                        | NULL |
|   7 | BEFORE LOOP registrationsIds 33,35,3463,4363   | NULL |
|   8 | registrationsIds 33,35,3463,4363               | NULL |
|   9 | nextRegistrationId 33                          | NULL |
|  10 | registrationsIds 35,3463,4363                  | NULL |
|  11 | nextRegistrationId 35                          | NULL |
|  12 | registrationsIds 3463,4363                     | NULL |
|  13 | nextRegistrationId 3463                        | NULL |
|  14 | registrationsIds 4363                          | NULL |
|  15 | nextRegistrationId 4363                        | NULL |
|  16 | BEFORE LOOP registrationsIds 32,54             | NULL |
|  17 | registrationsIds 32,54                         | NULL |
|  18 | nextRegistrationId 32                          | NULL |
|  19 | registrationsIds 54                            | NULL |
|  20 | nextRegistrationId 54                          | NULL |
|  21 | BEFORE LOOP registrationsIds 10,39,40,41,47,48 | NULL |
|  22 | registrationsIds 10,39,40,41,47,48             | NULL |
|  23 | nextRegistrationId 10                          | NULL |
|  24 | registrationsIds 39,40,41,47,48                | NULL |
|  25 | nextRegistrationId 39                          | NULL |
|  26 | registrationsIds 40,41,47,48                   | NULL |
|  27 | nextRegistrationId 40                          | NULL |
|  28 | registrationsIds 41,47,48                      | NULL |
|  29 | nextRegistrationId 41                          | NULL |
|  30 | registrationsIds 47,48                         | NULL |
|  31 | nextRegistrationId 47                          | NULL |
|  32 | registrationsIds 48                            | NULL |
|  33 | nextRegistrationId 48                          | NULL |
|  34 | ***yourcode start***                           | NULL |
|  35 | BEFORE LOOP registrationsIds 11,1017           | NULL |
|  36 | registrationsIds 11,1017                       | NULL |
|  37 | nextRegistrationId 11                          | NULL |
|  38 | registrationsIds 1,1017                        | NULL |
|  39 | nextRegistrationId 1                           | NULL |
|  40 | registrationsIds 1,1017                        | NULL |
|  41 | nextRegistrationId 1                           | NULL |
|  42 | registrationsIds 1,1017                        | NULL |
|  43 | nextRegistrationId 1                           | NULL |