mysql 5.6 中 explicit_defaults_for_timestamp参数

本文详细解析MySQL中TIMESTAMP数据类型的非标准行为及其在不同配置下的表现,重点介绍explicit_defaults_for_timestamp参数的作用与用法,帮助开发者正确使用TIMESTAMP列并避免常见陷阱。

一:

官方文档中关于explicit_defaults_for_timestamp参数说明如下:

 

 

  •  explicit_defaults_for_timestamp

    Introduced5.6.6
    Deprecated5.6.6
    Command-Line Format--explicit_defaults_for_timestamp=#
    System VariableNameexplicit_defaults_for_timestamp
    Variable ScopeGlobal, Session
    Dynamic VariableNo
    Permitted ValuesTypeboolean
    DefaultFALSE

    In MySQL, the TIMESTAMP data type differs in nonstandard ways from other data types: mysql中TIMESTAMP类型和其他的类型有点不一样(在没有设置explicit_defaults_for_timestamp=1的情况下)

    • TIMESTAMP columns not explicitly declared with the NULL attribute are assigned the NOT NULL attribute. (Columns of other data types, if not explicitly declared as NOT NULL, permit NULL values.) Setting such a column to NULL sets it to the current timestamp.在默认情况下,如果TIMESTAMP列没有显式的指明null属性,那么该列会被自动加上not null属性(而其他类型的列如果没有被显式的指定not null,那么是允许null值的),如果往这个列中插入null值,会自动的设置该列的值为current timestamp值

    • The first TIMESTAMP column in a table, if not declared with the NULL attribute or an explicit DEFAULT or ON UPDATE clause, is automatically assigned the DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP attributes.表中的第一个TIMESTAMP列,如果没有指定null属性或者没有指定默认值,也没有指定ON UPDATE语句。那么该列会自动被加上DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP属性。

    • TIMESTAMP columns following the first one, if not declared with the NULL attribute or an explicit DEFAULT clause, are automatically assigned DEFAULT '0000-00-00 00:00:00' (the “zero” timestamp). For inserted rows that specify no explicit value for such a column, the column is assigned '0000-00-00 00:00:00' and no warning occurs.第一个TIMESTAMP列之后的其他的TIMESTAMP类型的列,如果没有指定null属性,也没有指定默认值,那么该列会被自动加上DEFAULT '0000-00-00 00:00:00'属性。如果insert语句中没有为该列指定值,那么该列中插入'0000-00-00 00:00:00',并且没有warning

    Those nonstandard behaviors remain the default for TIMESTAMP but as of MySQL 5.6.6 are deprecated and this warning appears at startup:在5.6.6及以后的版本中,如果在配置文件中没有指定explicit_defaults_for_timestamp参数,启动时error日志中会报如下错误

    [Warning] TIMESTAMP with implicit DEFAULT value is deprecated.
    Please use --explicit_defaults_for_timestamp server option (see
    documentation for more details).
    

    As indicated by the warning, to turn off the nonstandard behaviors, enable the explicit_defaults_for_timestamp system variable at server startup. With this variable enabled, the server handles TIMESTAMP as follows instead:如果我们在启动的时候在配置文件中指定了explicit_defaults_for_timestamp=1,mysql会按照如下的方式处理TIMESTAMP 列

    • TIMESTAMP columns not explicitly declared as NOT NULL permit NULL values. Setting such a column to NULL sets it to NULL, not the current timestamp. 此时如果TIMESTAMP列没有显式的指定not null属性,那么默认的该列可以为null,此时向该列中插入null值时,会直接记录null,而不是current timestamp。

    • No TIMESTAMP column is assigned the DEFAULT CURRENT_TIMESTAMP or ON UPDATE CURRENT_TIMESTAMP attributes automatically. Those attributes must be explicitly specified. 不会自动的为表中的第一个TIMESTAMP列加上DEFAULT CURRENT_TIMESTAMP 和ON UPDATE CURRENT_TIMESTAMP属性,除非你在建表的时候显式的指明

    • TIMESTAMP columns declared as NOT NULL and without an explicit DEFAULT clause are treated as having no default value. For inserted rows that specify no explicit value for such a column, the result depends on the SQL mode. If strict SQL mode is enabled, an error occurs. If strict SQL mode is not enabled, the column is assigned the implicit default of '0000-00-00 00:00:00' and a warning occurs. This is similar to how MySQL treats other temporal types such as DATETIME.如果TIMESTAMP列被加上了not null属性,并且没有指定默认值。这时如果向表中插入记录,但是没有给该TIMESTAMP列指定值的时候,如果strict sql_mode被指定了,那么会直接报错。如果strict sql_mode没有被指定,那么会向该列中插入'0000-00-00 00:00:00'并且产生一个warning

    Note

    explicit_defaults_for_timestamp is itself deprecated because its only purpose is to permit control over now-deprecated TIMESTAMP behaviors that will be removed in a future MySQL release. When that removal occurs,explicit_defaults_for_timestamp will have no purpose and will be removed as well.  >>explicit_defaults_for_timestamp参数主要用来控制TIMESTAMP数据类型跟其他数据类型不一致的特性,但是TIMESTAMP的这个特性在将来会被废弃,所以explicit_defaults_for_timestamp参数也会在将来被废弃

    This variable was added in MySQL 5.6.6

二:测试
1.explicit_defaults_for_timestamp=0
1)查看errorlog
[Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2)创建测试表test_time
create table test_time(
time1 timestamp,
time2 timestamp,
time3 timestamp,
id int
);
##创建表的时候,没有显示的指定三个timestamp列的not null属性,也没有为三个列指定默认值
3)查看表结构
 show create table test_time;
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table     | Create Table                                                                                                                                                                                                                                                                                               |
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test_time | CREATE TABLE `test_time` (
  `time1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `time2` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `time3` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |

##从表结构中可以看到 表中三个timestamp列都被自动设置为not null,并且表中第一个timestamp列被设置了DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP默认值,其他的timestamp列被加上了DEFAULT '0000-00-00 00:00:00'默认值
3.插入测试
insert into test_time select null,'',null,1;
mysql> insert into test_time select null,'',null,1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 1
##需要去掉 sql_mode 中的 STRICT_TRANS_TABLES 限制,否则上面的语句会报如下错误
ERROR 1292 (22007): Incorrect datetime value: '' for column 'time2' at row 1


mysql> select * from test_time;
+---------------------+---------------------+---------------------+------+
| time1               | time2               | time3               | id   |
+---------------------+---------------------+---------------------+------+
| 2019-12-23 17:33:33 | 0000-00-00 00:00:00 | 2019-12-23 17:33:33 |    1 |
+---------------------+---------------------+---------------------+------+
##往timestamp列插入null值时,会自动为该列设置为current time,往timestamp列插入空值,会设置为该列默认值


mysql> insert into test_time(time1,id) select null,2;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from test_time;
+---------------------+---------------------+---------------------+------+
| time1               | time2               | time3               | id   |
+---------------------+---------------------+---------------------+------+
| 2019-12-23 17:33:33 | 0000-00-00 00:00:00 | 2019-12-23 17:33:33 |    1 |
| 2019-12-23 17:37:46 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |    2 |
+---------------------+---------------------+---------------------+------+
##插入时未指定值的timestamp列中被插入了0000-00-00 00:00:00(非表中第一个timestamp列)


mysql> insert into test_time(id) select 3;
Query OK, 1 row affected (0.03 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from test_time;
+---------------------+---------------------+---------------------+------+
| time1               | time2               | time3               | id   |
+---------------------+---------------------+---------------------+------+
| 2019-12-23 17:33:33 | 0000-00-00 00:00:00 | 2019-12-23 17:33:33 |    1 |
| 2019-12-23 17:37:46 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |    2 |
| 2019-12-23 17:39:01 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |    3 |
+---------------------+---------------------+---------------------+------+
##插入时未指定值的第一个timestamp列中被插入了current time值

2. explicit_defaults_for_timestamp=1
1)建表
create table test_time1(
time1 timestamp,
time2 timestamp,
time3 timestamp,
id int
);
##建表时没有为timestamp列指定null属性,也没有为其指定默认值
2) 查看表结构
show create table test_time1;
+------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                                                                                                                         |
+------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test_time1 | CREATE TABLE `test_time1` (
  `time1` timestamp NULL DEFAULT NULL,
  `time2` timestamp NULL DEFAULT NULL,
  `time3` timestamp NULL DEFAULT NULL,
  `id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 

 

##通过表结构我们看到,三个timestamp列都被设置为null,并且设置了默认值为null
3)插入测试
mysql> insert into test_time1 select null,'',null,1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 1

mysql> select * from test_time1;
+-------+---------------------+-------+------+
| time1 | time2               | time3 | id   |
+-------+---------------------+-------+------+
| NULL  | 0000-00-00 00:00:00 | NULL  |    1 |
+-------+---------------------+-------+------+
##未显示指定timestamp列为not null时,能够向timestamp列中插入null值
1 row in set (0.00 sec)

mysql> insert into test_time1(time1,id) select null,2;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test_time1;
+-------+---------------------+-------+------+
| time1 | time2               | time3 | id   |
+-------+---------------------+-------+------+
| NULL  | 0000-00-00 00:00:00 | NULL  |    1 |
| NULL  | NULL                | NULL  |    2 |
+-------+---------------------+-------+------+
##插入时没有为timestamp列指定值时,自动插入null值
2 rows in set (0.00 sec)

mysql> insert into test_time1(id) select 3;
Query OK, 1 row affected (0.02 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from test_time1;
+-------+---------------------+-------+------+
| time1 | time2               | time3 | id   |
+-------+---------------------+-------+------+
| NULL  | 0000-00-00 00:00:00 | NULL  |    1 |
| NULL  | NULL                | NULL  |    2 |
| NULL  | NULL                | NULL  |    3 |
+-------+---------------------+-------+------+
##插入时没有为timestamp指定值时,自动插入null值(表中第一个timestamp列也是插入null值)
3 rows in set (0.00 sec)

4)指定了not null属性的timestamp列插入测试
create table test_time2(
    -> time1 timestamp,
    -> time2 timestamp not null,
    -> time3 timestamp,
    -> id int
    -> );
Query OK, 0 rows affected (0.10 sec)

mysql> insert into test_time2(time1,id) select null,1;
ERROR 1364 (HY000): Field 'time2' doesn't have a default value ##为timestamp列指定了not null属性,在stric sql_mode时,如果插入时该列没有指定值,会直接报错
mysql> show variables like 'sql_mode';
+---------------+--------------------------------------------------------------------------------------+
| Variable_name | Value                                                                                |
+---------------+--------------------------------------------------------------------------------------+
| sql_mode      | NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+--------------------------------------------------------------------------------------+
1 row in set (0.01 sec)


mysql> set session sql_mode='';
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'sql_mode';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_mode      |       |
+---------------+-------+
1 row in set (0.00 sec)

mysql> insert into test_time2(time1,id) select null,1;
Query OK, 1 row affected, 1 warning (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 1 ##如果为timestamp列指定not null属性,在非stric sql_mode模式下,如果插入的时候该列没有指定值,那么会向该列中插入0000-00-00 00:00:00,并且产生告警

mysql> show warnings;
+---------+------+--------------------------------------------+
| Level   | Code | Message                                    |
+---------+------+--------------------------------------------+
| Warning | 1364 | Field 'time2' doesn't have a default value |
+---------+------+--------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from test_time2;
+-------+---------------------+-------+------+
| time1 | time2               | time3 | id   |
+-------+---------------------+-------+------+
| NULL  | 0000-00-00 00:00:00 | NULL  |    1 |
+-------+---------------------+-------+------+
1 row in set (0.00 sec)

 



 
 

 

 

 

<think>好的,用户遇到了关于MySQLTIMESTAMP隐式默认值被弃用的问题,想要通过使用--explicit_defaults_for_timestamp选项来解决。我需要先理解这个警告出现的原因以及该选项的作用。 首先,MySQL从某个版本开始,默认的TIMESTAMP处理方式可能会有变化,导致旧有的隐式默认值行为被弃用。用户可能是在升级MySQL后遇到了相关警告。查阅文档发现,当explicit_defaults_for_timestamp被禁用时,TIMESTAMP列会有隐式的默认值,而启用该选项后,这些隐式行为会被改变,必须显式指定默认值或允许NULL。 接下来,用户需要知道如何启用这个选项。可能的途径包括在配置文件中设置,或者启动时通过命令行参数。需要注意的是,不同MySQL版本可能有差异,比如在5.65.7中的默认值不同,需要确认用户的具体版本。 然后,具体的步骤应该包括修改配置文件(如my.cnf或my.ini),在[mysqld]部分添加explicit_defaults_for_timestamp=1,并重启服务。或者通过命令行启动时加上--explicit_defaults_for_timestamp=1。但要注意,动态设置可能需要不同的方法,可能需要重启才能生效。 另外,用户可能需要调整现有的表结构,将TIMESTAMP列的默认值显式声明,以避免表结构错误。例如,修改列的定义,明确设置DEFAULT CURRENT_TIMESTAMP或者允许NULL。这部分需要提供示例的SQL语句,帮助用户进行修改。 还需要考虑权限问题,用户是否有权限修改配置或表结构。此外,提醒用户备份数据,避免操作失误导致数据丢失。同时,可能存在的兼容性问题,比如旧应用是否依赖于隐式默认值,需要测试应用是否正常工作。 最后,生成相关问题应该围绕该选项的其他配置、不同版本的影响、修改后的验证方法以及替代解决方案等,帮助用户全面理解和解决问题。</think>### 解决MySQL TIMESTAMP隐式默认值警告的方法 在MySQL中,`TIMESTAMP`列隐式默认值的弃用警告与`explicit_defaults_for_timestamp`系统变量相关。以下是具体操作步骤: 1. **启用选项** 修改MySQL配置文件(`my.cnf`或`my.ini`),在`[mysqld]`部分添加: ```ini explicit_defaults_for_timestamp=1 ``` 重启MySQL服务使配置生效[^1]。 2. **验证配置** 登录MySQL后执行: ```sql SHOW VARIABLES LIKE 'explicit_defaults_for_timestamp'; ``` 若返回值为`ON`或`1`,则表示已启用。 3. **调整表结构** 启用后需显式定义`TIMESTAMP`列的默认值,例如: ```sql ALTER TABLE your_table MODIFY COLUMN ts_column TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; ``` --- ### 关键行为变化对比 | 行为描述 | `explicit_defaults_for_timestamp=0` | `explicit_defaults_for_timestamp=1` | |------------------------------|--------------------------------------|--------------------------------------| | 是否允许`NULL` | 自动转换为`NOT NULL` | 需显式定义`NULL`或`NOT NULL` | | 默认值 | 隐式设置`DEFAULT CURRENT_TIMESTAMP` | 需显式定义 | | 时区处理 | 使用系统时区 | 依赖会话时区设置 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

渔夫数据库笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值