Fehler in MySQL beim Festlegen des Standardwerts für DATE oder DATETIME


123

Ich verwende MySql Server 5.7.11 und diesen Satz:

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

wird nicht funktionieren. Den Fehler geben:

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

Aber folgendes:

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

funktioniert einfach .

Der gleiche Fall für DATE.

Als Nebenbemerkung wird es in den MySQL-Dokumenten erwähnt :

Der Typ DATE wird für Werte mit einem Datumsteil, aber keinem Zeitteil verwendet. MySQL ruft DATE-Werte im Format 'JJJJ-MM-TT' ab und zeigt sie an. Der unterstützte Bereich ist '1000-01-01' bis '9999-12-31'.

auch wenn sie auch sagen:

Ungültige DATE-, DATETIME- oder TIMESTAMP-Werte werden in den Wert „Null“ des entsprechenden Typs ('0000-00-00' oder '0000-00-00 00:00:00') konvertiert.

Kann mich jemand unter Berücksichtigung des zweiten Zitats aus der MySQL-Dokumentation wissen lassen, warum dieser Fehler auftritt?


11
Warum sollten Sie eine Standardeinstellung wünschen, die offensichtlich bedeutungslos ist? Wenn das Datum unbekannt ist, ist genau das der Zweck NULL.
Tom H

Hinweis: Dies funktioniert in Version 5.6 unter SQL Fiddle - sqlfiddle.com/#!9/02c98 .
Gordon Linoff

@Karlos überprüfen Sie die aktualisierte Antwort.
Geeksal

Antworten:


208

Der Fehler ist auf den SQL-Modus zurückzuführen, der gemäß der neuesten MYSQL 5.7-Dokumentation ein strikter Modus sein kann

In der MySQL-Dokumentation 5.7 heißt es :

Der strikte Modus beeinflusst, ob der Server '0000-00-00' als gültiges Datum zulässt: Wenn der strikte Modus nicht aktiviert ist, ist '0000-00-00' zulässig und Einfügungen geben keine Warnung aus. Wenn der strikte Modus aktiviert ist, ist '0000-00-00' nicht zulässig und Einfügungen erzeugen einen Fehler, es sei denn, IGNORE ist ebenfalls angegeben. Für INSERT IGNORE und UPDATE IGNORE ist '0000-00-00' zulässig und Einfügungen erzeugen eine Warnung.

So überprüfen Sie den MYSQL-Modus

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

Deaktivieren des STRICT_TRANS_TABLES-Modus

Um das Format zuzulassen, müssen 0000-00-00 00:00:00Sie jedoch den STRICT_TRANS_TABLES-Modus in der MySQL-Konfigurationsdatei oder per Befehl deaktivieren

Auf Befehl

SET sql_mode = '';

oder

SET GLOBAL sql_mode = '';

Die Verwendung des Schlüsselworts GLOBALerfordert hervorragende Vorkenntnisse und wirkt sich auf die Vorgänge aus, die alle Clients ab diesem Zeitpunkt verbinden

Wenn oben nicht funktioniert, gehen Sie zu /etc/mysql/my.cnf(gemäß Ubuntu) und kommentieren Sie ausSTRICT_TRANS_TABLES

Auch, wenn Sie wollen , um den SQL - Modus beim Start des Servers fest eingestellt ist dann SET sql_mode=''in my.cnfunter Linux oder MacOS. Für Windows muss dies in einer my.iniDatei erfolgen.

Hinweis

Der strikte Modus ist in MYSQL 5.6 jedoch standardmäßig nicht aktiviert. Daher produziert sie nicht den Fehler pro Dokumentation MYSQL 6 , die besagt ,

Mit MySQL können Sie den Wert "0000-00-00" als "Dummy-Datum" speichern. Dies ist in einigen Fällen bequemer als die Verwendung von NULL-Werten und benötigt weniger Daten und Indexraum. Aktivieren Sie den SQL-Modus NO_ZERO_DATE, um '0000-00-00' nicht zuzulassen.

AKTUALISIEREN

In Bezug auf die Bug-Angelegenheit, wie von @ Dylan-Su gesagt:

Ich denke nicht, dass dies der Fehler ist, wie sich MYSQL im Laufe der Zeit entwickelt hat, aufgrund dessen einige Dinge aufgrund weiterer Verbesserungen des Produkts geändert werden.

Ich habe jedoch einen anderen verwandten Fehlerbericht bezüglich der NOW()Funktion

Das Datum / Uhrzeit-Feld akzeptiert keine Standard-JETZT ()

Ein weiterer nützlicher Hinweis [siehe Automatische Initialisierung und Aktualisierung für TIMESTAMP und DATETIME ]

Ab MySQL 5.6.5 können die Spalten TIMESTAMP und DATETIME automatisch initialisiert und auf das aktuelle Datum und die aktuelle Uhrzeit (dh den aktuellen Zeitstempel) aktualisiert werden. Vor 5.6.5 gilt dies nur für TIMESTAMP und höchstens für eine TIMESTAMP-Spalte pro Tabelle. In den folgenden Hinweisen werden zunächst die automatische Initialisierung und Aktualisierung für MySQL 5.6.5 und höher sowie die Unterschiede für Versionen vor 5.6.5 beschrieben.

Update bezüglich NO_ZERO_DATE

Ab MySQL ab 5.7.4 ist dieser Modus veraltet. Für die vorherige Version müssen Sie die entsprechende Zeile in der Konfigurationsdatei auskommentieren. Weitere Informationen finden Sie in der MySQL 5.7-Dokumentation zu NO_ZERO_DATE


5
UPDATE IGNORE ist das, wonach ich gesucht habe Af
Afanasii Kurakin

2
Falsch. Ich habe STRICT_TRANS_TABLESfür meine MySQL-Instanzen sowohl lokale als auch Server. Ich kann zwar problemlos 0000-00-00in meine lokale Instanz einfügen , aber nicht in meine Serverinstanz - Fehler wird ausgelöst. Warum? Weil mein Server MySQL config NO_ZERO_DATEaktiviert hat. Und mein Einheimischer hat es nicht.
Green

ok @Green Ich werde herausfinden und die Antwort aktualisieren, falls zutreffend
Geeksal

4
In meinem Fall hat 'SET sql_mode = ""' nicht funktioniert. 'SET GLOBAL sql_mode = "";' hat den Job für mich gemacht.
Arjen Stens

Auch NO_ZERO_DATEsollte entfernt werden
Preshan Pradeepa

18

Ich hatte diesen Fehler mit WAMP 3.0.6 mit MySql 5.7.14.

Lösung :

Ändern Sie Zeile 70 (wenn Ihre INI-Datei unberührt ist) in der c:\wamp\bin\mysql\mysql5.7.14\my.iniDatei von

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

zu

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

und starten Sie alle Dienste neu.

Dadurch wird der strikte Modus deaktiviert. Gemäß der Dokumentation bedeutet "strikter Modus" einen Modus mit einem oder beiden STRICT_TRANS_TABLESoder STRICT_ALL_TABLESaktiviert. Die Dokumentation sagt:

"Der Standard-SQL-Modus in MySQL 5.7 umfasst die folgenden Modi: ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER und NO_EN.


14

Ich kam in eine Situation, in der die Daten für ein Datumsfeld zwischen NULL und 0000-00-00 gemischt wurden. Aber ich wusste nicht, wie ich die '0000-00-00' auf NULL aktualisieren sollte, weil

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

ist nicht mehr erlaubt. Meine Problemumgehung war ganz einfach:

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

weil alle falschen my_date_fieldWerte (ob korrekte Daten oder nicht) von vor diesem Datum stammten.


2
Perfekte schnelle Lösung. Sie können in der Tat auch verwenden, <'0000-01-01'da es sich natürlich um ein gültiges Datum handelt.
Ricky McMaster

5

Problem mit der Konfigurationssyntax

Auf einigen Versionen von MYSQL (getestet 5.7. *) Unter * nix-Systemen sollten Sie diese Syntax verwenden:

[mysqld]

sql-mode="NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLE,NO_ENGINE_SUBSTITUTION"

Diese werden nicht funktionieren:

Strich keine Anführungszeichen

sql-mode=NO_ENGINE_SUBSTITUTION

unterstreiche keine Anführungszeichen

sql_mode=NO_ENGINE_SUBSTITUTION

Unterstrich und Zitate

sql_mode="NO_ENGINE_SUBSTITUTION"

Eine umfassendere Überprüfung der Konfigurationswerte und des SQL-Modus:

So richten Sie permanente SQL-Modus-Flags ein


5

Wählen Sie zuerst die aktuelle Sitzung aus sql_mode:

SELECT @@SESSION.sql_mode;

Dann erhalten Sie so etwas wie diesen Standardwert :

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

und dann setzen sql_modeohne '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';

Wenn Sie Stipendien haben, können Sie dies auch tun für GLOBAL:

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

4

Fügen Sie einfach die Zeile hinzu: sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Insider-Datei: /etc/mysql/mysql.conf.d/mysqld.cnf

dann sudo service mysql restart


1
Funktioniert für 5.7.23.
user2513149

1
Ich würde wahrscheinlich SELECT @@SESSION.sql_mode;zuerst vorschlagen , und sie entfernen NO_ZERO_IN_DATE, NO_ZERO_DATE und STRICT_TRANS_TABLES von dem, was es Ihnen gibt. Auf diese Weise behalten Sie alle anderen Einstellungen bei, die Sie aktiviert haben. Ich hatte viel mehr als nur diese beiden Elemente für meinen SQL-Modus eingestellt. Ich weiß nicht, was sie alle tun, aber ich möchte nicht riskieren, sie an dieser Stelle zu entfernen.
Radley Sustaire

2

Es funktioniert für 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)

Sie können eine SQLFiddle erstellen, um Ihr Problem neu zu erstellen.

http://sqlfiddle.com/

Wenn es für MySQL 5.6 und 5.7.8 funktioniert, aber am 5.7.11 fehlschlägt. Dann ist es wahrscheinlich ein Regressionsfehler für 5.7.11.


1

So lösen Sie das Problem mit MySQL Workbench (nach dem Anwenden der Lösung auf der Serverseite):

Entfernen Sie SQL_MODE zu TRADITIONAL im Einstellungsfenster.

Geben Sie hier die Bildbeschreibung ein


1

Diese Antwort ist nur für MySQL 5.7:

Das Beste ist, dass der sql_mode nicht wirklich leer gesetzt wird. Verwenden Sie stattdessen in PHP eine Sitzungsvariable mit:

SET SESSION sql_mode= 'ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

Zumindest behalten Sie also die anderen Standardwerte bei.

Es ist verrückt, dass die MySQL-Dokumentation nicht klar ist. Sie müssen diese Standardwerte in sql_mode löschen:

NO_ZERO_IN_DATE, NO_ZERO_DATE, ich verstehe, aber in zukünftigen Versionen wird dies eingestellt.

STRICT_ALL_TABLES, bevor Parameter ignoriert werden, müssen Sie sie ebenfalls löschen.

Schließlich auch TRADITIONAL, aber die Dokumentation spricht über diesen Parameter: "Geben Sie einen Fehler anstelle einer Warnung", wenn Sie einen falschen Wert in eine Spalte einfügen ", mit diesem Parameter werden Daten mit Nullwerten nicht eingefügt, aber ohne Ja.

MySQL ist mit diesen Parametern und Kombinationen nicht wirklich organisiert.


0

Optionskombinationen für mysql Ver 14.14 Distrib 5.7.18, for Linux (x86_64).

Wirft nicht:

STRICT_TRANS_TABLES + NO_ZERO_DATE

Würfe:

STRICT_TRANS_TABLES + NO_ZERO_IN_DATE

Meine Einstellungen /etc/mysql/my.cnfunter Ubuntu:

[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

Im Verzeichnis xamp / mysql / bin Öffnen Sie "my.ini" und ändern Sie die Zeile: Sql_node für ->

"sql_mode = NO_ENGINE_SUBSTITUTION, NO_ZERO_DATE"

ENTFERNEN SIE "NO_ZERO_IN_DATE"


Willkommen bei Stackoverflow. Verwenden Sie die richtige Code-Formatierung, um die Lesbarkeit der Antwort zu verbessern.
Vlizana
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.