Czytałem to o słowie kluczowym SQL DEFERRABLE
w Database Systems - The Complete Book .
To ostatnie [NOT DEFERRABLE] jest wartością domyślną i oznacza, że za każdym razem, gdy wykonywana jest instrukcja modyfikacji bazy danych, ograniczenie jest sprawdzane natychmiast po tym, jeśli modyfikacja mogłaby naruszyć ograniczenie klucza obcego.
Jeśli jednak zadeklarujemy ograniczenie jako ODROCZONE , przed sprawdzeniem ograniczenia mamy możliwość, aby czekało do zakończenia transakcji.
Podążamy za słowem kluczowym ODROCZONE przez POCZĄTKOWO ODROCZONE lub POCZĄTKOWO NATYCHMIASTOWE . W pierwszym przypadku sprawdzanie zostanie odroczone tuż przed zatwierdzeniem każdej transakcji. W tym drugim przypadku czek będzie dokonywany natychmiast po każdym wyciągu.
Czym się NOT DEFERRABLE
różni od DEFERRABLE INITIALLY IMMEDIATE
? W obu przypadkach wydaje się, że wszelkie ograniczenia są sprawdzane po każdym indywidualnym oświadczeniu.
DEFERRABLE
określa zamiar projektanta, że odroczenie ograniczenia jest wartościowym lub koniecznym działaniem. Nie dotyczy to zdecydowanej większości ograniczeń baz danych i oznaczania wszystkiego, coDEFERRABLE
spowodowałoby utratę tego przydatnego rozróżnienia.NOT DEFERRABLE
jest zwykle najszybszy.Oprócz innych (poprawnych) odpowiedzi, mówiąc o PostgreSQL należy stwierdzić, że:
z NIE ODROCZONY każdy wiersz jest sprawdzany w czasie wstawiania / aktualizacji
z ODROCZONYM (obecnie NATYCHMIAST ) wszystkie wiersze są sprawdzane na końcu wstawiania / aktualizacji
z ODROCZONYM (obecnie ODROCZONYM ) wszystkie wiersze są sprawdzane na koniec transakcji
Zatem nie jest poprawne stwierdzenie, że ograniczenie ODROCZALNE działa jak NIE ODROCZONE, gdy jest ustawione na NATYCHMIAST.
Opiszmy tę różnicę:
CREATE TABLE example( row integer NOT NULL, col integer NOT NULL, UNIQUE (row, col) DEFERRABLE INITIALLY IMMEDIATE ); INSERT INTO example (row, col) VALUES (1,1),(2,2),(3,3); UPDATE example SET row = row + 1, col = col + 1; SELECT * FROM example;
To poprawnie wyświetla:
Ale jeśli usuniemy instrukcję ODROCZENIE INICJALNIE NATYCHMIAST,
ADDENDUM (12 października 2017)
Takie zachowanie jest rzeczywiście udokumentowane tutaj , w sekcji „Zgodność”:
źródło
NOT DEFERRABLE
jest szybkość ( patrz tutaj , sekcja Nieodroczone ograniczenia niepowtarzalności , „Należy pamiętać, że może to być znacznie wolniejsze niż natychmiastowe sprawdzanie niepowtarzalności” ).DEFERRABLE
ograniczenia nie można się odwoływać jako do kluczy obcych w innych tabelach ( patrz tutaj , sekcja Parametry , „Kolumny, do których istnieją odwołania, muszą być kolumnami niemożliwego do odroczenia ograniczenia unikalnego lub klucza podstawowego w tabeli, do której się odwołuje” ).NOT DEFERRABLE
po prostu dlatego, że działa lepiej?NOT DEFERRABLE
2) jeśli co najmniej jeden FK odwołuje się do ograniczenia, używamyNOT DEFERRABLE
również 3) w pozostałych przypadkach używamyDEFERRABLE INITIALLY IMMEDIATE
. Może to nieznacznie zmniejszyć wydajność tych ograniczeń, ale zapewnia maksymalną zgodność z innymi używanymi przez nas DBMS (Oracle, SqlServer). PK i FK nie stanowią problemu, ponieważ nigdy nie aktualizujemy ich wartości (co moim zdaniem jest dobrym nawykiem programistycznym dla DB).Oprócz oczywistej możliwości odroczenia, różnica polega w rzeczywistości na wydajności. Gdyby nie było spadku wydajności, nie byłoby potrzeby wyboru opcji odroczenia lub nie - wszystkie ograniczenia byłyby po prostu odroczone.
Obniżenie wydajności wiąże się z optymalizacjami, które baza danych może wykonać, wiedząc, jak ograniczone są dane. Na przykład indeks utworzony w celu poparcia unikalnego ograniczenia w Oracle nie może być indeksem unikatowym, jeśli ograniczenie jest możliwe do odroczenia, ponieważ tymczasowe zezwolenie na duplikaty musi być dozwolone. Jeśli jednak ograniczenie nie jest możliwe do odroczenia, indeks może być unikalny.
źródło
Jestem bardzo spóźniony na imprezę, ale dodam, że - od grudnia 2018 r. - tylko dwie znane mi bazy danych (może być ich więcej) oferują pewien poziom implementacji tej standardowej funkcjonalności SQL :
Database NOT DEFERRABLE DEFERRABLE DEFERRABLE INITIALLY IMMEDIATE INITIALLY DEFERRED ---------- -------------- ------------------- ------------------ Oracle N/A *1 Yes (default) Yes PostgreSQL Yes (default) Yes Yes DB2 - - - SQL Server - - - MySQL - - - MariaDB - - - SAP Sybase - - - HyperSQL - - - H2 - - - Derby - - -
* 1 Mimo że Oracle 12c akceptuje
NOT DEFERRABLE
stan ograniczenia , w rzeczywistości go ignoruje i sprawia, że działa tak, jakDEFERRABLE INITIALLY IMMEDIATE
.Jak widać, Oracle nie implementuje pierwszego typu (
NOT DEFERRABLE
), dlatego programiści używający Oracle (w tym przypadku OP) mogą się pomylić i uznać pierwsze dwa typy za równoważne.Co ciekawe, Oracle i PostgreSQL mają inny domyślny typ. Może ma to wpływ na wydajność.
źródło
NOT DEFERRABLE - nie możesz zmienić sprawdzania ograniczeń, oracle sprawdza je po każdej instrukcji (tj. Bezpośrednio po instrukcji insert).
ODROCZENIE INICJALNIE NATYCHMIAST - oracle sprawdza ograniczenie po każdej instrukcji. ALE możesz to zmienić na po każdej transakcji (tj. Po zatwierdzeniu):
set constraint pk_tab1 deferred;
źródło