【问题标题】:Error in MySQL when setting default value for DATE or DATETIME为 DATE 或 DATETIME 设置默认值时 MySQL 出错
【发布时间】:2020-10-23 07:53:30
【问题描述】:

我运行的是MySql Server 5.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 docs中提到:

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

即使他们也说:

无效的 DATE、DATETIME 或 TIMESTAMP 值将转换为相应类型的“零”值('0000-00-00' 或 '0000-00-00 00:00:00')。

还考虑到 MySQL 文档的第二个引用,谁能告诉我为什么它会给出这个错误?

【问题讨论】:

  • 你为什么想要一个明显没有意义的默认值?如果日期未知,那么这正是NULL 的用途。
  • 注意:这适用于 SQL Fiddle 的 5.6 版——sqlfiddle.com/#!9/02c98
  • @Karlos 检查更新的答案。
  • @TomH 约会中的零在您看来毫无意义,这已经超出了许多读者的兴趣。显然,NULL 始终存在,因为它是0000-00-00 00:00:00。他们两个,在我看来是非常不同的。回答您的评论,也超出了这篇文章的范围,并确保完整的网站本身。

标签: mysql sql date datetime console


【解决方案1】:

适用于 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 的回归错误。

【讨论】:

  • 这其实是一个非常准确的答案
【解决方案2】:

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

MySQL Documentation 5.7 says:

严格模式影响服务器是否允许 '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 上将 SET sql_mode='' 包含在 my.cnf 中。对于 Windows,这必须在 my.ini 文件中完成。

注意

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

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

更新

关于@Dylan-Su 所说的错误问题:

我不认为这是 MYSQL 随着时间的推移而演变的错误,因为随着产品的进一步改进,一些事情发生了变化。

但是我有另一个关于 NOW() 函数的相关错误报告

Datetime field does not accept default NOW()

另一个有用的说明 [参见Automatic Initialization and Updating for TIMESTAMP and DATETIME]

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

关于 NO_ZERO_DATE 的更新

从 MySQL 5.7.4 开始,此模式已弃用。对于以前的版本,您必须注释掉配置文件中的相应行。参考MySQL 5.7 documentation on NO_ZERO_DATE

【讨论】:

  • UPDATE IGNORE 是我要找的东西??
  • 错了。我的两个 MySQL 实例(本地和服务器)都有 STRICT_TRANS_TABLES。但是,我可以在本地实例中轻松插入 0000-00-00,但不能在我的服务器实例中插入 - 会引发错误。为什么?因为我的服务器 MySQL 配置启用了NO_ZERO_DATE。而我的本地没有。
  • ok @Green 如果适用,我会找出并更新答案
  • 在我的情况下,'SET sql_mode = ""' 不起作用。 'SET GLOBAL sql_mode = "";'为我完成了这项工作。
  • 还应该删除NO_ZERO_DATE
【解决方案3】:

我在 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 中的一个或两个的模式。 documentation 说:

"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 和 NO_ENGINE_SUBSTITUTION。”

【讨论】:

    【解决方案4】:

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

    在首选项面板中将 SQL_MODE 删除为 TRADITIONAL。

    【讨论】:

      【解决方案5】:

      配置语法问题

      在 *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-mode 回顾:

      How to setup permanent Sql Mode flags

      【讨论】:

        【解决方案6】:

        这个答案只适用于 MySQL 5.7:

        最好并没有真正将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,有了这个,before参数会被忽略,所以你也需要删除它。

        最后也是传统的,但是文档谈到了这个参数:“在将不正确的值插入列时给出错误而不是警告”,使用此参数,不会插入零值的日期,但没有插入。

        MySQL 并没有真正使用这些参数和组合进行组织。

        【讨论】:

          【解决方案7】:

          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"
          

          【讨论】:

            【解决方案8】:

            首先选择当前会话sql_mode

            SELECT @@SESSION.sql_mode;
            

            然后你会得到类似default value:

            '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'

            然后设置sql_mode 不带'NO_ZERO_DATE'

            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 = '...';
            

            【讨论】:

              【解决方案9】:

              只需添加一行:sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

              内部文件:/etc/mysql/mysql.conf.d/mysqld.cnf

              然后sudo service mysql restart

              【讨论】:

              • 适用于 5.7.23。
              • 我可能首先建议SELECT @@SESSION.sql_mode;,然后他们从它给你的内容中删除 NO_ZERO_IN_DATE、NO_ZERO_DATE 和 STRICT_TRANS_TABLES。这样您就可以保留您启用的任何其他设置。我为我的 sql 模式设置的不仅仅是这两个项目。不知道他们都做什么,但我不想冒险移除他们。
              【解决方案10】:

              我遇到了一种情况,日期字段的数据在 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 值(无论日期是否正确)都来自此日期之前。

              【讨论】:

              • 完美的快速解决方案。事实上,您也可以使用&lt;'0000-01-01',因为它当然是一个有效日期。
              • 我发现的少数解决方案之一,提示如何修复数据而不是更改模式,这不是我的选择。
              【解决方案11】:
              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';
              

              【讨论】:

                【解决方案12】:

                在目录 xampp/mysql/bin 打开“my.ini”并更改行:sql_mode for ->

                "sql_mode=NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE"
                
                REMOVE "NO_ZERO_IN_DATE"
                

                【讨论】:

                • 欢迎使用stackoverflow,请使用正确的代码格式以提高答案的易读性。
                【解决方案13】:

                我已经测试了如下修复:

                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'");
                

                【讨论】:

                  【解决方案14】:

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

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

                  【讨论】:

                    【解决方案15】:

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

                      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。使用以下命令更改超过 1 列的默认日期 使用单个 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;
                    

                    【讨论】:

                      【解决方案16】:

                      我正在做一个新项目,试图添加一个新列

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

                      得到了这个错误

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

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

                      正如@geeksal 提到的

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

                      我已经尝试了几个小时,以为问题与 PRIVILAGES

                      有关

                      这节省了我的工作时间。

                      SET GLOBAL sql_mode = '';
                      

                      编码愉快!

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2014-10-09
                        • 2023-02-02
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多