我在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 ;
答案 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 |