web-dev-qa-db-fra.com

Comment forcer MySQL à prendre 0 comme valeur d'auto-incrémentation valide

Pour faire court, j'ai un fichier SQL que je veux importer en tant que fichier de style skel, donc cela se fera à plusieurs reprises, par programme. Je peux modifier le fichier SQL comme je le souhaite, mais je préfère ne pas toucher l'application elle-même.

Cette application utilise userid = 0 pour représenter l'utilisateur anonyme. Il a également une entrée pertinente (vide) dans la base de données pour représenter cet "utilisateur". Par conséquent, la ligne dans mon skel.sql ressemble à ceci:

INSERT INTO `{{TABLE_PREFIX}}users` VALUES (0, '', '', '', 0, 0, 0, '', '', 0, 0, 0, 0, 0, NULL, '', '', '', NULL);

Le problème est que uid est un auto_increment champ, pour lequel, techniquement, 0 est une valeur non valide. Ou du moins, si vous le définissez sur 0, vous dites essentiellement à MySQL: "Veuillez insérer l'ID suivant dans ce champ."

Maintenant, je suppose que je pourrais mettre une INSERT puis une requête UPDATE dans mon fichier SQL, mais existe-t-il un moyen de dire à MySQL en général que oui, je veux réellement insérer 0 dans ce domaine?

72
Matthew Scharley

D'après la réponse que j'ai obtenue ici :

Vous pouvez utiliser:

SET [GLOBAL|SESSION] sql_mode='NO_AUTO_VALUE_ON_ZERO'

Ce qui, comme décrit ici , empêchera MySQL d'interpréter un ID INSERT/UPDATE de 0 comme étant le prochain ID de séquence. Un tel comportement sera limité à NULL.

C'est ce que je considérerais comme un comportement assez mauvais de l'application. Vous devrez faire très attention à ce qu'il soit utilisé de manière cohérente, surtout si vous choisissez d'implémenter la réplication à une date ultérieure.

89
Matthew Scharley

Vérifiez votre mode sql DB avec:

SELECT @@[GLOBAL|SESSION].sql_mode;

S'il est vide ou non défini, utilisez:

SET [GLOBAL|SESSION] sql_mode='NO_AUTO_VALUE_ON_ZERO'

FAITES ATTENTION! Si vous utilisez GLOBAL, ce n'est pas un changement immédiat, vous devez redémarrer votre connexion pour appliquer le paramètre.

Ainsi, si vous restaurez des données d'une base de données à une autre, par exemple, et que vous n'êtes pas sûr si ce paramètre est appliqué, utilisez SESSION pour un changement immédiat (il se réinitialise à la fermeture de la connexion). Une fois terminé, insérez la valeur 0 et elle ne changera pas même si le sql_mode est changé.

Pour réinitialiser ce mode (et d'autres), utilisez

SET [GLOBAL|SESSION] sql_mode=''

Les valeurs zéro auto-incrémentées ne sont pas recommandées car elles ne sont pas définies par défaut dans les bases de données MySQL.

Pour plus d'informations, vérifiez sujet de la page de développement mysql sur ce

Mise à jour

Pour MariaDB, utilisez la commande indiquée dans ce commentaire

SET sql_mode='NO_AUTO_VALUE_ON_ZERO'
26
I.G. Pascual

Si vous ne voulez pas traiter les variables mysql, voici un hack utile:

INSERT INTO `{{TABLE_PREFIX}}users` VALUES (-1, '', '', '', 0, 0, 0, '', '', 0, 0, 0, 0, 0, NULL, '', '', '', NULL);

Et alors

UPDATE `{{TABLE_PREFIX}}users` SET id = 0 where id = -1;

Évidemment, cela suppose que vous utilisez un entier signé et que vous n'utilisez pas de valeurs négatives pour vos identifiants de table.

11
e18r

Manière sûre:

SET @@session.sql_mode = 
    CASE WHEN @@session.sql_mode NOT LIKE '%NO_AUTO_VALUE_ON_ZERO%' 
        THEN CASE WHEN LENGTH(@@session.sql_mode)>0
            THEN CONCAT_WS(',',@@session.sql_mode,'NO_AUTO_VALUE_ON_ZERO')  -- added, wasn't empty
            ELSE 'NO_AUTO_VALUE_ON_ZERO'                                    -- replaced, was empty
        END
        ELSE @@session.sql_mode                                             -- unchanged, already had NO_AUTO_VALUE_ON_ZERO set
    END
  • Vérifie si NO_AUTO_VALUE_ON_ZERO est déjà défini dans sql_mode
  • Ajoute à sql_mode s'il n'est pas vide
  • Définit uniquement la session, je recommande de l'utiliser uniquement sur les sessions où vous devez insérer un 0
6
Stefan Rogin