Niedawno przejąłem stary projekt, który powstał 10 lat temu. Używa MySQL 5.1.
Między innymi muszę zmienić domyślny zestaw znaków z latin1 na utf8.
Jako przykład mam tabele takie jak ta:
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
Skonfigurowałem własnego Maca do pracy nad tym. Bez zastanawiania się nad tym uruchomiłem "brew install mysql", który zainstalował MySQL 5.7. Więc mam pewne konflikty wersji.
Pobrałem kopię tej bazy danych i zaimportowałem ją.
Jeśli spróbuję uruchomić takie zapytanie:
ALTER TABLE users MODIFY first_name varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
Otrzymuję ten błąd:
ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'created' at row 1
Pomyślałem, że mogę to naprawić za pomocą:
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
ale dostaję:
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
Czy muszę aktualizować każdą wartość?
Nie mogłem tego zrobić:
(w MySQL 5.7.13).
Ciągle otrzymywałem
Incorrect datetime value: '0000-00-00 00:00:00'
błąd.O dziwo, to działało:
SELECT * FROM users WHERE created = '0000-00-00 00:00:00'
. Nie mam pojęcia, dlaczego pierwszy zawodzi, a drugi działa ... może błąd MySQL?W każdym razie to zapytanie UPDATE zadziałało:
źródło
UPDATE users SET created = NULL WHERE created = '0'
entity
WHERE createdAt = "0000-00-00 00:00:00" działa dobrze, ale ze zaktualizowanym niepowodzeniem! Miałem ten sam problem. Napraw to za pomocą rozwiązania @obe CAST (utworzonego AS CHAR (20)) ... Myślę, że to błąd.UPDATE users SET created = NULL WHERE created=0
(bez „około zera)Zmiana wartości domyślnej dla kolumny z
ALTER TABLE
instrukcją, np... nie zmienia żadnych wartości, które są już zapisane. Wartość „domyślna” dotyczy wstawianych wierszy, dla których nie podano wartości dla kolumny.
Jeśli chodzi o przyczynę napotkania tego błędu, prawdopodobnie
sql_mode
ustawienie dla Twojej sesji obejmujeNO_ZERO_DATE
.Źródła: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_date
Po wykonaniu „importu” instrukcje SQL, które wykonały operację INSERT w tej tabeli, zostały uruchomione w sesji, która zezwalała na zerowe daty.
Aby zobaczyć ustawienie sql_mode:
-lub-
Jeśli chodzi o to, jak „naprawić” bieżący problem, aby błąd nie został wyrzucony po uruchomieniu
ALTER TABLE
instrukcji.Kilka opcji:
1) zmień,
sql_mode
aby zezwolić na zerowe daty, usuwającNO_ZERO_DATE
iNO_ZERO_IN_DATE
. Zmianę można zastosować w pliku my.cnf, więc po restarcie serwera MySQL,sql_mode
zmienna zostanie zainicjowana zgodnie z ustawieniem w my.cnf.W przypadku tymczasowej zmiany możemy zmodyfikować ustawienie podczas jednej sesji, bez konieczności zmiany globalnej.
2) Zmień
created
kolumnę, aby zezwolić na wartości NULL, i zaktualizuj istniejące wiersze, aby zmienić daty zerowe na wartości null3) zaktualizuj istniejące wiersze, aby zmienić daty zerowe na prawidłową datę
Nie musimy uruchamiać oddzielnych instrukcji, aby zaktualizować każdy wiersz. Możemy zaktualizować wszystkie wiersze za jednym zamachem (zakładając, że jest to tabela o rozsądnych rozmiarach. W przypadku większej tabeli, aby uniknąć ogromnego generowania wycofywania / cofania, możemy wykonać operację w rozsądnych fragmentach).
W pytaniu
AUTO_INCREMENT
wartość pokazana dla definicji tabeli zapewnia, że liczba wierszy nie jest nadmierna.Jeśli już zmieniliśmy
created
kolumnę, aby zezwalać naNULL
wartości, możemy zrobić coś takiego:Lub możemy ustawić je na ważną datę, np. 2 stycznia 1970
(Zwróć uwagę, że wartość daty i godziny o północy 1 stycznia 1970 r. (
'1970-01-01 00:00:00'
) Jest „datą zerową”. Zostanie ona oceniona jako'0000-00-00 00:00:00'
źródło
sql_mode
. Nowsze wersje MySQL mają domyślne ustawienia,sql_mode
które są bardziej rygorystyczne niż poprzednie wersje. Wniosek o 8,0 tutaj: dev.mysql.com/doc/refman/8.0/en/sql-mode.html SeeNO_ZERO_DATE
,ALLOW_INVALID_DATE
et al. pamiętać, że niektóre z nich są włączone w trybie ścisłym npSTRICT_TRANS_TABLES
,STRICT_ALL_TABLES
a innymi formami kombi. Aby obejść ograniczenia, tymczasowo zmodyfikuj tryb sql_mode dla sesji,Naprawiłem to, robiąc to przed zapytaniem
źródło
Zgodnie z podręcznikiem MySQL 5.7 :
Ponieważ
0000-00-00 00:00:00
nie jest to prawidłowaDATETIME
wartość, twoja baza danych jest uszkodzona. Dlatego MySQL 5.7 - który jestNO_ZERO_DATE
domyślnie włączony w tryb - wyświetla błąd podczas próby wykonania operacji zapisu.Możesz naprawić swoją tabelę, aktualizując wszystkie nieprawidłowe wartości na inne prawidłowe, na przykład
NULL
:Ponadto, aby uniknąć tego problemu, radzę zawsze ustawiać bieżący czas jako wartość domyślną dla
created
pól-like, aby były one automatycznie wypełnianeINSERT
. Po prostu zrób:źródło
źródło
Oto moje rozwiązanie PhpMyAdmin / Fedora 29 / MySQL 8.0 (na przykład):
set sql_mode='SOMETHING';
nie działa , wywołanie polecenia powiodło się, ale nic się nie zmieniło.set GLOBAL sql_mode='SOMETHING';
zmiana konfiguracji globalnej trwała zmiana.set SESSION sql_mode='SOMETHING';
zmiana konfiguracji sesji Zmienna SESSION dotyczy tylko bieżącego klienta.https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html
Więc robię to:
SHOW VARIABLES LIKE 'sql_mode';
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
NO_ZERO_IN_DATE,NO_ZERO_DATE
set GLOBAL SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
W ten sam sposób możesz usunąć lub dodać inny tryb.
Jest to pomocne przy zmianie globalnej na używanie i testowanie frameworków lub sql_mode muszą być określone w każdym pliku lub grupie zapytań.
Na podstawie pytania zadanego tutaj: how-can-i-disable-mysql -rict-mode
Przykład: zainstaluj najnowszą zawartość Joomla 4.0-alpha.
Edycja: W PhpMyadmin, jeśli masz kontrolę nad serwerem, możesz zmienić
sql_mode
(i wszystkie inne parametry) bezpośrednio wPlus > Variables > sql_mode
źródło
Możesz zmienić typ tworzonego pola z
datetime
navarchar(255)
, następnie możesz ustawić (zaktualizować) wszystkie rekordy, które mają wartość"0000-00-00 00:00:00"
naNULL
.Teraz możesz wykonywać zapytania bez błędów. Po zakończeniu można zmienić typ pola utworzonego na
datetime
.źródło
Ten błąd też mam po aktualizacji MySQL z 5.6 do 5.7
Doszedłem do wniosku, że najlepszym rozwiązaniem dla mnie jest połączenie niektórych rozwiązań tutaj i zrobienie czegoś, co działa przy minimalnym wkładzie.
Używam MyPHPAdmin ze względu na prostotę wysyłania zapytań przez interfejs, ponieważ wtedy mogę łatwo sprawdzić strukturę i wszystko to w prosty sposób. Możesz użyć ssh bezpośrednio lub innego interfejsu. Metoda i tak powinna być podobna lub taka sama.
...
1.
Najpierw sprawdź rzeczywisty błąd podczas próby naprawy db:
To mówi mi, że kolumna check_out_time w tabeli jos_menu musi mieć naprawione wszystkie złe daty, a także zmienioną „domyślną”.
...
2.
Uruchamiam zapytanie SQL na podstawie informacji w komunikacie o błędzie:
Jeśli pojawi się błąd, możesz zamiast tego użyć poniższego zapytania, które wydaje się zawsze działać:
...
3.
Następnie, gdy to się skończy, uruchamiam drugie zapytanie SQL:
Lub w przypadku, gdy jest to data, która musi być NULL
...
Jeśli teraz uruchomię bazę danych napraw, otrzymam:
joomla.jos_menu OK
...
Działa dobrze :)
źródło
Czek
jeśli zobaczysz tam dane „ZERO_DATE”, spróbuj
Wyloguj się i zaloguj ponownie do swojego klienta (to dziwne) i spróbuj ponownie
źródło
Spraw, aby tryb sql nie był rygorystyczny
jeśli używasz laravel, przejdź do config-> database, przejdź do ustawień mysql i ustaw tryb ścisły na false
źródło
Miałem podobny problem, ale w moim przypadku jakaś linia miała wartość NULL.
więc najpierw aktualizuję tabelę:
problem rozwiązany, przynajmniej w moim przypadku.
źródło
Ja też dostałem
informacje o błędzie
Napraw to, zmieniając
0000-00-00 00:00:00
na1970-01-01 08:00:00
1970-01-01 08:00:00
unix timestamp to 0źródło
NO_ZERO_DATE
Rozwiązanie znalazłem na https://support.plesk.com/hc/en-us/articles/115000666509-How-to-change-the-SQL-mode-in-MySQL . Miałem to:
Zwróć uwagę
NO_ZERO_IN_DATE,NO_ZERO_DATE
na powyższe wyniki. Usunąłem to, robiąc to:Wtedy miałem to:
Po wykonaniu tej czynności mogłem z
ALTER TABLE
powodzeniem używać i modyfikować moje tabele.źródło
Oto, co zrobiłem, aby rozwiązać mój problem. Testowałem w lokalnym MySQL 5.7 ubuntu 18.04.
Przed uruchomieniem tego zapytania globalnie dodałem plik cnf w katalogu /etc/mysql/conf.d . Nazwa pliku cnf to mysql.cnf i kody
Następnie ponownie uruchamiam mysql
Mam nadzieję, że to może komuś pomóc.
źródło
NO_ENGINE_SUBSTITUTION
jest we wszystkich kolumnach,SELECT @@global.sql_mode, @@session.sql_mode, @@sql_mode;
ale nadal pojawia się błąd dotyczący nieprawidłowej daty i godziny,0000-00-00 00:00:00
dopóki ponownie nie wykonam pierwszego zapytania.set global sql_mode="NO_ENGINE_SUBSTITUTION";
Jakieś pomysły?NO_ZERO_IN_DATE,NO_ZERO_DATE
w Twojej wersji linii my.ini definiującej pliksql_mode
.Jest to niesamowicie brzydkie, ale szybko rozwiązało problem. Twoja tabela wymaga unikalnego klucza, którego użyjesz do naprawy skażonych kolumn. W tym przykładzie klucz podstawowy nosi nazwę „id”, a uszkodzona kolumna z sygnaturą czasową nosi nazwę „BadColumn”.
Wybierz identyfikatory skażonych kolumn.
select id from table where BadColumn='0000-00-00 00:00:00'
Zbierz identyfikatory w ciąg rozdzielany przecinkami. Przykład:
1, 22, 33
. Użyłem do tego zewnętrznego opakowania (skryptu Perla), aby szybko je wszystkie wypluć.Skorzystaj z listy identyfikatorów, aby zaktualizować stare kolumny o prawidłową datę (od 1971 do 2038).
update table set BadColumn='2000-01-01 00:00:00' where id in (1, 22, 33)
źródło
Moje rozwiązanie
źródło
Zamiast
Posługiwać się
źródło
Jeśli wprowadzasz dane ręcznie, możesz rozważyć usunięcie wartości i zer z TIMESTAMP (6) .000000, tak aby stał się TIMESTAMP. U mnie to działało dobrze.
źródło