GREATEST() 和 LEAST() 函数无法在 MySQL 5.7 的存储过程中使用 TIME 变量
GREATEST() & LEAST() functions not working with TIME variables in stored procedure in MySQL 5.7
我有一个MySQL存储过程来计算员工的工作时间、加班时间等。在某些特殊情况下,我需要计算两个时间段(员工的工作时间和公司的工作时间)之间的重叠,并且我是在 TIME 类型的变量上使用 GREATEST() 和 LEAST() 函数完成的。
存储过程在 MySQL 5.5 中产生了正确的结果,但是当我升级到 MySQL 5.7 时行为发生了变化。实际上,如果我将变量类型更改为 VARCHAR(),它可以在 MySQL 5.7 中工作,但它所处理的数据来自 table 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)
看起来 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
此示例总是 returns GREATEST
的最后一个参数 (time_3
)。
我有一个MySQL存储过程来计算员工的工作时间、加班时间等。在某些特殊情况下,我需要计算两个时间段(员工的工作时间和公司的工作时间)之间的重叠,并且我是在 TIME 类型的变量上使用 GREATEST() 和 LEAST() 函数完成的。
存储过程在 MySQL 5.5 中产生了正确的结果,但是当我升级到 MySQL 5.7 时行为发生了变化。实际上,如果我将变量类型更改为 VARCHAR(),它可以在 MySQL 5.7 中工作,但它所处理的数据来自 table 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)
看起来 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
此示例总是 returns GREATEST
的最后一个参数 (time_3
)。