Recentemente, assumi um projeto antigo, criado há 10 anos. Ele usa o MySQL 5.1.
Entre outras coisas, preciso alterar o conjunto de caracteres padrão de latin1 para utf8.
Como exemplo, tenho tabelas como esta:
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
Eu configurei meu próprio Mac para trabalhar nisso. Sem pensar muito, executei o "brew install mysql", que instalava o MySQL 5.7. Então, eu tenho alguns conflitos de versão.
Eu baixei uma cópia desse banco de dados e importei.
Se eu tentar executar uma consulta como esta:
ALTER TABLE users MODIFY first_name varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
Eu recebo este erro:
ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'created' at row 1
Eu pensei que eu poderia consertar isso com:
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
mas eu entendo:
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
Preciso atualizar todos os valores?
Não pude fazer isso:
(no MySQL 5.7.13).
Eu continuei recebendo o
Incorrect datetime value: '0000-00-00 00:00:00'
erro.Estranhamente, isso funcionou:
SELECT * FROM users WHERE created = '0000-00-00 00:00:00'
. Não tenho idéia por que o primeiro falha e o último funciona ... talvez um bug do MySQL?De qualquer forma, essa consulta UPDATE funcionou:
fonte
UPDATE users SET created = NULL WHERE created = '0'
entity
WHERE createdAt = "0000-00-00 00:00:00" funciona bem, mas com uma falha atualizada! Eu tive o mesmo problema. Corrija-o com a solução do @obe CAST (criado como CHAR (20)) ... acho que é um bug.UPDATE users SET created = NULL WHERE created=0
(sem "em torno de zero)"Alterando o valor padrão para uma coluna com uma
ALTER TABLE
instrução, por exemplo... não altera nenhum valor que já esteja armazenado. O valor "padrão" se aplica às linhas inseridas e para as quais um valor não é fornecido para a coluna.
Quanto ao motivo pelo qual você está encontrando o erro, é provável que a
sql_mode
configuração da sua sessão incluaNO_ZERO_DATE
.Referência: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_date
Quando você fez a "importação", as instruções SQL que fizeram o INSERT nessa tabela foram executadas em uma sessão que permitia zero datas.
Para ver a configuração sql_mode:
-ou-
Na medida em que "consertar" o problema atual, para que o erro não seja gerado quando você executar o
ALTER TABLE
instrução.Várias opções:
1) altere
sql_mode
para permitir zero datas, removendoNO_ZERO_DATE
eNO_ZERO_IN_DATE
. A alteração pode ser aplicada no arquivo my.cnf; portanto, após a reinicialização do MySQL Server,sql_mode
variável será inicializada com a configuração em my.cnf.Para uma mudança temporária, podemos modificar a configuração com uma única sessão, sem exigir uma mudança global.
2) mude o
created
coluna para permitir valores NULL e atualize as linhas existentes para alterar as datas zero para valores nulos3) atualize as linhas existentes para alterar as datas zero para uma data válida
Não precisamos executar instruções individuais para atualizar cada linha. Podemos atualizar todas as linhas de uma só vez (assumindo que seja uma tabela de tamanho razoável. Para uma tabela maior, para evitar a geração de desfazer / desfazer enormes, podemos executar a operação em pedaços de tamanho razoável.)
Na pergunta, o
AUTO_INCREMENT
valor mostrado para a definição da tabela garante que o número de linhas não seja excessivo.Se já alteramos a
created
coluna para permitirNULL
valores, podemos fazer algo assim:Ou, podemos configurá-los para uma data válida, por exemplo, 2 de janeiro de 1970
(Observe que um valor datetime da meia-noite de 1º de janeiro de 1970 (
'1970-01-01 00:00:00'
) é uma "data zero". Isso será avaliado como'0000-00-00 00:00:00'
fonte
sql_mode
. Versões mais recentes do MySQL têm configurações padrãosql_mode
mais rigorosas que as versões anteriores. Referência para 8,0 aqui: dev.mysql.com/doc/refman/8.0/en/sql-mode.html verNO_ZERO_DATE
,ALLOW_INVALID_DATE
et al. note que alguns estão incluídos no modo STRICT, por exemploSTRICT_TRANS_TABLES
,STRICT_ALL_TABLES
e outros modos de combinação. Para contornar as restrições, modificar temporariamente sql_mode para a sessão,Eu o consertei fazendo isso antes da consulta
fonte
De acordo com o Manual de Referência do MySQL 5.7 :
Como
0000-00-00 00:00:00
não é umDATETIME
valor válido , seu banco de dados está quebrado. É por isso que o MySQL 5.7 - que vem com oNO_ZERO_DATE
modo ativado por padrão - gera um erro quando você tenta executar uma operação de gravação.Você pode corrigir sua tabela atualizando todos os valores inválidos para qualquer outro válido, como
NULL
:Além disso, para evitar esse problema, recomendo que você sempre defina a hora atual como valor padrão para seus
created
campos semelhantes, para que sejam preenchidos automaticamenteINSERT
. Apenas faça:fonte
fonte
Aqui está minha solução PhpMyAdmin / Fedora 29 / MySQL 8.0 (por exemplo):
set sql_mode='SOMETHING';
não funciona , chamada de comando bem-sucedida, mas nada foi alterado.set GLOBAL sql_mode='SOMETHING';
alterar configuração global mudança permanente.set SESSION sql_mode='SOMETHING';
alterar a configuração da sessão A variável SESSION afeta apenas o cliente atual.https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html
Então eu faço isso:
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'
Você pode remover ou adicionar outro modo da mesma maneira.
É útil mudar globalmente para usar e testar estruturas ou o modo sql_mode deve ser especificado em cada arquivo ou grupo de consultas.
Adaptado de uma pergunta, pergunte aqui: como-posso-desativar-mysql-strict-mode
Exemplo: instale o conteúdo mais recente do Joomla 4.0-alpha.
Edit: No PhpMyadmin, se você tiver o controle do servidor, poderá alterar o
sql_mode
(e todos os outros parâmetros) diretamente emPlus > Variables > sql_mode
fonte
Você pode alterar o tipo de criado campo de
datetime
paravarchar(255)
, em seguida, você pode definir (atualização) todos os registros que têm o valor"0000-00-00 00:00:00"
paraNULL
.Agora, você pode fazer suas consultas sem erros. Depois de terminar, você pode alterar o tipo do campo criado para
datetime
.fonte
Eu também tenho esse erro depois de atualizar o MySQL de 5.6 para 5.7
Eu descobri que a melhor solução para mim era combinar algumas das soluções aqui e criar algo que funcionasse com o mínimo de entrada.
Eu uso o MyPHPAdmin pela simplicidade de enviar as consultas pela interface, porque então posso verificar a estrutura e tudo isso facilmente. Você pode usar o ssh diretamente ou alguma outra interface. O método deve ser semelhante ou mesmo assim.
...
1
Primeiro, verifique o erro real ao tentar reparar o banco de dados:
Isso indica que a coluna check_out_time na tabela jos_menu precisa ter todas as datas incorretas fixadas, assim como o "padrão" alterado.
...
2)
Eu executo a consulta SQL com base nas informações na mensagem de erro:
Se você receber um erro, poderá usar a consulta abaixo que parece sempre funcionar:
...
3)
Feito isso, execute a segunda consulta SQL:
Ou, no caso, é uma data que precisa ser NULL
...
Se eu executar o banco de dados de reparo agora, recebo:
joomla.jos_menu OK
...
Funciona muito bem :)
fonte
Verifica
se você vir o item 'ZERO_DATE', tente
Saia e entre novamente no seu cliente (isso é estranho) e tente novamente
fonte
Tornar o modo sql não rigoroso
se estiver usando laravel, vá para config-> database, vá para mysql settings e torne o modo strict falso
fonte
Eu tive um problema semelhante, mas no meu caso, alguma linha tinha o valor NULL.
então primeiro eu atualizo a tabela:
problema resolvido, pelo menos no meu caso.
fonte
Eu também tenho
informação de erro
Corrija isso alterando
0000-00-00 00:00:00
para1970-01-01 08:00:00
1970-01-01 08:00:00
o carimbo de hora unix é 0fonte
NO_ZERO_DATE
Encontrei a solução em https://support.plesk.com/hc/en-us/articles/115000666509-How-to-change-the-SQL-mode-in-MySQL . Eu tive isso:
Observe o
NO_ZERO_IN_DATE,NO_ZERO_DATE
resultado acima. Eu removi isso fazendo o seguinte:Então eu tive isso:
Depois disso, eu poderia usar com
ALTER TABLE
êxito e alterar minhas tabelas.fonte
Foi isso que fiz para resolver meu problema. Eu testei no MySQL 5.7 local ubuntu 18.04.
Antes de executar esta consulta globalmente, adicionei um arquivo cnf no diretório /etc/mysql/conf.d . O nome do arquivo cnf é mysql.cnf e códigos
Então eu reinicio o mysql
Espero que isso possa ajudar alguém.
fonte
NO_ENGINE_SUBSTITUTION
está em todas as colunas de,SELECT @@global.sql_mode, @@session.sql_mode, @@sql_mode;
mas ainda assim recebo um erro pelo datetime inválido0000-00-00 00:00:00
até executar a primeira consulta novamente.set global sql_mode="NO_ENGINE_SUBSTITUTION";
Alguma idéia?NO_ZERO_IN_DATE,NO_ZERO_DATE
na sua versão da linha my.ini que define o arquivosql_mode
.Isso é incrivelmente feio, mas também corrigiu o problema rapidamente para mim. Sua tabela precisa de uma chave exclusiva que você usará para corrigir as colunas contaminadas. Neste exemplo, a chave primária é chamada 'id' e a coluna de carimbo de data / hora quebrada é chamada 'BadColumn'.
Selecione os IDs das colunas contaminadas.
select id from table where BadColumn='0000-00-00 00:00:00'
Colete os IDs em uma sequência delimitada por vírgula. Exemplo:
1, 22, 33
. Eu usei um invólucro externo para isso (um script Perl) para cuspir rapidamente todos eles.Use sua lista de IDs para atualizar as colunas antigas com uma data válida (1971 a 2038).
update table set BadColumn='2000-01-01 00:00:00' where id in (1, 22, 33)
fonte
Minha solução
fonte
Ao invés de
Usar
fonte
Se você estiver inserindo os dados manualmente, considere remover os valores e os zeros no TIMESTAMP (6) .000000 para que ele se torne TIMESTAMP. Isso funcionou bem comigo.
fonte