Помилка в 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 у форматі "РРРР-MM-DD". Підтримується діапазон від "1000-01-01" до "9999-12-31".

навіть якщо вони також кажуть:

Недійсні значення DATE, DATETIME або TIMESTAMP перетворюються на значення "нуль" відповідного типу ("0000-00-00" або "0000-00-00 00:00:00").

Враховуючи також другу цитату з документації на MySQL, чи могла б хто-небудь дозволити мені знати, чому вона дає цю помилку?


11
Чому ви хочете, щоб дефолт, який очевидно безглуздий? Якщо дата невідома, то саме це і NULLє.
Том Н

Як зауваження: Це працює у версії 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.cnfна Linux або MacOS. Для Windows це потрібно зробити у my.iniфайлі.

Примітка

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

MySQL дозволяє зберігати "нульове" значення "0000-00-00" як "фіктивну дату". Це в деяких випадках зручніше, ніж використання значень NULL, і використовується менше даних та простору індексів. Щоб заборонити "0000-00-00", увімкніть режим SQL NO_ZERO_DATE.

ОНОВЛЕННЯ

Щодо питання про помилку, як сказав @ Dylan-Su:

Я не думаю, що це помилка в тому, як MYSQL еволюціонував з часом, завдяки чому деякі речі змінюються на основі подальшого вдосконалення продукту.

Однак у мене є ще один відповідний звіт про помилку щодо 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 цей режим застарілий. Для попередньої версії потрібно прокоментувати відповідний рядок у конфігураційному файлі. Зверніться до документації MySQL 5.7 NO_ZERO_DATE


5
ОНОВЛЕННЯ IGNORE - це те, що я шукав 👍🏻
Куракін

2
Неправильно. У мене є STRICT_TRANS_TABLESобидва MySQL екземпляри, локальні та серверні. Однак я можу легко вставити 0000-00-00у свій локальний екземпляр, але не можу у своєму екземплярі сервера - помилка видається. Чому? Оскільки мій сервер MySQL config NO_ZERO_DATEувімкнено. І мої місцеві цього не мають.
Зелений

гаразд @ Зелений Я розберусь і оновлю відповідь, якщо це застосовно
geeksal

4
У моєму випадку 'SET sql_mode = ""' не працювало. 'SET GLOBAL sql_mode = "";' зробив роботу за мене.
arjen Stens

Також 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,".


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.
користувач2513149

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:

Найкраще насправді не встановлено порожнім 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, перед цим параметри будуть ігноровані, тому вам також потрібно видалити їх.

Нарешті, TRADITIONAL теж, але документація говорить про цей параметр: "подайте помилку замість попередження" при введенні неправильного значення в стовпець ", при цьому параметр дати з нульовими значеннями не вставляються, але без" так ".

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

0

У diretory xamp / mysql / bin Відкрийте "my.ini" та змініть рядок: Sql_node для ->

"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.