mysql日期时间设置默认0000-00-00 00:00:00出错

本文深入解析MySQL的严格模式与非严格模式的区别,重点探讨数据类型、长度和格式的处理方式。详细介绍了如何通过配置文件或查询设置开启严格模式,以及解决因严格模式导致的日期‘0000-00-00’无法插入的问题。

在解决问题之前,我们要先了解一下mysql的严格模式和非严格模式,有兴趣可以自己查看一下官方文档

严格模式

顾名思义,就是比非严格模式更为严格,主要就是对数据的要求更为严格,比如数据的类型,长度,格式等。比如一个整型字段我们写入一个字符串类型的数据,在非严格模式下MySQL不会报错,同样如果定义了char或varchar类型的字段,当写入或更新的数据超过了定义的长度也不会报错。还有一些关于null的数据问题,也可能是因为严格模式造成的,不过我没遇到过,就跳过这个问题┓( ´∀` )┏

个人推荐,开启严格模式,毕竟也算是对我们代码的一种测试,严格一点总好过项目完成后出问题再大改好。

首先,通过

SELECT @@GLOBAL.sql_mode;       //查看MySQL的全局模式
SELECT @@SESSION.sql_mode;      //查看MySQL的当前连接的模式,如果当前连接模式与全局模式不一致,关闭连接后再连接就一致了

这两个语句查看你是否处于严格模式,如果查询结果中有

STRICT_TRANS_TABLES

这个类型就代表你开启了严格模式(看了别人的文章貌似还要跟ONLY_FULL_GROUP_BY组合才算?这个不清楚)

如果没有,就可以通过以下两种方式打开严格模式:

1.修改配置文件

找到mysql安装目录下的my.cnf(windows系统则是my.ini)文件
在sql_mode中加入STRICT_TRANS_TABLES则表示开启严格模式,如没有加入则表示非严格模式,修改后重启mysql即可

2.在查询中设置

先查看一下当前你的sql_mode,然后复制查询结果,把STRICT_TRANS_TABLES加到开头就可以了

执行以下两个语句中的一个,根据自身情况修改(推荐了解一下这些变量,都挺容易记的,记住了就可以按需使用了):

SET GLOBAL sql_mode = STRICT_TRANS_TABLES,你的查询结果;
SET SESSION sql_mode = STRICT_TRANS_TABLES,你的查询结果;

 
 
 
 

然后我们就可以进入正题了

执行

SELECT @@SESSION.sql_mode;      //查看MySQL的当前连接的模式,如果当前连接模式与全局模式不一致,关闭连接后再连接就一致了

查询结果中有NO_ZERO_DATE和NO_ZERO_IN_DATE,就是我们日期不能设为0000-00-00的原因了

只要通过修改mysql的模式就可以了,参照上面的设置方法,根据自己情况选择session还是global,把这两个变量去掉就可以了。

还有一个方法,不过无法设置默认值,只能在修改数据时生效,就是将INSERT换成INSERT INGORE,UPDATE换成UPDATE INGORE,不过这样会导致错误的数据也可以进入数据库,不推荐使用

 
 
 

此处贴一下官方的介绍:

  • NO_ZERO_DATE

该NO_ZERO_DATE模式会影响服务器是否允许 '0000-00-00’作为有效日期。它的效果还取决于是否启用了严格的SQL模式。

    • 如果未启用此模式, '0000-00-00’则允许并且插入不会产生警告。
    • 如果启用此模式,‘0000-00-00’ 则允许并且插入产生警告。
    • 如果启用此模式和严格模式, '0000-00-00’则不允许插入产生错误,除非 IGNORE同时给出。对于 INSERT IGNORE和UPDATE IGNORE,'0000-00-00’允许和插入产生警告。

NO_ZERO_DATE已弃用。NO_ZERO_DATE 不是严格模式的一部分,但应与严格模式一起使用,默认情况下启用。如果NO_ZERO_DATE启用但未启用严格模式,则会发出警告, 反之亦然。

因为NO_ZERO_DATE已弃用,它将在未来的MySQL版本中作为单独的模式名称删除,其效果包含在严格SQL模式的效果中。

  • NO_ZERO_IN_DATE

该NO_ZERO_IN_DATE模式会影响服务器是否允许年份部分为非零但月份或日期部分为0的日期。(此模式会影响日期,例如’2010-00-01’或 ‘2010-01-00’,但不会 ‘0000-00-00’。要控制服务器是否允许’0000-00-00’,请使用 NO_ZERO_DATE模式。)效果的NO_ZERO_IN_DATE 还取决于是否启用严格的SQL模式。

    • 如果未启用此模式,则允许零件的日期,并且插入不会产生警告。
    • 如果启用此模式,则插入零件的日期’0000-00-00’并生成警告。
    • 如果启用此模式和严格模式,则不允许零件的日期,并且插入会产生错误,除非IGNORE同时给出。对于INSERT IGNORE和 UPDATE IGNORE,插入零件的日期’0000-00-00’并生成警告。

NO_ZERO_IN_DATE已弃用。 NO_ZERO_IN_DATE不是严格模式的一部分,但应与严格模式一起使用,默认情况下启用。如果NO_ZERO_IN_DATE启用但未启用严格模式,则会发出警告, 反之亦然。

因为NO_ZERO_IN_DATE已弃用,它将在未来的MySQL版本中作为单独的模式名称删除,其效果包含在严格SQL模式的效果中。
 
 
 

机翻见谅,不过大概是能看懂的,最后的意思大概是,这两个属性将会被删除,以后将直接包含在严格模式中了,也就是说以后的mysql开启了严格模式就没办法设置0000-00-00 00:00:00了

<think>好的,我现在需要解决用户在NestJS中连接MySQL时接口返回时间偏差8小时的问题。用户提到时区偏移8小时,这通常是因为服务器、数据库和应用程序的时区设置不一致导致的。我需要参考用户提供的引用内容,看看有没有相关的解决方案。 首先,引用[1]提到MySQL的时区表没有正确设置可能导致时间转换问题,用户遇到的CONVERT_TZ函数返回NULL可能就是时区表未配置。这可能意味着需要检查MySQL的时区设置是否正确安装。 引用[2]和[3]讨论了PHP中时区、位置设置的重要性,指出必须确保时区、经纬度设置一致,否则时间相关函数会出错。虽然用户使用的是NestJS(基于Node.js),但同样的原理适用:应用层、数据库和系统时区需要一致。 引用[4]提到了Java中的日期时间类,强调区分本地时间和UTC时间。这可能提示在NestJS中处理日期时,要明确时区,避免隐式转换。 接下来,我需要考虑NestJS连接MySQL时的配置。通常,在TypeORM配置中,可以设置时区选项。例如,在TypeORM的配置文件中,设置timezone参数为'+08:00'(假设用户所在时区是UTC+8)。同时,确保MySQL服务器的时区也设置为同样的值,可以通过SQL命令查看和修改MySQL的时区设置。 另外,应用服务器本身的时区也需要检查,比如Node.js进程的时区环境变量TZ是否设置为Asia/Shanghai(对应UTC+8)。这会影响Date对象的行为,进而影响从数据库读取的时间值。 还需要确认数据库中的时间字段类型是否正确,比如使用TIMESTAMP或DATETIME。TIMESTAMP会转换为UTC存储,而DATETIME则按输入值存储。如果应用和数据库时区不一致,TIMESTAMP可能导致偏差。 可能的解决方案步骤包括: 1. 配置MySQL时区为UTC+8。 2. 在NestJS的TypeORM连接配置中指定时区。 3. 确保服务器和Node.js进程的时区设置正确。 4. 检查时间字段类型,必要时进行调整。 同时,用户可能需要验证数据库中的时间值是否正确存储,以及应用在读取时是否进行了正确的时区转换。例如,查询数据库时使用CONVERT_TZ函数转换时区,或者在实体类中使用转换装饰器处理日期字段。 还需要考虑ORM框架是否自动转换时区,例如TypeORM在处理日期时是否会根据配置的时区进行调整。如果数据库存储的是UTC时间,而应用配置为UTC+8,TypeORM可能自动进行转换,导致前端显示正确的时间。 最后,可能需要测试不同的配置组合,例如数据库时区设为UTC,应用配置时区为UTC+8,查看是否能够正确显示时间。或者确保所有环节都使用同一时区,避免转换带来的问题。</think>### NestJS连接MySQL时间偏差8小时的解决方案 #### 问题原因分析 时间偏差通常由三个层面的时区不匹配导致: 1. **MySQL服务时区**:默认可能使用系统时区或UTC 2. **数据库连接时区**:TypeORM连接配置未指定时区 3. **应用服务器时区**:Node.js进程时区与环境变量$TZ不一致 4. **时间字段类型差异**:TIMESTAMP与DATETIME的存储机制不同[^4] #### 分步解决方案 1. **检查MySQL服务时区** ```sql -- 查看当前时区设置 SELECT @@global.time_zone, @@session.time_zone; ``` 若结果为SYSTEM,需确认系统时区: ```bash # 在MySQL服务器执行 date +"%Z %z" ``` 建议修改MySQL配置文件(my.cnf): ```ini [mysqld] default-time-zone = '+08:00' ``` *重启MySQL生效* 2. **配置TypeORM连接时区** 在NestJS的TypeORM配置模块中增加时区参数: ```typescript TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', // ... timezone: '+08:00', // 关键配置项 extra: { connectTimeout: 60000 } }) ``` 3. **统一应用层时区** 在Dockerfile或启动脚本中设置环境变量: ```dockerfile ENV TZ=Asia/Shanghai ``` 或在package.json的启动命令中: ```json { "scripts": { "start": "TZ=Asia/Shanghai nest start" } } ``` 4. **处理时间字段类型差异** - **TIMESTAMP**:存储为UTC时间,检索时转换 - **DATETIME**:按字面值存储,无时区转换 建议在实体类中明确处理: ```typescript @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP', transformer: { from: (value: Date) => value, to: (value: Date) => value } }) createdAt: Date; ``` #### 验证方案 1. 直接查询数据库: ```sql SELECT NOW(), UNIX_TIMESTAMP(); ``` 2. 通过API接口返回时间: ```typescript @Get('timecheck') getTimeCheck() { return { dbTime: this.repository.query('SELECT NOW()'), serverTime: new Date() }; } ``` 正常应返回相同时间值(误差在1秒内) #### 高级配置建议 对于云数据库场景,建议: 1. 保持数据库时区为UTC 2. 应用层配置时区为本地时区 3. 在前端显示时进行时区转换 ```typescript // 前端返回ISO格式时间 @Column({ type: 'timestamp' }) get createdAt() { return this.createdAt.toISOString(); } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值