我有一个MySQL存储过程来计算员工的工作时间,加班等。在某些特殊情况下,我需要计算两个时间段(员工的工作时间和公司的工作时间)之间的重叠,然后使用GREATEST( )和LEAST()函数用于TIME类型的变量。
存储过程在MySQL 5.5中产生了正确的结果,但是当我升级到MySQL 5.7时改变了行为。实际上,如果我将变量类型更改为VARCHAR(),它就可以在MySQL 5.7中使用,但是它所处理的数据来自TIME类型的表字段。
下面是演示该问题的过程的简化形式。
DROP procedure IF EXISTS `timetest`;
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `timetest`()
BEGIN
DECLARE working_from, working_to, open_from, open_to TIME;
-- This data actually comes from table column of type TIME
SET working_from = '08:00:00';
SET working_to = '16:00:00';
SET open_from = '07:00:00';
SET open_to = '14:00:00';
IF open_from IS NOT NULL AND open_to IS NOT NULL THEN
SET working_from = GREATEST(working_from, open_from);
SET working_to = LEAST(working_to, open_to);
END IF;
SELECT working_from, working_to;
END$$
DELIMITER ;
在MySQL 5.5中:
mysql> call timetest();
+--------------+------------+
| working_from | working_to |
+--------------+------------+
| 08:00:00 | 14:00:00 |
+--------------+------------+
1 row in set (0.00 sec)
在MySQL 5.7中:
mysql> call timetest();
+--------------+------------+
| working_from | working_to |
+--------------+------------+
| 07:00:00 | 14:00:00 |
+--------------+------------+
1 row in set (0,00 sec)
答案 0 :(得分:2)
看起来GREATEST
不会将这些值检测为TIME
值。您可以使用CAST(column_name AS TIME)
解决此问题:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `timetest`()
BEGIN
DECLARE working_from, working_to, open_from, open_to TIME;
-- This data actually comes from table column of type TIME
SET working_from = '08:00:00';
SET working_to = '16:00:00';
SET open_from = '07:00:00';
SET open_to = '14:00:00';
IF open_from IS NOT NULL AND open_to IS NOT NULL THEN
SET working_from = CAST(GREATEST(working_from, open_from) AS TIME);
SET working_to = CAST(LEAST(working_to, open_to) AS TIME);
END IF;
SELECT working_from, working_to;
END$$
DELIMITER ;
这看起来像是MySQL 5.7(see this bug report)上的错误:
CREATE PROCEDURE `test_greatest`()
BEGIN
DECLARE time_1 TIME;
DECLARE time_2 TIME;
DECLARE time_3 TIME;
DECLARE result TIME;
SET time_1 = '08:00:00';
SET time_2 = '07:00:00';
SET time_3 = '06:00:00';
-- always returns the last parameter.
SET result = GREATEST(time_1, time_2, time_3); -- result is 06:00:00
SET result = GREATEST(time_1, time_3, time_2); -- result is 07:00:00
SET result = GREATEST(time_2, time_3, time_1); -- result is 08:00:00
-- using a CAST on first parameter the GREATEST is working.
SET result = GREATEST(CAST(time_1 AS TIME), time_2, time_3); -- result is 08:00:00
SET result = GREATEST(time_1, CAST(time_2 AS TIME), time_3); -- result is 06:00:00
SET result = GREATEST(time_1, time_2, CAST(time_3 AS TIME)); -- result is 06:00:00
-- using CAST on the whole GREATEST is working.
SET result = CAST(GREATEST(time_1, time_2, time_3) AS TIME); -- result is 08:00:00
SELECT result;
END
此示例始终返回time_3
的最后一个参数(GREATEST
)。