So zwingen Sie MySQL, 0 als gültigen Wert für die automatische Inkrementierung zu verwenden

75

Kurz gesagt, ich habe eine SQL-Datei, die ich als Stildatei importieren möchte. skelDies wird also wiederholt programmgesteuert durchgeführt. Ich kann die SQL-Datei bearbeiten, wie ich möchte, aber ich möchte die Anwendung selbst lieber nicht berühren.

Diese Anwendung verwendet userid = 0, um den anonymen Benutzer darzustellen. Es hat auch einen relevanten (leeren) Eintrag in der Datenbank, um diesen 'Benutzer' darzustellen. Daher skel.sqlsieht die Zeile in meinem ungefähr so ​​aus:

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

Das Problem dabei ist, dass uides sich um ein auto_incrementFeld handelt, für das technisch gesehen 0ein ungültiger Wert vorliegt. Oder zumindest, wenn Sie es auf 0 setzen, sagen Sie MySQL im Grunde: "Bitte geben Sie die nächste ID in dieses Feld ein."

Nun, ich nehme an, ich könnte INSERTeine UPDATEAbfrage in meine SQL-Datei einfügen, aber gibt es eine Möglichkeit, MySQL im Allgemeinen mitzuteilen, dass ich tatsächlich 0in dieses Feld einfügen möchte ?

Matthew Scharley
quelle

Antworten:

93

Aus der Antwort, die ich hier bekam :

Sie können verwenden:

SET [GLOBAL|SESSION] sql_mode='NO_AUTO_VALUE_ON_ZERO'

Dies verhindert, wie hier beschrieben , dass MySQL eine INSERT / UPDATE-ID von 0 als nächste Sequenz-ID interpretiert. Ein solches Verhalten ist auf NULL beschränkt.

Es ist das, was ich von der Anwendung als ziemlich schlechtes Verhalten betrachten würde. Sie müssen wirklich darauf achten, dass es konsistent verwendet wird, insbesondere wenn Sie die Replikation zu einem späteren Zeitpunkt implementieren.

Matthew Scharley
quelle
17
Eine Sache, bei der Sie vorsichtig sein müssen: sql_modeEine durch Kommas getrennte Liste von Flags. Wenn Sie dies tun sql_mode='NO_AUTO_VALUE_ON_ZERO', können Sie versehentlich andere Flags deaktivieren
Kip
Diese Lösung funktionierte im Grunde genommen für mich, mein Speicherauszug enthielt jedoch auch einige Stellen, an denen er sql_modedie Mitte der SQL-Datei überschrieb und dann auf die Variable zurückgesetzt OLD_SQL_MODEwurde, auf die am Ende des Skripts zurückgesetzt werden sollte. Dies überschrieb meine NO_AUTO_VALUE_ON_ZEROin der Mitte meines Skripts, so dass dies nicht funktionierte. Meine Lösung bestand darin, eine neue Variable zu erstellen INIT_OLD_SQL_MODE, auf die ich am Ende zurückgesetzt hatte, und nachdem ich auf eingestellt hatte sql_mode, NO_AUTO_VALUE_ON_ZEROlegte ich eine neue Variable fest, auf OLD_SQL_MODEdie diese temporären Überschreibungen zurückgesetzt werden konnten
Joshua Fricke
27

Überprüfen Sie Ihren SQL-DB-Modus mit:

SELECT @@[GLOBAL|SESSION].sql_mode;

Wenn es leer oder nicht festgelegt ist, verwenden Sie:

SET [GLOBAL|SESSION] sql_mode='NO_AUTO_VALUE_ON_ZERO'

ACHTUNG! Wenn Sie verwenden GLOBAL, handelt es sich nicht um eine sofortige Änderung. Sie müssen Ihre Verbindung neu starten, um die Einstellung zu übernehmen.

Wenn Sie beispielsweise Daten von einer Datenbank in eine andere wiederherstellen und nicht sicher sind, ob diese Einstellung angewendet wird, verwenden Sie sie SESSIONfür eine sofortige Änderung (sie wird beim Schließen der Verbindung zurückgesetzt). Wenn Sie fertig sind, geben Sie den Wert 0 ein, der sich auch dann nicht ändert, wenn der Wert sql_modegeändert wird.

Um diesen Modus (und andere) zurückzusetzen, verwenden Sie

SET [GLOBAL|SESSION] sql_mode=''

Null-Auto-Inkrement-Werte werden nicht empfohlen, da sie in MySQL-Datenbanken nicht als Standard festgelegt sind.

Für weitere Informationen Check mysql dev Seite Thema auf diese

Aktualisieren

Verwenden Sie für MariaDB den in diesem Kommentar angegebenen Befehl

SET sql_mode='NO_AUTO_VALUE_ON_ZERO'
IG Pascual
quelle
Dies funktionierte nicht auf MariaDB, ich musste dies verwenden:SET sql_mode='NO_AUTO_VALUE_ON_ZERO'
hiddeneyes02
@ hiddeneyes02 Dies ist ein Beitrag aus dem Jahr 2010, danke für die Bemerkung, ich werde die Antwort aktualisieren :)
IG Pascual
Hat nicht funktioniert: SELECT @@ [GLOBAL | SESSION] .sql_mode; Hat funktioniert: SELECT @@ SESSION.sql_mode; Hat funktioniert: SELECT @@ GLOBAL.sql_mode;
Azoundria
14

Wenn Sie sich nicht mit MySQL-Variablen befassen möchten, ist hier ein nützlicher Hack:

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

Und dann

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

Dies setzt natürlich voraus, dass Sie eine vorzeichenbehaftete Ganzzahl verwenden und keine negativen Werte für Ihre Tabellen-IDs verwenden.

e18r
quelle
6
Offensichtlich funktioniert es nicht, wenn Sie eine vorzeichenlose Ganzzahl verwenden.
fnkr
7

Ausfallsicherer Weg:

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
  • Überprüft, ob NO_AUTO_VALUE_ON_ZERO bereits im sql_mode festgelegt ist
  • Wird zu sql_mode hinzugefügt, wenn es nicht leer ist
  • Legt nur die Sitzung fest. Ich empfehle, sie nur für Sitzungen zu verwenden, in denen Sie eine 0 einfügen müssen
Stefan Rogin
quelle