Erreur dans MySQL lors de la définition de la valeur par défaut pour DATE ou DATETIME

124

J'exécute MySql Server 5.7.11 et cette phrase:

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

est pas de travail. Donner l'erreur:

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

Mais ce qui suit:

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

fonctionne juste .

Même cas pour DATE.

En guise de remarque , il est mentionné dans la documentation MySQL :

Le type DATE est utilisé pour les valeurs avec une partie date mais aucune partie heure. MySQL récupère et affiche les valeurs DATE au format «AAAA-MM-JJ». La plage prise en charge va de «1000-01-01» à «9999-12-31».

même s'ils disent aussi:

Les valeurs DATE, DATETIME ou TIMESTAMP non valides sont converties en valeur «zéro» du type approprié («0000-00-00» ou «0000-00-00 00:00:00»).

Ayant également pris en compte la deuxième citation de la documentation MySQL, quelqu'un pourrait-il me dire pourquoi il donne cette erreur?

Evhz
la source
11
Pourquoi voudriez-vous une valeur par défaut qui n'a manifestement aucun sens? Si la date est inconnue, c'est exactement ce à quoi ça NULLsert.
Tom H
Remarque: cela fonctionne dans la version 5.6 sur SQL Fiddle - sqlfiddle.com/#!9/02c98 .
Gordon Linoff le
@Karlos vérifie la réponse mise à jour.
geeksal

Réponses:

209

L'erreur est due au mode sql qui peut être le mode strict selon la dernière documentation MYSQL 5.7

MySQL Documentation 5.7 dit :

Le mode strict affecte si le serveur autorise «0000-00-00» comme date valide: Si le mode strict n'est pas activé, «0000-00-00» est autorisé et les insertions ne produisent aucun avertissement. Si le mode strict est activé, «0000-00-00» n'est pas autorisé et les insertions produisent une erreur, sauf si IGNORE est également indiqué. Pour INSERT IGNORE et UPDATE IGNORE, «0000-00-00» est autorisé et les insertions produisent un avertissement.

Pour vérifier le mode MYSQL

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

Désactivation du mode STRICT_TRANS_TABLES

Cependant pour autoriser le format 0000-00-00 00:00:00vous devez désactiver le mode STRICT_TRANS_TABLES dans le fichier de configuration mysql ou par commande

Par commande

SET sql_mode = '';

ou

SET GLOBAL sql_mode = '';

L'utilisation du mot-clé GLOBALnécessite des précisions et affecte les opérations auxquelles tous les clients se connectent à partir de ce moment

si ci-dessus ne fonctionne pas, allez à /etc/mysql/my.cnf(selon ubuntu) et commentezSTRICT_TRANS_TABLES

En outre, si vous voulez régler définitivement le mode sql au démarrage du serveur puis inclure SET sql_mode=''dans my.cnfsous Linux ou MacOS. Pour Windows, cela doit être fait dans un my.inifichier.

Remarque

Cependant, le mode strict n'est pas activé par défaut dans MYSQL 5.6. Par conséquent, il ne produit pas l'erreur selon la documentation MYSQL 6 qui dit

MySQL vous permet de stocker une valeur «zéro» de «0000-00-00» en tant que «date factice». C'est dans certains cas plus pratique que d'utiliser des valeurs NULL et utilise moins de données et d'espace d'index. Pour interdire «0000-00-00», activez le mode SQL NO_ZERO_DATE.

METTRE À JOUR

En ce qui concerne le problème du bug, comme l'a dit @ Dylan-Su:

Je ne pense pas que ce soit le bogue de la façon dont MYSQL a évolué au fil du temps, en raison duquel certaines choses sont modifiées en fonction de l'amélioration du produit.

Cependant, j'ai un autre rapport de bogue concernant la NOW()fonction

Le champ Datetime n'accepte pas la valeur par défaut NOW ()

Une autre note utile [voir Initialisation et mise à jour automatiques pour TIMESTAMP et DATETIME ]

Depuis MySQL 5.6.5, les colonnes TIMESTAMP et DATETIME peuvent être automatiquement initialisées et mises à jour à la date et à l'heure actuelles (c'est-à-dire l'horodatage actuel). Avant la version 5.6.5, cela n'est vrai que pour TIMESTAMP et pour au plus une colonne TIMESTAMP par table. Les notes suivantes décrivent d'abord l'initialisation et la mise à jour automatiques pour MySQL 5.6.5 et versions ultérieures, puis les différences pour les versions antérieures à la 5.6.5.

Mise à jour concernant NO_ZERO_DATE

Depuis MySQL à partir de la version 5.7.4, ce mode est obsolète. Pour la version précédente, vous devez commenter la ligne respective dans le fichier de configuration. Reportez-vous à la documentation MySQL 5.7 le NO_ZERO_DATE

geeksal
la source
5
UPDATE IGNORE est ce que je cherchais 👍🏻
Afanasii
2
Faux. J'ai STRICT_TRANS_TABLESpour mes deux instances MySQL, locales et serveur. Cependant, je peux facilement insérer 0000-00-00dans mon instance locale, mais pas dans mon instance de serveur - une erreur est générée. Pourquoi? Parce que la configuration de mon serveur MySQL a été NO_ZERO_DATEactivée. Et mon local ne l'a pas.
Vert
ok @Green je vais comprendre et mettre à jour la réponse le cas échéant
geeksal
4
Dans mon cas, 'SET sql_mode = ""' ne fonctionnait pas. 'SET GLOBAL sql_mode = "";' fait le travail pour moi.
arjen Stens
NO_ZERO_DATE
Devrait
18

J'ai eu cette erreur avec WAMP 3.0.6 avec MySql 5.7.14.

Solution :

changer la ligne 70 (si votre fichier ini n'est pas touché) dans le c:\wamp\bin\mysql\mysql5.7.14\my.inifichier de

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

à

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

et redémarrez tous les services.

Cela désactivera le mode strict. Selon la documentation, «mode strict» signifie un mode avec l'un ou les deux STRICT_TRANS_TABLESou STRICT_ALL_TABLESactivé. La documentation dit:

"Le mode SQL par défaut de MySQL 5.7 inclut les modes suivants: ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER et NO_ENGINE_SUBSTITUTION."

bg17aw
la source
14

Je me suis retrouvé dans une situation où les données étaient mélangées entre NULL et 0000-00-00 pour un champ de date. Mais je ne savais pas comment mettre à jour le '0000-00-00' en NULL, car

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

n'est plus autorisé. Ma solution de contournement était assez simple:

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

car toutes les my_date_fieldvaleurs incorrectes (que les dates soient correctes ou non) étaient antérieures à cette date.

Martin T.
la source
2
Solution rapide parfaite. Vous pourriez en fait également l'utiliser <'0000-01-01'puisqu'il s'agit bien sûr d'une date valide.
Ricky McMaster
5

Problème de syntaxe de configuration

Sur certaines versions de MYSQL (testé 5.7. *) Sous les systèmes * nix, vous devez utiliser cette syntaxe:

[mysqld]

sql-mode="NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLE,NO_ENGINE_SUBSTITUTION"

Cela ne fonctionnera pas:

tiret sans guillemets

sql-mode=NO_ENGINE_SUBSTITUTION

soulignement sans guillemets

sql_mode=NO_ENGINE_SUBSTITUTION

soulignement et citations

sql_mode="NO_ENGINE_SUBSTITUTION"

Un examen plus complet des valeurs de configuration et du mode sql:

Comment configurer des indicateurs de mode SQL permanents

Heroselohim
la source
5

Sélectionnez d'abord la session en cours sql_mode:

SELECT @@SESSION.sql_mode;

Ensuite, vous obtiendrez quelque chose comme cette valeur par défaut :

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

puis définissez sql_modesans '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';

Si vous avez des subventions, vous pouvez le faire aussi pour GLOBAL:

SELECT @@GLOBAL.sql_mode;
SET GLOBAL sql_mode = '...';
simhumileco
la source
4

Ajoutez simplement la ligne: sql_mode = "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

fichier intérieur: /etc/mysql/mysql.conf.d/mysqld.cnf

puis sudo service mysql restart

ferreidon aftahi
la source
1
Fonctionne pour 5.7.23.
user2513149
1
Je suggérerais probablement d' SELECT @@SESSION.sql_mode;abord, et leur supprimer NO_ZERO_IN_DATE, NO_ZERO_DATE et STRICT_TRANS_TABLES de ce qu'il vous donne. De cette façon, vous conservez tous les autres paramètres que vous avez activés. J'avais beaucoup plus que ces deux éléments définis pour mon mode SQL. Je ne sais pas ce qu'ils font tous, mais je ne veux pas risquer de les supprimer à ce stade.
Radley Sustaire
2

Cela fonctionne pour 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)

Vous pouvez créer un SQLFiddle pour recréer votre problème.

http://sqlfiddle.com/

Si cela fonctionne pour MySQL 5.6 et 5.7.8, mais échoue sur 5.7.11. Ensuite, il s'agit probablement d'un bogue de régression pour 5.7.11.

Dylan Su
la source
1

Pour résoudre le problème avec MySQL Workbench (après avoir appliqué la solution côté serveur):

Supprimez SQL_MODE en TRADITIONAL dans le panneau des préférences.

entrez la description de l'image ici

Vindic
la source
1

Cette réponse est juste pour MySQL 5.7:

Best n'est pas vraiment mis en blanc le sql_mode, utilisez plutôt en PHP une variable de session avec:

SET SESSION sql_mode= 'ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'

Donc au moins vous gardez les autres valeurs par défaut.

C'est fou que la documentation mysql ne soit pas claire, vous devez supprimer ces valeurs par défaut dans sql_mode:

NO_ZERO_IN_DATE, NO_ZERO_DATE, je comprends, mais dans les versions futures, cela sera abandonné.

STRICT_ALL_TABLES, avec ceci, avant que les paramètres ne soient ignorés, vous devez donc le supprimer également.

Enfin TRADITIONNEL aussi, mais la documentation parle de ce paramètre: "donner une erreur au lieu d'un avertissement" lors de l'insertion d'une valeur incorrecte dans une colonne ", avec ce paramètre, les dates avec des valeurs nulles ne sont pas insérées, mais sans oui.

MySQL n'est pas vraiment organisé avec ces paramètres et ces combinaisons.

stackdave
la source
0

Combinaisons d'options pour mysql Ver 14.14 Distrib 5.7.18, for Linux (x86_64) .

Ne lance pas:

STRICT_TRANS_TABLES + NO_ZERO_DATE

Jette:

STRICT_TRANS_TABLES + NO_ZERO_IN_DATE

Mes paramètres /etc/mysql/my.cnfsur Ubuntu:

[mysqld]
sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
vert
la source
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
la source
0

Dans le répertoire xamp / mysql / bin Ouvrez "my.ini" et changez la ligne: Sql_node for ->

"sql_mode = NO_ENGINE_SUBSTITUTION, NO_ZERO_DATE"

SUPPRIMER "NO_ZERO_IN_DATE"

leandro ramos
la source
Bienvenue dans stackoverflow, veuillez utiliser un formatage de code approprié pour améliorer la lisibilité de la réponse.
vlizana le