在MySQL 5.7的存储过程中,GREATEST()和LEAST()函数无法与TIME变量一起使用

时间:2019-05-07 06:53:53

标签: mysql mysql-5.7

我有一个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)

1 个答案:

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

demo on dbfiddle.uk


这看起来像是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)。