MySQL SYSDATE函数

简介:在本教程中,您将了解MySQL SYSDATE()函数及其警告。

MySQL SYSDATE函数简介

下面说明了SYSDATE()函数的语法:

SYSDATE(fsp);

如果该函数用于字符串上下文或YYYYMMDDHHMMSS格式,则SYSDATE()函数以'YYYY-MM-DD HH:MM:SS'格式返回当前日期和时间作为值,如果该函数用于数字上下文。

SYSDATE()函数接受一个可选参数fsp,该参数确定结果是否应包括从0到6的小数秒精度。

请参见以下示例。

mysql> SELECT SYSDATE();
+---------------------+
| SYSDATE()           |
+---------------------+
| 2017-07-13 17:42:37 |
+---------------------+
1 row in set (0.00 sec)

如果传递fsp参数,结果将包括小数秒精度,如以下示例所示:

mysql> SELECT SYSDATE(3);
+-------------------------+
| SYSDATE(3)              |
+-------------------------+
| 2017-07-13 17:42:55.875 |
+-------------------------+
1 row in set (0.00 sec)

SYSDATE与现在

考虑以下示例。

mysql>  SELECT SYSDATE(), 
               NOW();
+---------------------+---------------------+
| SYSDATE()           | NOW()               |
+---------------------+---------------------+
| 2017-07-13 17:46:30 | 2017-07-13 17:46:30 |
+---------------------+---------------------+
1 row in set (0.00 sec)

似乎SYSDATE()和NOW()函数都返回相同的值,该值是执行它的当前日期和时间。

但是,SYSDATE()函数实际上返回执行时间,而NOW()函数返回恒定时间开始执行语句。

请参阅以下查询:

mysql> SELECT NOW(), 
              SLEEP(5), 
              NOW();
+---------------------+----------+---------------------+
| NOW()               | SLEEP(5) | NOW()               |
+---------------------+----------+---------------------+
| 2017-07-13 17:49:18 |        0 | 2017-07-13 17:49:18 |
+---------------------+----------+---------------------+
1 row in set (5.00 sec)

在此示例中,我们使用SLEEP()函数将查询暂停了5秒钟。
在同一条语句中,NOW()函数始终返回一个常量,该常量是该语句开始的时间。

让我们将NOW()函数更改为SYSDATE()函数:

mysql> SELECT SYSDATE(), SLEEP(5), SYSDATE();
+---------------------+----------+---------------------+
| SYSDATE()           | SLEEP(5) | SYSDATE()           |
+---------------------+----------+---------------------+
| 2017-07-13 17:50:57 |        0 | 2017-07-13 17:51:02 |
+---------------------+----------+---------------------+
1 row in set (5.00 sec)

在同一条语句中,SYSDATE()函数返回不同的时间值,这些时间值反映了SYSDATE()函数的执行时间。

因为SYSDATE()函数是不确定的,所以不能使用索引来评估引用该函数的表达式。

为了说明这一点,我们将创建一个名为tests的表,并将一些数据插入该表中。

CREATE TABLE tests (
    id INT AUTO_INCREMENT PRIMARY KEY,
    t DATETIME UNIQUE
);

INSERT INTO tests(t) 
WITH RECURSIVE times(t) AS
( 
    SELECT now() - interval 1 YEAR t
        UNION ALL 
    SELECT t + interval 1 hour
    FROM times
    WHERE t < now() 
)
SELECT t
FROM times;

请注意,我们使用了递归CTE来生成时间序列。
自MySQL 8.0以来,CTE已可用

由于t列具有唯一索引,因此以下查询应快速执行:

SELECT 
    id, 
    t
FROM
    tests
WHERE
    t >= SYSDATE() - INTERVAL 1 DAY;

但是,它需要15毫秒才能完成。
让我们使用EXPLAIN语句查看详细信息。

EXPLAIN SELECT 
    id, t
FROM
    tests
WHERE
    t >= SYSDATE() - INTERVAL 1 DAY;

事实证明,MySQL必须扫描表中的所有行以获取数据。
该索引无法使用。

如果在查询中将SYSDATE()更改为NOW()函数:

SELECT 
    id, 
    t
FROM
    tests
WHERE
    t >= NOW() - INTERVAL 1 DAY;

借助NOW()函数,索引已用于查询数据,如下面的EXPLAIN结果所示:

EXPLAIN SELECT 
    id, 
    t
FROM
    tests
WHERE
    t >= NOW() - INTERVAL 1 DAY;

请注意,MySQL为您提供了--sysdate-is-now选项,可以使SYSDATE()函数的行为与NOW()函数相同。

在本教程中,您了解了MySQL SYSDATE()函数以及为什么在使用它之前应该三思而后行的原因。

日期:2019-11-20 08:52:23 来源:oir作者:oir