J'ai récemment repris un ancien projet qui a été créé il y a 10 ans. Il utilise MySQL 5.1.
Entre autres choses, je dois changer le jeu de caractères par défaut de latin1 à utf8.
À titre d'exemple, j'ai des tableaux comme celui-ci:
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
J'ai configuré mon propre Mac pour y travailler. Sans trop y penser, j'ai lancé "brew install mysql" qui a installé MySQL 5.7. J'ai donc des conflits de version.
J'ai téléchargé une copie de cette base de données et je l'ai importée.
Si j'essaye d'exécuter une requête comme celle-ci:
ALTER TABLE users MODIFY first_name varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
J'obtiens cette erreur:
ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'created' at row 1
J'ai pensé que je pourrais résoudre ce problème avec:
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
mais j'obtiens:
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
Dois-je mettre à jour chaque valeur?
Je n'ai pas pu faire ça:
(sur MySQL 5.7.13).
J'ai continué à recevoir l'
Incorrect datetime value: '0000-00-00 00:00:00'
erreur.Étrangement, cela a fonctionné:
SELECT * FROM users WHERE created = '0000-00-00 00:00:00'
. Je ne sais pas pourquoi le premier échoue et le second fonctionne ... peut-être un bogue MySQL?Dans tous les cas, cette requête UPDATE a fonctionné:
la source
UPDATE users SET created = NULL WHERE created = '0'
entity
WHERE createdAt = "0000-00-00 00:00:00" fonctionne bien, mais avec un échec mis à jour! J'ai eu le même problème. Corrigez-le avec la solution de @obe CAST (créé AS CHAR (20)) ... Je pense que c'est un bug.UPDATE users SET created = NULL WHERE created=0
(sans 'autour de zéro)Modification de la valeur par défaut d'une colonne avec une
ALTER TABLE
instruction, par ex.... ne modifie aucune valeur déjà stockée. La valeur "par défaut" s'applique aux lignes insérées et pour lesquelles aucune valeur n'est fournie pour la colonne.
Quant à savoir pourquoi vous rencontrez l'erreur, il est probable que le
sql_mode
paramètre de votre session inclutNO_ZERO_DATE
.Référence: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_date
Lorsque vous avez effectué l '"importation", les instructions SQL qui ont effectué l'INSERT dans cette table ont été exécutées dans une session qui n'autorisait aucune date.
Pour voir le paramètre sql_mode:
-ou-
En ce qui concerne la façon de «résoudre» le problème actuel, afin que l'erreur ne soit pas générée lorsque vous exécutez l'
ALTER TABLE
instruction.Plusieurs options:
1) modifiez le
sql_mode
pour autoriser zéro date, en supprimantNO_ZERO_DATE
etNO_ZERO_IN_DATE
. La modification peut être appliquée dans le fichier my.cnf, donc après un redémarrage de MySQL Server, lasql_mode
variable sera initialisée avec le paramètre dans my.cnf.Pour un changement temporaire, nous pouvons modifier le paramètre en une seule session, sans nécessiter de changement global.
2) modifiez la
created
colonne pour autoriser les valeurs NULL et mettez à jour les lignes existantes pour changer les dates zéro en valeurs nulles3) mettre à jour les lignes existantes pour changer les dates zéro en une date valide
Nous n'avons pas besoin d'exécuter des instructions individuelles pour mettre à jour chaque ligne. Nous pouvons mettre à jour toutes les lignes d'un seul coup (en supposant qu'il s'agisse d'une table de taille raisonnable. Pour une table plus grande, pour éviter une énorme génération de restauration / annulation, nous pouvons effectuer l'opération par tranches de taille raisonnable.)
Dans la question, la
AUTO_INCREMENT
valeur indiquée pour la définition de la table nous assure que le nombre de lignes n'est pas excessif.Si nous avons déjà modifié la
created
colonne pour autoriser lesNULL
valeurs, nous pouvons faire quelque chose comme ceci:Ou, nous pouvons les définir sur une date valide, par exemple le 2 janvier 1970
(Notez qu'une valeur datetime du 1er janvier 1970 à minuit (
'1970-01-01 00:00:00'
) est une "date zéro". Elle sera évaluée comme étant'0000-00-00 00:00:00'
la source
sql_mode
. Les versions plus récentes de MySQL ont des paramètres par défautsql_mode
qui sont plus stricts que les versions précédentes. Référence pour 8.0 ici: dev.mysql.com/doc/refman/8.0/en/sql-mode.html voirNO_ZERO_DATE
,ALLOW_INVALID_DATE
et al. notez que certains sont inclus dans le mode STRICT par exempleSTRICT_TRANS_TABLES
,STRICT_ALL_TABLES
et d'autres modes combinés. Pour contourner les restrictions, modifiez temporairement sql_mode pour la session,Je l'ai réparé en faisant cela avant la requête
la source
Selon le manuel de référence de MySQL 5.7 :
Puisque ce
0000-00-00 00:00:00
n'est pas uneDATETIME
valeur valide , votre base de données est cassée. C'est pourquoi MySQL 5.7 - qui est livré avec leNO_ZERO_DATE
mode activé par défaut - génère une erreur lorsque vous essayez d'effectuer une opération d'écriture.Vous pouvez corriger votre table en mettant à jour toutes les valeurs non valides en une autre valide, comme
NULL
:Aussi, pour éviter ce problème, je vous recommande de toujours définir l'heure actuelle comme valeur par défaut pour vos
created
champs similaires, afin qu'ils soient automatiquement remplisINSERT
. Faites simplement:la source
la source
Voici ce que ma solution PhpMyAdmin / Fedora 29 / MySQL 8.0 (par exemple):
set sql_mode='SOMETHING';
ne fonctionne pas , l'appel de commande a réussi mais rien n'a changé.set GLOBAL sql_mode='SOMETHING';
changer la configuration globale changement permanent.set SESSION sql_mode='SOMETHING';
modifier la configuration de session La variable SESSION affecte uniquement le client actuel.https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html
Alors je fais ceci:
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'
Vous pouvez supprimer ou ajouter un autre mode de la même manière.
Ceci est utile pour changer global pour l'utilisation et le test des frameworks ou sql_mode doit être spécifié dans chaque fichier ou groupe de requêtes.
Adapté d'une question posée ici: comment-puis-je-désactiver-mysql-strict-mode
Exemple: installez le dernier contenu Joomla 4.0-alpha.
Edit: Dans PhpMyadmin, si vous avez le contrôle du serveur, vous pouvez modifier le
sql_mode
(et tous les autres paramètres) directement dansPlus > Variables > sql_mode
la source
Vous pouvez modifier le type de créé champ à partir
datetime
devarchar(255)
, vous pouvez définir (mise à jour) tous les enregistrements qui ont la valeur"0000-00-00 00:00:00"
àNULL
.Maintenant, vous pouvez faire vos requêtes sans erreur. Une fois que vous avez terminé, vous pouvez modifier le type de champ créé en
datetime
.la source
J'ai également cette erreur après la mise à niveau de MySQL de 5.6 à 5.7
J'ai compris que la meilleure solution pour moi était de combiner certaines des solutions ici et d'en faire quelque chose qui fonctionnait avec le minimum d'entrée.
J'utilise MyPHPAdmin pour la simplicité de l'envoi des requêtes via l'interface car je peux alors vérifier la structure et tout cela facilement. Vous pouvez utiliser ssh directement ou une autre interface. La méthode doit être similaire ou identique de toute façon.
...
1.
Vérifiez d'abord l'erreur réelle lorsque vous essayez de réparer la base de données:
Cela me dit que la colonne check_out_time dans la table jos_menu doit avoir toutes les mauvaises dates corrigées ainsi que la "valeur par défaut" changée.
...
2.
J'exécute la requête SQL en fonction des informations du message d'erreur:
Si vous obtenez une erreur, vous pouvez utiliser la requête ci-dessous à la place qui semble toujours fonctionner:
...
3.
Ensuite, une fois que cela est fait, j'exécute la deuxième requête SQL:
Ou dans le cas où c'est une date qui doit être NULL
...
Si j'exécute la base de données de réparation maintenant, j'obtiens:
joomla.jos_menu OK
...
Fonctionne très bien :)
la source
Vérifier
si vous voyez des éléments "ZERO_DATE" là-dedans, essayez
Déconnectez-vous et reconnectez-vous à votre client (c'est étrange) et réessayez
la source
Rendre le mode SQL non strict
si vous utilisez laravel, allez dans config-> database, allez dans les paramètres mysql et définissez le mode strict sur false
la source
J'ai eu un problème similaire mais dans mon cas, une ligne avait la valeur NULL.
donc d'abord je mets à jour le tableau:
problème résolu, du moins dans mon cas.
la source
J'ai aussi
info d'erreur
Résoudre ce problème en changeant
0000-00-00 00:00:00
de1970-01-01 08:00:00
1970-01-01 08:00:00
L'horodatage unix est 0la source
NO_ZERO_DATE
J'ai trouvé la solution sur https://support.plesk.com/hc/en-us/articles/115000666509-How-to-change-the-SQL-mode-in-MySQL . J'avais ceci:
Remarquez les
NO_ZERO_IN_DATE,NO_ZERO_DATE
résultats ci-dessus. J'ai supprimé cela en faisant ceci:Ensuite, j'ai eu ceci:
Après cela, je pourrais utiliser
ALTER TABLE
avec succès et modifier mes tables.la source
C'est ce que j'ai fait pour résoudre mon problème. J'ai testé dans MySQL 5.7 local ubuntu 18.04.
Avant d'exécuter cette requête globalement, j'ai ajouté un fichier cnf dans le répertoire /etc/mysql/conf.d . Le nom du fichier cnf est mysql.cnf et codes
Puis je redémarre mysql
J'espère que cela peut aider quelqu'un.
la source
NO_ENGINE_SUBSTITUTION
est dans toutes les colonnes deSELECT @@global.sql_mode, @@session.sql_mode, @@sql_mode;
mais j'obtiens toujours une erreur pour la date / heure invalide0000-00-00 00:00:00
jusqu'à ce que j'exécute à nouveau la première requêteset global sql_mode="NO_ENGINE_SUBSTITUTION";
Des idées?NO_ZERO_IN_DATE,NO_ZERO_DATE
dans votre version de la ligne my.ini définissant lesql_mode
.C'est incroyablement moche, mais cela a aussi résolu le problème rapidement pour moi. Votre table a besoin d'une clé unique que vous utiliserez pour réparer les colonnes corrompues. Dans cet exemple, la clé primaire est appelée «id» et la colonne d'horodatage interrompue est appelée «BadColumn».
Sélectionnez les ID des colonnes contaminées.
select id from table where BadColumn='0000-00-00 00:00:00'
Collectez les ID dans une chaîne délimitée par des virgules. Exemple:
1, 22, 33
. J'ai utilisé un wrapper externe pour cela (un script Perl) pour les recracher rapidement.Utilisez votre liste d'identifiants pour mettre à jour les anciennes colonnes avec une date valide (1971 à 2038).
update table set BadColumn='2000-01-01 00:00:00' where id in (1, 22, 33)
la source
Ma solution
la source
Au lieu de
Utilisation
la source
Si vous entrez les données manuellement, vous pouvez envisager de supprimer les valeurs et les zéros du TIMESTAMP (6) .000000 afin qu'il devienne TIMESTAMP. Cela a bien fonctionné avec moi.
la source