Ошибка в MySQL при установке значения по умолчанию для DATE или DATETIME


124

Я запускаю 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 :

Тип DATE используется для значений с частью даты, но без части времени. MySQL извлекает и отображает значения DATE в формате «ГГГГ-ММ-ДД». Поддерживаемый диапазон: от «1000-01-01» до «9999-12-31».

даже если они также говорят:

Недопустимые значения DATE, DATETIME или TIMESTAMP преобразуются в «нулевое» значение соответствующего типа ('0000-00-00' или '0000-00-00 00:00:00').

Принимая во внимание вторую цитату из документации MySQL, может ли кто-нибудь сообщить мне, почему он дает эту ошибку?


11
Зачем вам явно бессмысленное значение по умолчанию? Если дата неизвестна, то это именно то, что NULLнужно.
Tom H

В качестве примечания: это работает в версии 5.6 на SQL Fiddle - sqlfiddle.com/#!9/02c98 .
Гордон Линофф

@Karlos проверьте обновленный ответ.
geeksal

Ответы:


209

Ошибка связана с режимом sql, который может быть строгим режимом в соответствии с последней документацией MYSQL 5.7.

В документации 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вы должны отключить режим STRICT_TRANS_TABLES в файле конфигурации mysql или с помощью команды

По команде

SET sql_mode = '';

или

SET GLOBAL sql_mode = '';

Использование ключевого слова GLOBALтребует суперпредложений и влияет на операции, которые с этого момента подключаются все клиенты.

если указанное выше не работает, перейдите к /etc/mysql/my.cnf(согласно ubuntu) и закомментируйтеSTRICT_TRANS_TABLES

Кроме того, если вы хотите постоянно устанавливать режим sql при запуске сервера, включите его SET sql_mode=''в my.cnfLinux или MacOS. Для окон это должно быть сделано в my.iniфайле.

Заметка

Однако строгий режим не включен по умолчанию в MYSQL 5.6. Следовательно, он не вызывает ошибку согласно документации MYSQL 6, в которой говорится

MySQL позволяет вам сохранять «нулевое» значение «0000-00-00» в качестве «фиктивной даты». В некоторых случаях это более удобно, чем использование значений NULL, и требует меньше данных и места для индекса. Чтобы запретить «0000-00-00», включите режим SQL NO_ZERO_DATE.

ОБНОВИТЬ

Что касается ошибки, как сказал @ 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

Начиная с MySQL 5.7.4 этот режим устарел. Для предыдущей версии вы должны закомментировать соответствующую строку в файле конфигурации. Обратитесь к документации MySQL 5.7 на NO_ZERO_DATE


5
UPDATE IGNORE - это то, что я искал 👍🏻
Афанасий Куракин

2
Неправильно. У меня есть STRICT_TRANS_TABLESоба экземпляра MySQL, локальный и серверный. Однако я могу легко вставить 0000-00-00в свой локальный экземпляр, но не могу в свой экземпляр сервера - возникает ошибка. Зачем? Поскольку моя конфигурация MySQL сервера NO_ZERO_DATEвключена. А у моего местного нет.
Green

хорошо @Green, я выясню и обновлю ответ, если применимо,
geeksal

4
В моем случае "SET sql_mode =" "" не сработал. 'УСТАНОВИТЬ ГЛОБАЛЬНЫЙ sql_mode = "";' сделал всю работу за меня.
Арьен Стенс

Также NO_ZERO_DATEследует удалить
Прешан Прадипа

18

У меня была эта ошибка с WAMP 3.0.6 с MySql 5.7.14.

Решение :

измените строку 70 (если ваш ini-файл не затронут) в c:\wamp\bin\mysql\mysql5.7.14\my.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_TABLESили STRICT_ALL_TABLESвключен. В документации говорится:

«Режим SQL по умолчанию в MySQL 5.7 включает следующие режимы: 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_USER».


14

Я попал в ситуацию, когда данные были смешаны между 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<'1000-01-01'

потому что все неверные my_date_fieldзначения (правильные или неправильные даты) были до этой даты.


2
Идеальное быстрое решение. Фактически, вы также можете использовать, <'0000-01-01'поскольку это, конечно, действительная дата.
Рики Макмастер

5

Проблема с синтаксисом конфигурации

В некоторых версиях MYSQL (проверенных 5.7. *) В системах * nix вы должны использовать этот синтаксис:

[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


5

Сначала выберите текущий сеанс sql_mode:

SELECT @@SESSION.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'

а затем установить 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 = '...';

4

Просто добавьте строку: sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

внутри файла: /etc/mysql/mysql.conf.d/mysqld.cnf

затем sudo service mysql restart


1
Работает на 5.7.23.
user2513149

1
Я бы, вероятно, предложил SELECT @@SESSION.sql_mode;сначала удалить NO_ZERO_IN_DATE, NO_ZERO_DATE и STRICT_TRANS_TABLES из того, что он вам дает. Таким образом вы сохраните все остальные настройки, которые вы включили. У меня было гораздо больше, чем просто эти два элемента, установленные для моего режима sql. Не знаю, что они все делают, но я не хочу рисковать удалением их сейчас.
Radley Sustaire

2

Работает на 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.


1

Чтобы решить проблему с MySQL Workbench (после применения решения на стороне сервера):

Удалите SQL_MODE на TRADITIONAL на панели настроек.

введите описание изображения здесь


1

Этот ответ предназначен только для 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, с этим, прежде чем параметры будут проигнорированы, поэтому вам также необходимо удалить его.

Наконец, тоже ТРАДИЦИОННЫЙ, но в документации говорится об этом параметре: «выдавать ошибку вместо предупреждения» при вставке неверного значения в столбец », с этим параметром даты с нулевыми значениями не вставляются, а без да.

MySQL на самом деле не организован с этими параметрами и комбинациями.


0

Комбинации вариантов для 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

Мои настройки в /etc/mysql/my.cnfUbuntu:

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


0

В директории xamp / mysql / bin Откройте "my.ini" и измените строку: Sql_node for ->

"Sql_mode = NO_ENGINE_SUBSTITUTION, NO_ZERO_DATE"

УДАЛИТЬ "NO_ZERO_IN_DATE"


Добро пожаловать в stackoverflow! Используйте правильное форматирование кода, чтобы сделать ответ более разборчивым.
vlizana
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.