在 MySQL 中为 DATE 或 DATETIME 设置默认值时出错

我正在运行 MySqlServer5.7.11,这个句子是:

updated datetime NOT NULL DEFAULT '0000-00-00 00:00:00'

没有正常工作。给出错误:

ERROR 1067 (42000): Invalid default value for 'updated'

但是下面这些:

updated datetime NOT NULL DEFAULT '1000-01-01 00:00:00'

只是工作

DATE 的情况相同。

作为一个 旁注,它在 MySQL 文档中被提到:

DATE 类型用于具有日期部分但没有时间部分的值。MySQL 以“ YYYY-MM-DD”格式检索和显示 DATE 值。支持的范围是“1000-01-01”到“9999-12-31”。

即使他们也会说:

无效的日期、 DATETIME 或 TIMESTAMP 值将转换为适当类型(“0000-00-00”或“0000-00-0000:00:00:00:00”)的“零”值。

考虑到 MySQL 文档的第二个引用,有人能告诉我为什么会出现这个错误吗?

281763 次浏览

它适用于5.7.8:

mysql> create table t1(updated datetime NOT NULL DEFAULT '0000-00-00 00:00:00');
Query OK, 0 rows affected (0.01 sec)


mysql> show create table t1;
+-------+-------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                            |
+-------+-------------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
`updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+-------+-------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)


mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.8-rc  |
+-----------+
1 row in set (0.00 sec)

您可以创建一个 SQLFiddle 来重新创建您的问题。

Http://sqlfiddle.com/

如果它适用于 MySQL 5.6和5.7.8,但在5.7.11上失败。那么它可能是5.7.11的一个回归 bug。

错误是因为 sql 模式,根据最新的 MYSQL 5.7文档,sql 模式可以是严格模式

MySQL 文档5.7说:

严格模式影响服务器是否允许“0000-00-00”作为有效日期: 如果严格模式未启用,则允许“0000-00-00”,插入不会产生警告。 如果严格模式被启用,’0000-00-00’是不允许的并且插入产生一个错误,除非 IGNORE 也被给予。对于 INSERT IGNORE 和 UPDATE IGNORE,允许“0000-00-00”,并且插入将产生警告。

检查 MYSQL 模式

SELECT @@GLOBAL.sql_mode global, @@SESSION.sql_mode session

禁用 STRICT _ TRANS _ TABLES 模式

但是,要允许格式 0000-00-00 00:00:00,您必须在 mysql 配置文件中或通过命令禁用 STRICT _ TRANS _ TABLES 模式

是命令

SET sql_mode = '';

或者

SET GLOBAL sql_mode = '';

使用关键字 GLOBAL需要超级优先权,它会影响所有客户端从那时起连接的操作

如果上面的不起作用,那么转到 /etc/mysql/my.cnf(根据 ubuntu)并注释掉 STRICT_TRANS_TABLES

另外,如果您想在服务器启动时永久设置 sql 模式,那么在 Linux 或 MacOS 上的 my.cnf中包含 SET sql_mode=''。对于窗口,这必须在 my.ini文件中完成。

注意

然而,在 MYSQL 5.6中默认不启用严格模式。因此,它不会按照 MYSQL 6文档的说法产生错误

MySQL 允许您将“0000-00-00”的“零”值存储为“虚拟日期”在某些情况下,这比使用 NULL 值更方便,并且使用更少的数据和索引空间。若要禁用“0000-00-00”,请启用 NO _ ZERO _ DATE SQL 模式。

更新

关于@Dylan-Su 所说的虫子问题:

我不认为这是一个错误,它的方式 MYSQL 是随着时间的推移,由于有些事情是改变了基于进一步改进的产品。

然而,我有另一个相关的故障报告关于 NOW()的功能

日期时间字段不接受默认的 NOW ()

另一个有用的注解 [见 TIMESTAMP 和 DATETIME 的自动初始化和更新]

从 MySQL 5.6.5开始,TIMESTAMP 和 DATETIME 列可以自动初始化并更新为当前日期和时间(即当前时间戳)。在5.6.5之前,这只适用于 TIMESTAMP,而且每个表最多只有一个 TIMESTAMP 列。下面的说明首先描述 MySQL 5.6.5及以上版本的自动初始化和更新,然后描述5.6.5之前版本的差异。

关于 NO _ ZERO _ DATE 的更新

从5.7.4版本的 MySQL 开始,不推荐使用这种模式。对于以前的版本,必须注释掉配置文件中的相应行。请参阅 关于 NO _ ZERO _ DATE 的 MySQL 5.7文档

我在使用 WAMP 3.0.6和 MySql 5.7.14时出现了这个错误。

解决方案 :

修改 c:\wamp\bin\mysql\mysql5.7.14\my.ini文件中的第70行(如果您的 ini 文件未被修改)

sql-mode= "STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE,NO_AUTO_CREATE_USER"

sql-mode="ERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE,NO_AUTO_CREATE_USER"

重启所有服务。

这将禁用严格模式。正如文档中所述,“严格模式”意味着启用了 STRICT_TRANS_TABLESSTRICT_ALL_TABLES之一或同时启用了 STRICT_TRANS_TABLESSTRICT_ALL_TABLES的模式。 文件表示:

”MySQL 5.7中的默认 SQL 模式包括以下模式: ONLY _ FULL _ GROUP _ BY,STRICT _ TRANS _ TABLES,NO _ ZERO _ IN _ DATE, NO _ ZERO _ Date,ERROR _ FOR _ Division _ BY _ ZERO,NO _ AUTO _ CREATE _ USER,and 无引擎替代

要解决 MySQL Workbench 的问题(在服务器端应用解决方案之后) :

在首选项面板中将 SQL _ MODE 移除到 TRADITION。

enter image description here

配置语法问题

在 * nix 系统下的某些版本的 MYSQL (测试5.7. *)中,您应该使用以下语法:

[mysqld]


sql-mode="NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLE,NO_ENGINE_SUBSTITUTION"

这些方法行不通:

破折号,不要引号

sql-mode=NO_ENGINE_SUBSTITUTION

下划线,不要引号

sql_mode=NO_ENGINE_SUBSTITUTION

下划线和引号

sql_mode="NO_ENGINE_SUBSTITUTION"

对配置值和 sql 模式的更全面回顾:

如何设置永久 Sql 模式标志

这个答案只适用于 MySQL 5.7:

Best 实际上并没有在 sql _ mode 空白处设置,而是在 PHP 中使用了一个会话变量:

SET SESSION sql_mode= 'ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

所以至少保留了其他的默认值。

真是疯了,mysql 文档不清楚,您需要在 sql _ mode 中删除这些默认值:

NO _ ZERO _ IN _ DATE,NO _ ZERO _ DATE,我明白,但在未来的版本中,这将被停止。

STRICT _ ALL _ TABLES,使用这个,在参数被忽略之前,所以您也需要删除它。

最后也是 TRADITION,但是文档中提到了这个参数: “在向列中插入不正确的值时,给出一个错误而不是一个警告”,使用这个参数,不会插入值为零的日期,但是不会插入 yes。

MySQL 实际上并没有使用这些参数和组合进行组织。

mysql Ver 14.14 Distrib 5.7.18, for Linux (x86_64)的选项组合。

不扔:

STRICT_TRANS_TABLES + NO_ZERO_DATE

投掷:

STRICT_TRANS_TABLES + NO_ZERO_IN_DATE

我在 Ubuntu 上的 /etc/mysql/my.cnf设置:

[mysqld]
sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

首先选择当前会议 sql_mode:

SELECT @@SESSION.sql_mode;

然后你会得到类似的 默认值:

“ ONLY _ FULL _ GROUP _ BY,STRICT _ TRANS _ TABLE,NO _ ZERO _ IN _ DATE,NO _ ZERO _ DATE,ERROR _ FOR _ DISION _ BY _ ZERO,NO _ AUTO _ CREATE _ USER,NO _ ENGINE _ SUSTION”(仅限 _ FULL _ GROUP _ BY,严格的 TRANS _ TABLE,NO _ ZERO _ IN _ DATE,NO _ ZERO _ DATE,NO _ ZERO _ DATE,误差 _ FOR _ ZERO _ BY _ BY

然后设置不包含 'NO_ZERO_DATE'sql_mode:

SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

如果你有补助金,你也可以为 GLOBAL这样做:

SELECT @@GLOBAL.sql_mode;
SET GLOBAL sql_mode = '...';

只要加上一行: sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

内部档案: /etc/mysql/mysql.conf.d/mysqld.cnf

然后是 sudo service mysql restart

我遇到了这样一种情况: 对于一个日期字段,数据混合在 NULL 和0000-00-00之间。但是我不知道如何将“0000-00-00”更新为 NULL,因为

 update my_table set my_date_field=NULL where my_date_field='0000-00-00'

再也不允许了。 我的解决办法很简单:

update my_table set my_date_field=NULL where my_date_field<'0000-01-01'

因为所有不正确的 my_date_field值(不管日期是否正确)都来自这个日期之前。

set global sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

在目录 xampp/mysql/bin 中 打开“ my.ini”并修改行: sql _ mode for->

"sql_mode=NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE"


REMOVE "NO_ZERO_IN_DATE"

我测试了一个修复程序,如下所示:

1). On the file "system/library/db/mysqli.php" search and comment the line:
"$this->connection->query("SET SESSION sql_mode = 'NO_ZERO_IN_DATE,NO_ZERO_DATE,NO_ENGINE_SUBSTITUTION'");"


2) Add the following line above the one you just commented:
// Correction by Added by A.benkorich
$this->connection->query("SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY'");

选择数据库并运行 SQL 查询:

SELECT @@GLOBAL.sql_mode global, @@SESSION.sql_mode session

1. 使用以下命令将默认日期更改为 current _ time 戳:-

  ALTER TABLE `wp_posts` CHANGE `post_date` `post_date`  DATETIME NOT
NULL DEFAULT CURRENT_TIMESTAMP

2. 使用以下命令将默认日期更改为 NULL:-

 ALTER TABLE `wp_posts` CHANGE `post_date` `post_date`  DATETIME NOT
NULL DEFAULT NULL

3. 使用以下命令更改多列的默认日期 使用单个 SQL 查询:-

ALTER TABLE `wp_posts`  CHANGE `post_date` `post_date` DATETIME NOT NULL
DEFAULT CURRENT_TIMESTAMP, CHANGE `post_date_gmt` `post_date_gmt`
DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, CHANGE `post_modified`
`post_modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, CHANGE
`post_modified_gmt` `post_modified_gmt` DATETIME NOT NULL DEFAULT
CURRENT_TIMESTAMP;

我在做一个新项目,想加一个新栏目

ALTER TABLE prefix_example_table ADD COLUMN stackoverflow decimal(11,3) NOT NULL

然后得到了这个错误

#1292 - Incorrect date value: '0000-00-00'

对于另一个我甚至没有尝试向其添加新数据的列,返回此错误的 Column 具有 日期类型的默认值 “0000-00-00”

就像@geeksal 提到的

严格模式影响服务器是否允许“0000-00-00”作为有效日期: 如果未启用严格模式,则允许“0000-00-00”,插入操作不会产生警告。如果严格模式被启用,’0000-00-00’是不允许的并且插入产生一个错误,除非 IGNORE 也被给予。对于 INSERT IGNORE 和 UPDATE IGNORE,允许“0000-00-00”,并且插入将产生警告。

我已经尝试了几个小时,认为这个问题与 特权有关

这节省了我的工作时间。

SET GLOBAL sql_mode = '';