Errore in MySQL durante l'impostazione del valore predefinito per DATE o DATETIME


124

Sto eseguendo MySql Server 5.7.11 e questa frase:

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

è non lavorare. Dando l'errore:

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

Ma quanto segue:

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

funziona e basta .

Lo stesso caso per DATE.

Come nota a margine , è menzionato nei documenti di MySQL :

Il tipo DATE viene utilizzato per i valori con una parte di data ma nessuna parte di tempo. MySQL recupera e visualizza i valori DATE nel formato "AAAA-MM-GG". L'intervallo supportato è compreso tra "1000-01-01" e "9999-12-31".

anche se dicono anche:

I valori DATE, DATETIME o TIMESTAMP non validi vengono convertiti nel valore "zero" del tipo appropriato ("0000-00-00" o "0000-00-00 00:00:00").

Tenendo conto anche della seconda citazione dalla documentazione di MySQL, qualcuno potrebbe farmi sapere perché dà quell'errore?


11
Perché vorresti un'impostazione predefinita che è ovviamente priva di significato? Se la data è sconosciuta, allora è esattamente a cosa NULLserve.
Tom H

Nota: funziona nella versione 5.6 su SQL Fiddle - sqlfiddle.com/#!9/02c98 .
Gordon Linoff

@Karlos controlla la risposta aggiornata.
geeksal

Risposte:


209

L'errore è dovuto alla modalità sql che può essere modalità rigorosa secondo l'ultima documentazione di MYSQL 5.7

La documentazione di MySQL 5.7 dice :

La modalità rigorosa determina se il server consente o meno "0000-00-00" come data valida: se la modalità rigorosa non è abilitata, è consentita "0000-00-00" e gli inserti non producono alcun avviso. Se la modalità rigorosa è abilitata, "0000-00-00" non è consentito e gli inserimenti producono un errore, a meno che non venga fornito anche IGNORE. Per INSERT IGNORE e UPDATE IGNORE, è consentito "0000-00-00" e gli inserimenti producono un avviso.

Per controllare la modalità MYSQL

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

Disattivazione della modalità STRICT_TRANS_TABLES

Tuttavia per consentire il formato 0000-00-00 00:00:00è necessario disabilitare la modalità STRICT_TRANS_TABLES nel file di configurazione mysql o tramite comando

A comando

SET sql_mode = '';

o

SET GLOBAL sql_mode = '';

L'utilizzo della parola chiave GLOBALrichiede superpreciliges e influisce sulle operazioni che tutti i client si connettono da quel momento in poi

se sopra non funziona vai su /etc/mysql/my.cnf(come per ubuntu) e commentaSTRICT_TRANS_TABLES

Inoltre, se desideri impostare in modo permanente la modalità sql all'avvio del server, includi SET sql_mode=''in my.cnfLinux o MacOS. Per Windows questo deve essere fatto in my.inifile.

Nota

Tuttavia, la modalità rigorosa non è abilitata per impostazione predefinita in MYSQL 5.6. Quindi non produce l'errore come da documentazione MYSQL 6 che dice

MySQL ti consente di memorizzare un valore "zero" di "0000-00-00" come "data fittizia". Questo in alcuni casi è più conveniente rispetto all'utilizzo di valori NULL e utilizza meno dati e spazio dell'indice. Per non consentire "0000-00-00", abilitare la modalità SQL NO_ZERO_DATE.

AGGIORNARE

Per quanto riguarda la questione dei bug, come detto da @ Dylan-Su:

Non credo che questo sia il bug nel modo in cui MYSQL si è evoluto nel tempo a causa del quale alcune cose sono cambiate in base a ulteriori miglioramenti del prodotto.

Tuttavia ho un'altra segnalazione di bug relativa alla NOW()funzione

Il campo data / ora non accetta il valore predefinito NOW ()

Un'altra nota utile [vedi Inizializzazione e aggiornamento automatici per TIMESTAMP e DATETIME ]

A partire da MySQL 5.6.5, le colonne TIMESTAMP e DATETIME possono essere inizializzate automaticamente e aggiornate alla data e all'ora correnti (ovvero, il timestamp corrente). Prima della 5.6.5, questo è vero solo per TIMESTAMP e per al massimo una colonna TIMESTAMP per tabella. Le seguenti note descrivono prima l'inizializzazione e l'aggiornamento automatici per MySQL 5.6.5 e versioni successive, quindi le differenze per le versioni precedenti 5.6.5.

Aggiornamento relativo a NO_ZERO_DATE

A partire dalla versione 5.7.4 di MySQL, questa modalità è deprecata. Per la versione precedente è necessario commentare la rispettiva riga nel file di configurazione. Fare riferimento alla documentazione di MySQL 5.7 su NO_ZERO_DATE


5
UPDATE IGNORE è quello che stavo cercando 👍🏻
Afanasii Kurakin

2
Sbagliato. Ho STRICT_TRANS_TABLESper entrambe le mie istanze MySQL, locale e server. Tuttavia, posso facilmente inserire 0000-00-00nella mia istanza locale, ma non posso nell'istanza del mio server: viene generato un errore. Perché? Perché il mio server MySQL config è NO_ZERO_DATEabilitato. E il mio locale non ce l'ha.
Verde

ok @Green Capirò e aggiornerò la risposta se applicabile
geeksal

4
Nel mio caso "SET sql_mode =" "" non ha funzionato. "SET GLOBAL sql_mode =" ";" ha fatto il lavoro per me.
arjen Stens

Inoltre NO_ZERO_DATEdovrebbe essere rimosso
Preshan Pradeepa

18

Ho riscontrato questo errore con WAMP 3.0.6 con MySql 5.7.14.

Soluzione :

cambia la riga 70 (se il tuo file ini non è stato modificato) nel c:\wamp\bin\mysql\mysql5.7.14\my.inifile da

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

per

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

e riavvia tutti i servizi.

Questo disabiliterà la modalità rigorosa. Secondo la documentazione, "modalità rigorosa" indica una modalità con uno o entrambi STRICT_TRANS_TABLESo STRICT_ALL_TABLESabilitati. La documentazione dice:

"La modalità SQL predefinita in MySQL 5.7 include queste modalità: 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_SUBSTIT."


14

Sono entrato in una situazione in cui i dati erano mescolati tra NULL e 0000-00-00 per un campo data. Ma non sapevo come aggiornare il "0000-00-00" a NULL, perché

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

non è più consentito. La mia soluzione alternativa è stata abbastanza semplice:

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

perché tutti i my_date_fieldvalori errati (indipendentemente dal fatto che le date siano corrette o meno) risalgono a prima di questa data.


2
Soluzione rapida perfetta. Potresti infatti anche usarla <'0000-01-01'visto che ovviamente è una data valida.
Ricky McMaster

5

Problema di sintassi di configurazione

Su alcune versioni di MYSQL (testato 5.7. *) Con sistemi * nix dovresti usare questa sintassi:

[mysqld]

sql-mode="NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLE,NO_ENGINE_SUBSTITUTION"

Questi non funzioneranno:

trattino senza virgolette

sql-mode=NO_ENGINE_SUBSTITUTION

Sottolineare senza virgolette

sql_mode=NO_ENGINE_SUBSTITUTION

trattino basso e virgolette

sql_mode="NO_ENGINE_SUBSTITUTION"

Una revisione più completa dei valori di configurazione e della modalità sql:

Come impostare flag permanenti in modalità SQL


5

Seleziona prima la sessione corrente sql_mode:

SELECT @@SESSION.sql_mode;

Quindi otterrai qualcosa di simile a quel valore predefinito :

'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 quindi impostare sql_modesenza '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 hai delle borse di studio puoi farlo anche per GLOBAL:

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

4

Basta aggiungere la riga: sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

all'interno del file: /etc/mysql/mysql.conf.d/mysqld.cnf

poi sudo service mysql restart


1
Funziona per 5.7.23.
user2513149

1
Probabilmente suggerirei SELECT @@SESSION.sql_mode;prima e rimuovono NO_ZERO_IN_DATE, NO_ZERO_DATE e STRICT_TRANS_TABLES da ciò che ti offre. In questo modo manterrai tutte le altre impostazioni che avevi abilitato. Avevo molto di più di quei due elementi impostati per la mia modalità sql. Non so cosa fanno tutti, ma non voglio rischiare di rimuoverli a questo punto.
Radley Sustaire

2

Funziona per 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)

Puoi creare un SQLFiddle per ricreare il problema.

http://sqlfiddle.com/

Se funziona per MySQL 5.6 e 5.7.8, ma fallisce su 5.7.11. Quindi probabilmente si tratta di un bug di regressione per 5.7.11.


1

Per risolvere il problema con MySQL Workbench (dopo aver applicato la soluzione lato server):

Rimuovi da SQL_MODE a TRADITIONAL nel pannello delle preferenze.

inserisci qui la descrizione dell'immagine


1

Questa risposta è solo per MySQL 5.7:

Best non è realmente impostato come vuoto sql_mode, utilizza invece in PHP una variabile di sessione con:

SET SESSION sql_mode= 'ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

Quindi almeno mantieni gli altri valori predefiniti.

È pazzesco che la documentazione di mysql non sia chiara, è necessario eliminare questi valori predefiniti in sql_mode:

NO_ZERO_IN_DATE, NO_ZERO_DATE, capisco, ma nelle versioni future questo verrà interrotto.

STRICT_ALL_TABLES, con questo, i parametri prima verranno ignorati, quindi è necessario eliminarli anche.

Infine anche TRADIZIONALE, ma la documentazione parla di questo parametro: “dare un errore invece di un avvertimento” quando si inserisce un valore errato in una colonna ”, con questo parametro non si inseriscono date con valore zero, ma senza si.

MySQL non è realmente organizzato con questi parametri e combinazioni.


0

Combinazioni di opzioni per mysql Ver 14.14 Distrib 5.7.18, for Linux (x86_64).

Non lancia:

STRICT_TRANS_TABLES + NO_ZERO_DATE

Produce:

STRICT_TRANS_TABLES + NO_ZERO_IN_DATE

Le mie impostazioni /etc/mysql/my.cnfsu Ubuntu:

[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

Nella directory xamp / mysql / bin Apri "my.ini" e cambia riga: Sql_node per ->

"Sql_mode = NO_ENGINE_SUBSTITUTION, NO_ZERO_DATE"

RIMUOVI "NO_ZERO_IN_DATE"


Benvenuto in stackoverflow, utilizza la formattazione del codice corretta per migliorare la leggibilità della risposta.
vlizana
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.