Erro no MySQL ao definir o valor padrão para DATE ou DATETIME


124

Estou executando o MySql Server 5.7.11 e esta frase:

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

não está funcionando. Dando o erro:

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

Mas o seguinte:

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

apenas funciona .

O mesmo caso para DATE.

Como nota lateral , ele é mencionado na documentação do MySQL :

O tipo DATE é usado para valores com parte da data, mas sem parte da hora. O MySQL recupera e exibe os valores DATE no formato 'AAAA-MM-DD'. O intervalo compatível é de '1000-01-01' a '9999-12-31'.

mesmo que também digam:

Valores inválidos de DATE, DATETIME ou TIMESTAMP são convertidos para o valor “zero” do tipo apropriado ('0000-00-00' ou '0000-00-00 00:00:00').

Tendo também em conta a segunda citação da documentação do MySQL, alguém poderia me informar por que está apresentando esse erro?


11
Por que você quer um padrão que obviamente não tem sentido? Se a data for desconhecida, então é exatamente NULLpara isso.
Tom H,

Como uma nota: Isso funciona na versão 5.6 no SQL Fiddle - sqlfiddle.com/#!9/02c98 .
Gordon Linoff,

@Karlos verifique a resposta atualizada.
geeksal

Respostas:


209

O erro é devido ao modo sql, que pode ser o modo estrito de acordo com a documentação MYSQL 5.7 mais recente

A documentação do MySQL 5.7 diz :

O modo estrito afeta se o servidor permite '0000-00-00' como uma data válida: Se o modo estrito não estiver ativado, '0000-00-00' é permitido e inserções não produzem nenhum aviso. Se o modo estrito estiver habilitado, '0000-00-00' não é permitido e inserções produzem um erro, a menos que IGNORE seja fornecido também. Para INSERT IGNORE e UPDATE IGNORE, '0000-00-00' é permitido e inserções produzem um aviso.

Para verificar o modo MYSQL

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

Desativando o modo STRICT_TRANS_TABLES

No entanto, para permitir o formato 0000-00-00 00:00:00 você deve desabilitar o modo STRICT_TRANS_TABLES no arquivo de configuração mysql ou por comando

Por comando

SET sql_mode = '';

ou

SET GLOBAL sql_mode = '';

Usando a palavra-chave GLOBAL requer super previlégios e afeta as operações que todos os clientes se conectam a partir daquele momento

se acima não estiver funcionando, vá para /etc/mysql/my.cnf(de acordo com o ubuntu) e comenteSTRICT_TRANS_TABLES

Além disso, se você deseja definir permanentemente o modo sql na inicialização do servidor, inclua SET sql_mode=''no my.cnfLinux ou MacOS. Para Windows, isso deve ser feito em my.iniarquivo.

Nota

No entanto, o modo estrito não é habilitado por padrão no MYSQL 5.6. Portanto, ele não produz o erro de acordo com a documentação MYSQL 6 que diz

O MySQL permite que você armazene um valor “zero” de '0000-00-00' como uma “data fictícia”. Em alguns casos, isso é mais conveniente do que usar valores NULL e usa menos dados e espaço de índice. Para desabilitar '0000-00-00', ative o modo SQL NO_ZERO_DATE.

ATUALIZAR

Em relação ao bug, como dito por @ Dylan-Su:

Não acho que esse seja o bug da maneira como o MYSQL evolui ao longo do tempo, devido ao qual algumas coisas são alteradas com base em melhorias futuras do produto.

No entanto, tenho outro relatório de bug relacionado à NOW()função

O campo data e hora não aceita o padrão AGORA ()

Outra observação útil [consulte Inicialização e atualização automática para TIMESTAMP e DATETIME ]

A partir do MySQL 5.6.5, as colunas TIMESTAMP e DATETIME podem ser inicializadas e atualizadas automaticamente para a data e hora atuais (ou seja, o carimbo de data / hora atual). Antes de 5.6.5, isso era verdadeiro apenas para TIMESTAMP e para no máximo uma coluna TIMESTAMP por tabela. As notas a seguir descrevem primeiro a inicialização e atualização automáticas para MySQL 5.6.5 e superior, depois as diferenças para as versões anteriores a 5.6.5.

Atualização sobre NO_ZERO_DATE

A partir do MySQL a partir de 5.7.4, esse modo está obsoleto. Para a versão anterior, você deve comentar a linha respectiva no arquivo de configuração. Consulte a documentação do MySQL 5.7 em NO_ZERO_DATE


5
ATUALIZAR IGNORAR é o que eu procurava 👍🏻
Afanasii Kurakin

2
Errado. Eu tenho STRICT_TRANS_TABLESpara minhas duas instâncias do MySQL, local e servidor. No entanto, posso inserir facilmente 0000-00-00na minha instância local, mas não na minha instância do servidor - um erro é lançado. Por quê? Porque minha configuração de servidor MySQL foi NO_ZERO_DATEhabilitada. E meu local não tem.
Verde de

ok @Green irei descobrir e atualizar a resposta, se aplicável
geeksal

4
No meu caso, 'SET sql_mode = ""' não funcionou. 'SET GLOBAL sql_mode = "";' fez o trabalho para mim.
Arjen Stens

Também NO_ZERO_DATEdeve ser removido
Preshan Pradeepa

18

Eu tive este erro com WAMP 3.0.6 com MySql 5.7.14.

Solução :

mude a linha 70 (se o seu arquivo ini não foi alterado) no c:\wamp\bin\mysql\mysql5.7.14\my.iniarquivo de

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

para

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

e reinicie todos os serviços.

Isso desativará o modo estrito. De acordo com a documentação, “modo estrito” significa um modo com um ou ambos STRICT_TRANS_TABLESou STRICT_ALL_TABLEShabilitado. A documentação diz:

"O modo SQL padrão no MySQL 5.7 inclui estes modos: ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER e NO_ENGINE_SUBSTITUTION."


14

Eu entrei em uma situação em que os dados foram misturados entre NULL e 0000-00-00 para um campo de data. Mas eu não sabia como atualizar o '0000-00-00' para NULL, porque

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

não é mais permitido. Minha solução alternativa foi bastante simples:

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

porque todos os my_date_fieldvalores incorretos (datas corretas ou não) eram anteriores a esta data.


2
Solução rápida perfeita. Na verdade, você também pode usar, <'0000-01-01'já que é uma data válida.
Ricky McMaster

5

Problema de sintaxe de configuração

Em algumas versões do MYSQL (testado 5.7. *) Em sistemas * nix, você deve usar esta sintaxe:

[mysqld]

sql-mode="NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLE,NO_ENGINE_SUBSTITUTION"

Estes não funcionam:

traço sem aspas

sql-mode=NO_ENGINE_SUBSTITUTION

sublinhado sem aspas

sql_mode=NO_ENGINE_SUBSTITUTION

sublinhado e citações

sql_mode="NO_ENGINE_SUBSTITUTION"

Uma revisão mais completa dos valores de configuração e do modo sql:

Como configurar sinalizadores de modo SQL permanentes


5

Primeiro selecione a sessão atual sql_mode:

SELECT @@SESSION.sql_mode;

Então você obterá algo parecido com o valor padrão :

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

e depois definido sql_modesem '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';

Se você tiver bolsas, também pode fazer isso por GLOBAL:

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

4

Basta adicionar a linha: sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

dentro do arquivo: /etc/mysql/mysql.conf.d/mysqld.cnf

então sudo service mysql restart


1
Funciona para 5.7.23.
user2513149

1
Eu provavelmente sugeriria SELECT @@SESSION.sql_mode;primeiro, e eles removendo NO_ZERO_IN_DATE, NO_ZERO_DATE e STRICT_TRANS_TABLES do que ele oferece. Dessa forma, você mantém todas as outras configurações que ativou. Eu tinha muito mais do que apenas esses dois itens definidos para o meu modo sql. Não sei o que todos eles fazem, mas não quero arriscar removê-los neste momento.
Radley Sustaire

2

Funciona para 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)

Você pode criar um SQLFiddle para recriar seu problema.

http://sqlfiddle.com/

Se funcionar para MySQL 5.6 e 5.7.8, mas falhar em 5.7.11. Então provavelmente será um bug de regressão para 5.7.11.


1

Para resolver o problema com o MySQL Workbench (após aplicar a solução no lado do servidor):

Remova SQL_MODE para TRADITIONAL no painel de preferências.

insira a descrição da imagem aqui


1

Esta resposta é apenas para MySQL 5.7:

Best não é realmente definido em branco no sql_mode, em vez disso, use em PHP uma variável de sessão com:

SET SESSION sql_mode= 'ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

Portanto, pelo menos você mantém os outros valores padrão.

É uma loucura que a documentação do mysql não esteja clara, você precisa deletar esses valores padrão em sql_mode:

NO_ZERO_IN_DATE, NO_ZERO_DATE, eu entendo, mas nas versões futuras isso será descontinuado.

STRICT_ALL_TABLES, com isso, os parâmetros anteriores serão ignorados, então você precisa excluí-los também.

Finalmente também TRADICIONAL, mas a documentação fala sobre este parâmetro: “dar um erro em vez de um aviso” ao inserir um valor incorreto em uma coluna ", com este parâmetro, datas com valor zero não são inseridas, mas sem sim.

O MySQL não é realmente organizado com esses parâmetros e combinações.


0

Combinações de opções para mysql Ver 14.14 Distrib 5.7.18, for Linux (x86_64).

Não atira:

STRICT_TRANS_TABLES + NO_ZERO_DATE

Lança:

STRICT_TRANS_TABLES + NO_ZERO_IN_DATE

Minhas configurações no /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

Em diretory xamp / mysql / bin Abra "my.ini" e altere a linha: Sql_node para ->

"sql_mode = NO_ENGINE_SUBSTITUTION, NO_ZERO_DATE"

REMOVER "NO_ZERO_IN_DATE"


Bem-vindo ao stackoverflow, use a formatação de código adequada para melhorar a legibilidade da resposta.
vlizana
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.