作者:俊达
NO_ZERO_DATE 和 NO_ZERO_IN_DATE这两个SQL MODE,主要用于确保日期字段不包含非法的零值,以提高数据的完整性和准确性。
1、**NO_ZERO_DATE 模式:**日期中不允许使用 ‘0000-00-00’ 这样的零值。如果启用了该模式,MySQL将拒绝插入或更新包含这种零值的日期数据。
2、**NO_ZERO_IN_DATE 模式:**日期中年、月或日不允许为0,如不允许’2021-00-01’, ‘2021-01-00’,启用此模式后,MySQL会阻止插入或更新包含这种零值的日期数据。
date, datetime, timestamp都会受这两个SQL MODE的影响,而且它们需要跟 STRICT MODE 一起使用。启用 STRICT MODE 将在遇到数据不符合规范的情况下引发错误,防止非法数据被写入数据库。如果不开启 STRICT MODE,MySQL 在遇到异常数据时可能会尝试进行隐式转换或使用默认值,从而允许非法数据进入数据库。
只设置NO_ZERO_DATE, 异常数据会产生Warning,但是数据能写入
mysql> create table t_date( a date);
Query OK, 0 rows affected (0.01 sec)
-- 只设置NO_ZERO_DATE, 异常数据会产生Warning,但是数据能写入
mysql> set sql_mode='NO_ZERO_DATE';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> insert into t_date values(0);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+--------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------+
| Warning | 1264 | Out of range value for column 'a' at row 1 |
+---------+------+--------------------------------------------+
1 row in set (0.01 sec)
mysql> select * from t_date;
+------------+
| a |
+------------+
| 0000-00-00 |
+------------+
1 row in set (0.00 sec)
mysql> insert into t_date values('2021-00-00');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t_date;
+------------+
| a |
+------------+
| 0000-00-00 |
| 2021-00-00 |
+------------+
2 rows in set (0.00 sec)
只设置NO_ZERO_IN_DATE, 异常数据会产生Warning,但是数据能写入
-- 设置NO_ZERO_IN_DATE, 日期、月份为0的数据会触发warning
mysql> set sql_mode='NO_ZERO_IN_DATE';
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> insert into t_date values('2022-01-00');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+--------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------+
| Warning | 1264 | Out of range value for column 'a' at row 1 |
+---------+------+--------------------------------------------+
1 row in set (0.00 sec)
mysql> select * from t_date;
+------------+
| a |
+------------+
| 0000-00-00 |
| 2021-00-00 |
| 0000-00-00 |
+------------+
3 rows in set (0.00 sec)
同时设置STRICT和NO_ZERO_DATE,NO_ZERO_IN_DATE,才能避免写入异常日期数据:
-- 增加STRICT模式,异常数据无法写入
mysql> set sql_mode='NO_ZERO_IN_DATE,NO_ZERO_DATE,STRICT_ALL_TABLES';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> insert into t_date values(0);
ERROR 1292 (22007): Incorrect date value: '0' for column 'a' at row 1
mysql> insert into t_date values('2023-00-00');
ERROR 1292 (22007): Incorrect date value: '2023-00-00' for column 'a' at row 1
mysql> insert into t_date values('2023-01-02');
Query OK, 1 row affected (0.00 sec)
如果只设置STRICT模式,不设置NO_ZERO_IN_DATE,NO_ZERO_DATE,还是能写入为0的日期:
mysql> set sql_mode='STRICT_ALL_TABLES';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> insert into t_date values('');
ERROR 1292 (22007): Incorrect date value: '' for column 'a' at row 1
mysql> select * from t_date;
Empty set (0.00 sec)
mysql> insert into t_date values(0);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t_date;
+------------+
| a |
+------------+
| 0000-00-00 |
+------------+
1 row in set (0.00 sec)
建议同时设置NO_ZERO_IN_DATE,NO_ZERO_DATE和STRICT_TRANS_TABLES,可以确保更加严格的日期数据规范,防止不合法或者异常的日期数据写入数据库,这对于确保数据库中数据的一致性和准确性非常重要。
更多技术信息请查看云掣官网https://yunche.pro/?t=yrgw