2009-07-17 4 views
60

Krótko mówiąc, mam plik SQL, który chcę zaimportować jako plik stylu skel, więc będzie to wykonywane wielokrotnie, programowo. Mogę edytować plik SQL tak jak chcę, ale wolałbym nie dotykać samej aplikacji. Ta aplikacja używa userid = 0 do reprezentowania anonimowego użytkownika. Ma również odpowiednią (pustą) pozycję w bazie danych do reprezentowania tego "użytkownika". Stąd, linia w moim skel.sql wygląda mniej więcej tak:Jak zmusić MySQL do podjęcia 0 jako poprawnej wartości auto-inkrementacji

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

Problem polega na tym, że uid jest auto_increment pole, dla którego, technicznie 0 jest niepoprawną wartość. Lub przynajmniej, jeśli ustawisz go na 0, zasadniczo mówisz MySQL, "Proszę wstawić następny id do tego pola."

Teraz przypuszczam mogłem położyć INSERT wtedy UPDATE zapytanie do mojego pliku SQL, ale czy istnieje sposób mówienia MySQL w ogóle, że tak, faktycznie chcę wstawić 0 w tej dziedzinie?

Odpowiedz

74

Z odpowiedzi dostałem here:

można użyć:

SET [GLOBAL|SESSION] sql_mode='NO_AUTO_VALUE_ON_ZERO' 

Które opisanym here, uniemożliwi MySQL od interpretacji identyfikator INSERT/UPDATE z 0 jako kolejna sekwencja ID. Takie zachowanie będzie ograniczone do NULL.

To, co uważam za złe zachowanie z aplikacji. Musisz być naprawdę ostrożny, aby był konsekwentnie używany, szczególnie jeśli zdecydujesz się na wdrożenie replikacji w późniejszym terminie.

+12

Jedna rzecz, na którą trzeba uważać: 'sql_mode' jest rozdzielaną przecinkami listą flag. Jeśli wykonasz 'sql_mode = 'NO_AUTO_VALUE_ON_ZERO'', możesz nieumyślnie wyłączyć inne flagi – Kip

+0

To rozwiązanie w zasadzie działało dla mnie, jednak mój zrzut zawierał również miejsca, w których nadpisał' sql_mode' w środku pliku sql, a następnie resetowanie do zmiennej 'OLD_SQL_MODE', która została przywrócona na końcu skryptu. To nadpisało moje 'NO_AUTO_VALUE_ON_ZERO' w środku mojego skryptu, co nie działa. Moim rozwiązaniem było utworzenie nowej zmiennej 'INIT_OLD_SQL_MODE', której użyłem do zresetowania na końcu i po ustawieniu' sql_mode' na 'NO_AUTO_VALUE_ON_ZERO', ustawiłem nową zmienną' OLD_SQL_MODE', którą te tymczasowe przesłonięcia mogą zresetować do –

19

Sprawdź tryb DB SQL z:

SELECT @@[GLOBAL|SESSION].sql_mode; 

Jeśli jest pusta lub nie jest ustawiona, zastosowanie:

SET [GLOBAL|SESSION] sql_mode='NO_AUTO_VALUE_ON_ZERO' 

bądź ostrożny! Jeśli używasz GLOBAL, nie jest to natychmiastowa zmiana, musisz ponownie uruchomić połączenie, aby zastosować to ustawienie.

Tak więc, jeśli jesteś przywracanie danych z jednego do drugiego DB, na przykład, i nie jesteś pewien, czy to ustawienie jest stosowane, należy SESSION do natychmiastowej zmiany (resetuje podczas zamykania połączenia). Po zakończeniu wstaw wartość 0 i nie zmieni się, nawet jeśli zmieniono sql_mode.

Aby zresetować ten tryb (i inni) używają

SET [GLOBAL|SESSION] sql_mode='' 

Zero automatycznego przyrostu wartości nie są zalecane, ponieważ nie są one ustawione jako domyślne w bazach danych MySQL.

Aby uzyskać więcej informacji czeku mysql dev page topic na tej

5

Fail bezpieczny sposób:

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 
  • sprawdza czy NO_AUTO_VALUE_ON_ZERO już ustawiony w sql_mode
  • Dodaje do sql_mode jeśli nie tylko puste
  • Ustawia sesji, zalecam używanie go tylko w sesjach, w których trzeba wstawić 0
4

Jeśli nie chcesz magiel ze zmiennymi mysql, tutaj jest przydatna Hack:

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

A potem

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

Oczywiście, to zakłada się, że nie używasz wartości ujemne dla twoje identyfikatory stołowe.

+6

Oczywiście , to nie działa, jeśli używasz liczby całkowitej bez znaku. – fnkr

Powiązane problemy