我正在编写一个程序,该程序获取一个数据表以映射一个字段并在另一个表中插入/更新。
我的问题是,如果映射函数找不到任何匹配项,则光标将在第一次迭代后停止,而不会引发任何错误。
这是我的功能:
BEGIN
DECLARE mapped_name VARCHAR(255);
SELECT mapped_field INTO mapped_name
FROM mapping_civility
WHERE original_field = nameVar
LIMIT 1;
IF mapped_name IS NULL THEN
RETURN 'INDEFINI';
ELSE
RETURN mapped_name;
END IF;
END
通过测试,我发现如果我的映射表中有一个对应的字段,它可以工作,但是如果SELECT由于找不到映射的字段而返回NULL值,它将在第一次迭代时停止游标。
然后,我在另一个数据库,另一个服务器上进行了尝试,一切正常,所以可能是配置问题?两者都有字符集“LATIN1 - CP1252西欧”归类“latin1_swedish_ci”。
这是我的过程代码:
BLOCK1: BEGIN
DECLARE no_more_rows1 INT;
DECLARE my_name VARCHAR(255);
DECLARE civility VARCHAR(255);
DECLARE curseur1 CURSOR FOR
SELECT `name`
FROM source;
DECLARE CONTINUE handler FOR NOT FOUND SET no_more_rows1 = TRUE;
OPEN curseur1;
LOOP1: LOOP
FETCH curseur1 INTO my_name;
IF no_more_rows1 THEN
CLOSE curseur1;
LEAVE LOOP1;
END IF;
SET civility = get_civility(my_name);
INSERT INTO log (id, message, date) VALUES (NULL, CONCAT(my_name, ' : ', civility), NOW());
END LOOP LOOP1;
END BLOCK1;
如果名称映射正确,此过程将正确插入,但如果名称未映射,它将在第一行之后停止。
您可以使用下表进行测试
-- ----------------------------
-- Table structure for `source`
-- ----------------------------
DROP TABLE IF EXISTS `source`;
CREATE TABLE `source` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of source
-- ----------------------------
INSERT INTO `source` VALUES ('1', 'Pierre');
INSERT INTO `source` VALUES ('2', 'David');
INSERT INTO `source` VALUES ('3', 'Kevin');
INSERT INTO `source` VALUES ('4', 'Pierre');
INSERT INTO `source` VALUES ('5', 'Donald Pierre');
-- ----------------------------
-- Table structure for `log`
-- ----------------------------
DROP TABLE IF EXISTS `log`;
CREATE TABLE `log` (
`id` int(5) NOT NULL AUTO_INCREMENT COMMENT 'id',
`message` text COMMENT 'message',
`date` varchar(64) DEFAULT NULL COMMENT 'date',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for `mapping_civility`
-- ----------------------------
DROP TABLE IF EXISTS `mapping_civility`;
CREATE TABLE `mapping_civility` (
`id` int(5) NOT NULL AUTO_INCREMENT COMMENT 'id',
`original_field` varchar(255) DEFAULT NULL COMMENT 'original_field',
`mapped_field` varchar(255) DEFAULT NULL COMMENT 'mapped_field',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of mapping_civility
-- ----------------------------
INSERT INTO `mapping_civility` VALUES ('1', 'kevin', 'H');
INSERT INTO `mapping_civility` VALUES ('2', 'pierre', 'H');
INSERT INTO `mapping_civility` VALUES ('3', 'isabelle', 'F');
在MySQL 5.6之前,存储过程只有一个处理程序,请参见5.6的更改日志:
此外,条件处理程序处理规则中的一些缺陷已得到纠正,因此MySQL行为更像标准SQL:
- 块作用域用于确定选择哪个处理程序。以前,存储程序被视为具有单个范围的处理程序选择。
因此NOT FOUND
不幸的是mapping_civility
,由于在函数中找不到行,因此会触发您的继续处理程序into
。
您可以在获取新行之前直接重新初始化变量,以重置之前发生的所有事情:
...
LOOP1: LOOP
set no_more_rows1 = false; -- add this
FETCH curseur1 INTO my_name;
IF no_more_rows1 THEN
...
如果您像原始问题中那样有嵌套循环,请注意它仍将只是一个(活动的)处理程序,因此请对两个循环使用相同的变量,并在每个循环之前将其重置fetch
。
对于MySQL 5.6及更高版本,您当前的代码将按预期工作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句