2013-06-20 11 views
9

Używam OracleOracle: różnica między max (id) +1 i sequence.nextval

Jaka jest różnica kiedy tworzymy ID użyciu max(id)+1 i korzystania sequance.nexval, gdzie używać i kiedy?

odczuwalna:

insert into student (id,name) values (select max(id)+1 from student, 'abc'); 

i

insert into student (id,name) values (SQ_STUDENT.nextval, 'abc'); 

SQ_STUDENT.nextval kiedyś błąd, który daje rekord powielać ...

pomóż mi w tym wątpliwości

Odpowiedz

30

Dzięki podejściu select max(id) + 1, dwie sesje wstawiania jednocześnie będą se Ten sam bieżący maksymalny identyfikator z tabeli i oba wstawiają tę samą nową wartość identyfikatora. Jedynym sposobem bezpiecznego użycia jest zablokowanie stołu przed rozpoczęciem transakcji, co jest bolesne i serializuje transakcje. (I jak wskazuje Stijn, wartości można wykorzystać ponownie, jeśli najwyższy rekord zostanie usunięty). Zasadniczo nigdy nie stosuj tego podejścia. (Czasami może to być nieodparty powód, aby to zrobić, ale nie jestem pewien, czy kiedykolwiek widziałem).

Numer sequence guarantees that the two sessions will get different values, bez konieczności serializacji. Będzie działał lepiej i będzie bezpieczniejszy, łatwiejszy do kodowania i łatwiejszy w utrzymaniu.

Jedynym sposobem na uzyskanie powtarzających się błędów przy użyciu sekwencji jest zapisanie rekordów już w tabeli z identyfikatorami powyżej wartości sekwencji lub jeśli coś nadal wstawia rekordy bez użycia sekwencji. Jeśli więc masz istniejącą tabelę z ręcznie wprowadzonymi identyfikatorami, powiedz 1 do 10 i utworzyłeś sekwencję z domyślnym początkiem - z wartością 1, pierwsza wstawka używająca sekwencji spróbuje wstawić identyfikator 1 - który już istnieje . Po wypróbowaniu tego 10 razy sekwencja dałaby 11, które działałyby. Jeśli następnie używałeś podejścia max-ID do wykonania następnego wkładu, który użyłby 12, ale sekwencja nadal byłaby na 11, a także dałaby ci 12 następnym razem, gdy zadzwoniłbyś pod numer nextval.

Sekwencja i tabela nie są powiązane. Sekwencja nie jest automatycznie aktualizowana, jeśli ręcznie wstawiona wartość identyfikatora zostanie wstawiona do tabeli, więc te dwa podejścia nie mieszają się. (Między innymi, ta sama sekwencja może być używana do generowania identyfikatorów dla wielu tabel, jak wspomniano w dokumentach).

Jeśli zmieniasz podejście ręczne na podejście sekwencyjne, musisz upewnić się, że sekwencja jest tworzona z wartością początkową wyższą niż wszystkie istniejące identyfikatory w tabeli i że wszystko, co robi insert używa sekwencji tylko w przyszłości.

9

Używanie sekwencji działa, jeśli masz wielu użytkowników. Używanie max nie działa.

Jeśli wykonasz numer max(id) + 1 i zezwolisz wielu użytkownikom, wówczas wiele sesji, które działają jednocześnie, będzie regularnie wyświetlać ten sam numer max, co spowoduje wygenerowanie tego samego nowego klucza. Zakładając, że poprawnie skonfigurowałeś swoje ograniczenia, wygenerujesz błąd, z którym będziesz musiał sobie poradzić. Poradzisz sobie z tym, ponawiając próbę ponownego użycia, jeśli inne sesje blokują Cię przed próbą wykonania sesji, ale jest to dużo dodatkowego kodu dla każdej operacji INSERT.

Spowoduje to również serializację kodu.Jeśli wstawię nowy wiersz do mojej sesji i odejdę na lunch, zanim zapamiętasz commit (lub moja aplikacja kliencka ulegnie awarii, zanim będę mógł zatwierdzić), każdy inny użytkownik będzie mógł wstawić nowy wiersz, dopóki nie wrócę i nie zatwierdzę DBA zabija moją sesję, zmuszając do ponownego uruchomienia.

+0

ale trochę czasu Dlaczego otrzymuję błąd duplikat rekordu z sequence.nextval i działa kiedy uruchamiam to samo zapytanie z max (id) +1 –

+2

@PriyaPrajapati - ponieważ aktualna wartość twojej sekwencji jest niższa niż maksymalny identyfikator w tabeli. Sekwencja nie zostanie zmodyfikowana, jeśli ręcznie wstawisz wartość do tabeli. Nie powinieneś mieszać dwóch podejść - uzyskaj kolejność, aby była wyższa niż wartości w tabeli, a następnie używaj tylko sekwencji. –

+0

@Alex - Dzięki za odpowiedź, to może być powód błędu –

4

Aby dodać do innych odpowiedzi, kilka problemów.

Twój max (id) +1 składnia będzie również powiedzie się, jeśli nie istnieją żadne wiersze już tabeli, więc należy używać:

Coalesce(Max(id),0) + 1 

Nie ma nic złego w tej technice, jeśli masz tylko jeden proces, który wstawia do tabeli, jak może być w przypadku obciążenia hurtowni danych, a jeśli max (id) jest szybki (który prawdopodobnie jest).

Pozwala to również uniknąć konieczności synchronizowania wartości między tabelami i sekwencjami, na przykład w przypadku przenoszenia danych do systemu testowego.

Można rozszerzyć tę metodę do Multirow wkładkę za pomocą:

Coalesce(max(id),0) + rownum 

Spodziewam się, że może serialise równoległą wkładkę, choć.

Niektóre techniki nie działają dobrze w przypadku tych metod. Polegają one oczywiście na możliwości wydania instrukcji select, więc SQL * Loader może być wykluczony. Jednak SQL * Loader posiada wsparcie dla tej techniki w ogóle poprzez parametr sekwencji specyfikacji kolumna: http://docs.oracle.com/cd/E11882_01/server.112/e22490/ldr_field_list.htm#i1008234

+0

Albo obciążenie równoległe ... –

+1

Dodano notatkę na ten temat i rozwinięto komentarz w SQL * Loader. –

0

Zakładając MAX (ID) jest faktycznie dość szybko, czy nie byłoby możliwe:

  • Pierwszy dostać MAX (ID) +1
  • Zapraszamy zatem NEXTVAL
  • porównać te dwa i zwiększyć ciąg w przypadku NEXTVAL jest mniejsza niż MAX (ID) +1
  • Zastosowanie NEXTVAL w INSERT

W takim razie chciałbym mieć w pełni stabilne wkładki procedura i manualnych będzie również dozwolone bez martwienia się o aktualizację sekwencję

+0

Wprowadzasz luki, które tak naprawdę nie stanowią problemu; i wciąż masz okno, w którym dwie sesje wysyłają zapytanie o tę samą wartość 'max (id)', chociaż wywołania 'nextval' powinny sprawić, żeby to działało. Nie można tego zrobić w zwykłym języku SQL, a zezwolenie na mieszanie jest nadal nieuporządkowane. Innym podobnym podejściem jest próba wstawienia z 'nextval' w pętli, wyjściem, jeśli nie * otrzymasz ORA-00001, zakładając, że w kolumnie jest PK/UK. Pozwala to uniknąć konieczności szukania maksimum i wypełnia luki, które mogą być pożądane lub nie. Tylko używanie sekwencji jest łatwiejsze ... –

Powiązane problemy