为什么游标在变量中返回null,而查询返回行?

qzlgjiam  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(465)

我在mysql中有一个存储过程,它的suposed应该可以工作,但是它不能。我放了一个名为logs的表来记录这些值,看看那里发生了什么:

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

这将在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 ;
q3aa0525

q3aa05251#

您需要检查continue处理程序是否在 FETCH .

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

ep6jt1vc2#

我不认为您正在退出createandassigngroups:loop。假设您的select into游标起作用,我已经从您的结果集中创建了一个表

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\表,注解掉了insert into groups和update REGISTRIONS代码,添加了一些代码来运行你的或我的代码,移动了错误位置的游标退出测试,'fixed'set registrationsids代码段和mycode中测试了空字符串而不是空字符串。所以这是修改后的程序。

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 |

相关问题