MySQL 5.7 datetime和timestamp设置default 0报错

本文解析了MySQL5.7及更高版本中,由于NO_ZERO_IN_DATE和NO_ZERO_DATE模式导致的DateTime字段默认值为0或'0000-00-00 00:00:00'时出现的错误,并提供了通过修改sql_mode来解决问题的详细步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mysql5.7之后版本 datetime/timestamp 默认值0或0000-00-00 00:00:00出错
出现异常:Invalid default value for ‘create_time’
原因:
mysql5.7之后版本的sql_mode默认使用:

mysql> select @@sql_mode;
ONLY_FULL_GROUP_BY,
STRICT_TRANS_TABLES, 
NO_ZERO_IN_DATE, 
NO_ZERO_DATE, 
ERROR_FOR_DIVISION_BY_ZERO, 
NO_AUTO_CREATE_USER, 
NO_ENGINE_SUBSTITUTION 

其中NO_ZERO_IN_DATE, NO_ZERO_DATE两个选项禁止了0000这样的日期和时间。因此在mysql的配置文件中,重新设置sql_mode,去掉这两项就可以了。
解决办法:

# 临时修改
mysql> set global sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' ;
mysql> set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' ;
# 永久修改
# 修改my.cnf文件,在[mysqld]中添加
sql-mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

作者:iscona
链接:https://www.jianshu.com/p/f701ceffc7e1
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

<think>好的,用户想了解MySQL 5.7timestamp的用法。我需要先回忆一下timestamp类型的特点,尤其是5.7版本中的变化注意事项。 首先,timestampMySQL中用于存储日期时间,范围是从1970-01-01 00:00:01到2038-01-19 03:14:07,这是因为它占用4字节,datetime不同。用户可能需要知道这个范围限制,特别是2038年的问题,这在5.7版本依然存在。 接下来,timestamp的时区处理。MySQL会将其转换为UTC存储,并在检索时转换回当前时区。这点需要强调,特别是当系统跨时区使用时,可能会出现时间显示不一致的问题。而datetime不会自动转换时区,这也是两者的区别之一。 然后,默认值自动更新的特性。用户可能关心如何设置默认值为当前时间,或者在更新时自动更新时间戳。比如,在创建表时,可以指定默认值CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP。需要注意的是,在5.7版本中,每个表只能有一个timestamp列使用这两个属性,但如果有多个timestamp列,可以分别设置默认值或更新时的行为吗?可能需要确认,比如一个列设置DEFAULT CURRENT_TIMESTAMP,另一个设置ON UPDATE,但根据文档,可能仍然有限制。 还要提到,在MySQL 5.6.5之后,允许datetime也使用自动初始化,但用户问的是5.7,所以这个特性是支持的,不过问题集中在timestamp上,是否需要对比datetime?可能用户需要明确两者的区别,所以应该简单提一下。 此外,需要注意timestamp列是否允许NULL。默认情况下,timestamp列是NOT NULL的,如果没有显式声明,并且没有默认值的话,可能会有默认值的问题。例如,如果插入一行时不指定timestamp列的值,第一个timestamp列会被设置为当前时间,后续的则设置为'0000-00-00 00:00:00',但在严格模式下会报错。不过这可能随着版本不同而变化,需要确认5.7的默认行为。 还有,显式设置NULL的情况。如果列允许NULL,且没有默认值,那么插入时可以设为NULL,否则会报错。但默认情况下timestamp列是否允许NULL?根据文档,如果使用explicit_defaults_for_timestamp参数,可能会影响这个行为。在5.7中,默认这个参数是OFF,所以第一个timestamp列如果没有指定NULL属性,会自动设置为NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,而后续的timestamp列会被视为NOT NULL DEFAULT '0000-00-00 00:00:00',但这样的默认值在严格模式下可能不允许。 因此,在严格模式下,可能需要显式地为timestamp设置默认值或者允许NULL,否则插入时可能出现错误。需要提醒用户注意这一点。 另外,举例说明如何创建表,包含timestamp列,并展示自动初始化更新的语法。比如: CREATE TABLE example ( id INT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); 这里要注意,在5.7中,如果两个列都使用DEFAULTON UPDATE可能会有问题,因为旧版本只允许一个列这样设置。但可能从某个版本开始允许了,需要确认。比如在5.6.5之后,这个限制可能被取消,允许每个表有多个timestamp列使用DEFAULT或ON UPDATE,但需要验证。如果用户使用的是5.7,应该没问题,但需要指出可能需要注意的版本差异。 最后,使用时区转换的例子,比如SET time_zone = '+00:00'; 来查看不同时区下的时间显示差异,说明timestamp的时区敏感性。 可能还需要提醒用户2038年的限制,以及如果超出范围会发生什么,比如存储失败或者值被截断。 总结要涵盖的内容点:定义与范围、时区处理、默认值与自动更新、NULL处理、示例注意事项。确保信息准确,特别是针对5.7版本的特定行为。</think>MySQL 5.7 中的 `TIMESTAMP` 类型用于存储日期时间,具有一些独特的特性注意事项。以下是其主要用法细节: --- ### 1. **定义与范围** - **存储格式**:`TIMESTAMP` 存储为 **UTC 时间**,占用 **4 字节**。 - **时间范围**:`1970-01-01 00:00:01` UTC 至 `2038-01-19 03:14:07` UTC(受 4 字节限制,称为“2038 年问题”)。 - **显示依赖时区**:检索时会根据当前会话的时区设置(通过 `time_zone` 变量)自动转换时间。 --- ### 2. **时区处理** - **存储时自动转 UTC**:插入或更新时间时,MySQL 会将其从当前会话时区转换为 UTC 存储。 - **检索时转回本地时区**:查询时再将 UTC 时间转换回当前会话时区。 示例: ```sql -- 设置会话时区为 UTC+8(东八区) SET time_zone = '+08:00'; INSERT INTO table (ts_column) VALUES ('2023-10-01 12:00:00'); -- 若切换时区为 UTC SET time_zone = '+00:00'; SELECT ts_column FROM table; -- 显示为 '2023-10-01 04:00:00' ``` --- ### 3. **默认值与自动更新** - **默认值**: - 若未显式指定默认值,第一个 `TIMESTAMP` 列默认 `DEFAULT CURRENT_TIMESTAMP`。 - 其他 `TIMESTAMP` 列默认 `DEFAULT '0000-00-00 00:00:00'`(严格模式下可能报错)。 - **自动更新**: - 可通过 `ON UPDATE CURRENT_TIMESTAMP` 在行更新时自动更新时间。 - **MySQL 5.6.5+** 允许同一表多个列使用 `CURRENT_TIMESTAMP`(需显式定义)。 **示例表定义**: ```sql CREATE TABLE example ( id INT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); ``` - `created_at` 在插入时自动填充当前时间。 - `updated_at` 在插入或更新时自动更新为当前时间。 --- ### 4. **NULL 值处理** - 默认 `TIMESTAMP` 列为 `NOT NULL`。若未显式赋值且无默认值,会尝试用 `'0000-00-00 00:00:00'` 填充(严格模式下可能报错)。 - 允许 `NULL` 需显式声明: ```sql CREATE TABLE demo ( ts_nullable TIMESTAMP NULL -- 允许插入 NULL ); ``` --- ### 5. **与 `DATETIME` 的区别** | 特性 | TIMESTAMP | DATETIME | |--------------------|-------------------------------|-----------------------| | **存储范围** | 1970-01-01 ~ 2038-01-19 | 1000-01-01 ~ 9999年 | | **时区敏感** | 自动转换 | 按字面值存储 | | **存储空间** | 4 字节 | 8 字节 | | **自动初始化/更新**| 支持(需显式定义) | MySQL 5.6.5+ 支持 | --- ### 6. **注意事项** 1. **2038 年限制**:超出 `2038-01-19 03:14:07` 的时间会溢出,建议未来使用 `DATETIME`。 2. **严格模式**:若启用 SQL 严格模式 (`STRICT_ALL_TABLES`),无效日期或隐式默认值可能导致错误。 3. **时区一致**:跨时区应用需确保会话时区设置正确,避免时间显示混乱。 4. **参数影响**:通过 `explicit_defaults_for_timestamp` 可禁用默认自动初始化行为(需谨慎修改)。 --- ### 7. **操作示例** ```sql -- 插入当前时间 INSERT INTO example (id) VALUES (1); -- created_at updated_at 均为当前时间 -- 更新时自动修改 updated_at UPDATE example SET id = 2 WHERE id = 1; -- updated_at 变为当前时间 -- 显式插入时间 INSERT INTO example (created_at, updated_at) VALUES ('2023-10-01 08:00:00', '2023-10-01 08:00:00'); ``` --- 通过合理利用 `TIMESTAMP` 的时区转换自动更新特性,可以高效管理记录的创建修改时间。但在涉及大范围时间或长期系统时,需谨慎评估是否选用 `DATETIME`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值