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?

Evhz
fonte
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

geeksal
fonte
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."

bg17aw
fonte
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.

Martin T.
fonte
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

Heroselohim
fonte
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 = '...';
simhumileco
fonte
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

Ferreidon Aftahi
fonte
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.

Dylan Su
fonte
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

Vindic
fonte
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.

Stackdave
fonte
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"
Verde
fonte
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';
Aris tri jaka
fonte
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"

leandro ramos
fonte
Bem-vindo ao stackoverflow, use a formatação de código adequada para melhorar a legibilidade da resposta.
vlizana