MySQL Falscher Datumswert: '0000-00-00 00:00:00'
Ich habe kürzlich ein altes Projekt übernommen, das vor 10 Jahren erstellt wurde. Es verwendet MySQL 5.1.
Unter anderem muss ich den Standardzeichensatz von latin1 auf utf8 ändern.
Ich habe zum Beispiel Tabellen wie die folgende:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(45) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`last_name` varchar(45) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`username` varchar(127) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`email` varchar(127) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`pass` varchar(20) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`active` char(1) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL DEFAULT 'Y',
`created` datetime NOT NULL,
`last_login` datetime DEFAULT NULL,
`author` varchar(1) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT 'N',
`locked_at` datetime DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`ripple_token` varchar(36) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`ripple_token_expires` datetime DEFAULT '2014-10-31 08:03:55',
`authentication_token` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index_users_on_reset_password_token` (`reset_password_token`),
UNIQUE KEY `index_users_on_confirmation_token` (`confirmation_token`),
UNIQUE KEY `index_users_on_unlock_token` (`unlock_token`),
KEY `users_active` (`active`),
KEY `users_username` (`username`),
KEY `index_users_on_email` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=1677 DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC
Ich habe meinen eigenen Mac eingerichtet, um daran zu arbeiten. Ohne groß darüber nachzudenken, habe ich "brew install mysql" ausgeführt, wodurch MySQL 5.7 installiert wurde. Ich habe also einige Versionskonflikte.
Ich lud eine Kopie dieser Datenbank herunter und importierte sie.
Wenn ich versuche, eine Abfrage wie diese auszuführen:
ALTER TABLE users MODIFY first_name varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
erhalte ich diesen Fehler:
ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'created' at row 1
Ich dachte, ich könnte das mit beheben:
ALTER TABLE users MODIFY created datetime NULL DEFAULT '1970-01-01 00:00:00';
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
aber ich bekomme:
ALTER TABLE users MODIFY first_name varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ;
ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'created' at row 1
Muss ich jeden Wert aktualisieren?
124
3
Ich war nicht in der Lage, dies zu tun:
(unter MySQL 5.7.13).
Ich bekam immer wieder den Fehler "Falscher Datumswert: '0000-00-00 00:00:00'`.
Seltsamerweise funktionierte dies:
SELECT * FROM users WHERE created = '0000-00-00 00:00:00'
. Ich habe keine Ahnung, warum ersteres fehlschlägt und letzteres funktioniert... vielleicht ein MySQL-Fehler?Auf jeden Fall hat diese UPDATE-Abfrage funktioniert:
Ändern des Standardwertes für eine Spalte mit einer
ALTER TABLE
-Anweisung, z.B.... ändert keine Werte, die bereits gespeichert sind. Der "Standardwert" gilt für Zeilen, die eingefügt werden und für die kein Wert für die Spalte geliefert wird.
Was den Grund für den Fehler angeht, so ist es wahrscheinlich, dass die
sql_mode
-Einstellung für Ihre SitzungNO_ZERO_DATE
enthält.Referenz: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_date
Als Sie den "Import" durchführten, wurden die SQL-Anweisungen, die das INSERT in diese Tabelle durchführten, in einer Sitzung ausgeführt, die Nulldaten zuließ.
Um die sql_mode-Einstellung zu sehen:
-oder-
Wie kann man das aktuelle Problem beheben, so dass der Fehler nicht mehr auftritt, wenn man die Anweisung "ALTER TABLE" ausführt?
Es gibt mehrere Möglichkeiten:
sql_mode
so, dass er Null-Daten zulässt, indem SieNO_ZERO_DATE
undNO_ZERO_IN_DATE
entfernen. Die Änderung kann in der Datei my.cnf vorgenommen werden, so dass nach einem Neustart des MySQL-Servers die Variablesql_mode
mit der Einstellung in my.cnf initialisiert wird.Für eine temporäre Änderung können wir die Einstellung mit einer einzigen Sitzung ändern, ohne dass eine globale Änderung erforderlich ist.
Ändern Sie die Spalte
created
, um NULL-Werte zuzulassen, und aktualisieren Sie die vorhandenen Zeilen, um die Null-Daten in Null-Werte zu ändernaktualisieren Sie die vorhandenen Zeilen, um die Null-Daten in ein gültiges Datum zu ändern
Wir müssen keine einzelnen Anweisungen ausführen, um jede Zeile zu aktualisieren. Wir können alle Zeilen auf einen Schlag aktualisieren (vorausgesetzt, es handelt sich um eine Tabelle von angemessener Größe). Bei einer größeren Tabelle können wir die Operation in angemessen großen Stücken durchführen, um ein riesiges Rollback/Undo zu vermeiden).
Der in der Frage angegebene Wert "AUTO_INCREMENT" für die Tabellendefinition gibt uns die Sicherheit, dass die Anzahl der Zeilen nicht zu hoch ist.
Wenn wir die Spalte
created
bereits geändert haben, umNULL
-Werte zuzulassen, können wir etwas wie folgt tun:Oder wir können sie auf ein gültiges Datum setzen, z.B. 2. Januar 1970
(Beachten Sie, dass ein datetime-Wert von Mitternacht des 1. Januar 1970 (
'1970-01-01 00:00:00'
) *ein "Null-Datum" ist. Dies wird als'0000-00-00 00:00:00'
ausgewertet.Wenn die Tabelle leer oder nicht sehr groß ist, schlage ich vor, die Erstellungsanweisungen als .sql-Datei zu exportieren und sie nach Belieben umzuschreiben. Machen Sie dasselbe, wenn Sie bereits Daten haben, d.h. exportieren Sie die Einfügeanweisungen (ich empfehle, dies in einer separaten Datei wie die Erstellungsanweisungen zu tun). Zum Schluss lassen Sie die Tabelle fallen und führen zuerst die create-Anweisungen und dann die inserts aus.
Sie können dafür entweder den Befehl
mysqldump
verwenden, der in Ihrer MySQL-Installation enthalten ist, oder Sie können auch MySQL Workbench installieren, ein kostenloses grafisches Tool, das auch diese Option auf sehr anpassbare Weise enthält, ohne dass Sie nach spezifischen Befehlsoptionen suchen müssen.