最近碰到一个需求,需要根据将一张表的某个字段将这条记录分解成多条,并插入到另外一张表,逻辑简单,使用存储过程和游标搞定。
但是在开发过程中发现了一个问题。使用FETCH INTO取出来的某些字段为NULL,分析了良久,发现,为NULL的字段都是以单个单词命名的,例子如下。
DROP TABLE IF EXISTS `tbl_job`;
CREATE TABLE `tbl_job` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`JOB_NAME` varchar(32) NOT NULL COMMENT '职位名称',
`OCCUPANT_ID` int(11) NOT NULL COMMENT '任职者',
`AGE` int(11) NOT NULL COMMENT '年龄',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tbl_job
-- ----------------------------
INSERT INTO `tbl_job` VALUES ('1', '经理', '1', '21'),
('2', '董事长', '2', '21'),
('3', '项目组长', '3', '22'),
('4', 'SE', '4', '24'),
('5', 'MDE', '5', '24');
DROP PROCEDURE IF EXISTS proc_tbl_job;
delimiter $$
CREATE PROCEDURE proc_tbl_job(IN inId INT)
BEGIN
DECLARE id INT;
DECLARE jobName VARCHAR(32);
DECLARE occupantId INT;
DECLARE age INT;
DECLARE done INT DEFAULT FALSE;
DECLARE curJob CURSOR FOR ( -- 定义
SELECT ID,JOB_NAME,OCCUPANT_ID,AGE FROM tbl_job -- WHERE ID = inId
);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- 监听器
OPEN curJob; -- 打开游标
label:LOOP
FETCH curJob INTO id,jobName,occupantId,age;
IF done THEN LEAVE label;END IF;
SELECT id,jobName,occupantId,age;
END LOOP label;
CLOSE curJob; -- 关闭游标
END $$
delimiter;
CALL proc_tbl_job(2);
得到的结果为:
ID对应id,JOB_NAME 对应jobName,带下划线的字段可以正常读取,单个单词的字段读出来是NULL,将变量id改成eId,age改成eage,就可以正常读取了。
这可能是Mysql的一个BUG,在游标范围内字段名称应该不能和变量名称重复,而Mysql是不区分大小写的,所以即使字段名称是大写,变量名称是小写,也会被认为是同一个字符串。