Mieszkam i pracuję w pobliżu placówki Microsoft. W związku z tym wielu naszych obecnych pracowników to byli pracownicy firmy Microsoft, którzy wywodzą się z SQL Server. SQL Server umożliwia tworzenie tabeli z kolumną IDENTITY. Oracle 12c pozwala teraz zrobić to samo. Powinno to pomóc tym, którzy przechodzą z SQL Server na Oracle. Pozwala także firmie łatwiej przenieść aplikację z SQL Server lub dowolnej innej bazy danych, która pozwala na kolumnę IDENTITY, do Oracle.
Najpierw stworzę tabelę z kolumną IDENTITY i wypełnię ją kilkoma wierszami danych.
SQL> create table test_tab ( 2 id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY, 3 val VARCHAR2(20)); Table created. SQL> insert into test_tab (val) values ('my first row'); 1 row created. SQL> insert into test_tab (val) values ('my second row'); 1 row created. SQL> commit; Commit complete.
Zauważ, że nie wstawiłem żadnych wartości do kolumny ID. Teraz przeprowadźmy zapytanie do tabeli.
SQL> select * from test_tab; ID VAL ---------- -------------------- 1 my first row 2 my second row
Jak widać, moje wartości ID zostały dodane zgodnie z oczekiwaniami. Podczas tworzenia tabeli zdefiniowałem tę kolumnę IDENTITY za pomocą: GENERATED BY DEFAULT ON NULL
Klauzula BY DEFAULT oznacza, że Oracle automatycznie przypisze następną wartość w sekwencji, jeśli pominiesz ją w instrukcji INSERT. Jeśli ją uwzględnisz, Oracle użyje określonej przez Ciebie wartości. Rozważ to:
SQL> insert into test_tab values (4,'specified ID=4'); 1 row created. SQL> commit; Commit complete. SQL> select * from test_tab; ID VAL ---------- -------------------- 1 my first row 2 my second row 4 specified ID=4
Jak widać, ponieważ wyraźnie określiłem ID=4 i Oracle przepuściło tę wartość. Co się stanie, gdy spróbuję wstawić następną wartość, która powinna wynosić 3?
SQL> insert into test_tab (val) values ('my row after ID=4'); 1 row created. SQL> commit; Commit complete. SQL> select * from test_tab; ID VAL ---------- -------------------- 1 my first row 2 my second row 4 specified ID=4 3 my row after ID=4Powyższe zadziałało zgodnie z oczekiwaniami. Użyto następnej dostępnej wartości identyfikatora. Ale czy następne wstawienie użyje „4” czy „5”?
SQL> insert into test_tab (val) values ('my fifth row'); 1 row created. SQL> commit; Commit complete. SQL> select * from test_tab; ID VAL ---------- -------------------- 1 my first row 2 my second row 4 specified ID=4 3 my row after ID=4 4 my fifth rowO o! Zduplikowana wartość była dozwolona. Spodziewałem się, że zostanie utworzone ograniczenie klucza podstawowego, aby wymusić koncepcję wartości „tożsamości”, ale tak się nie dzieje. Jakie ograniczenia istnieją?
SQL> select constraint_name,constraint_type,table_name,search_condition from user_constraints; CONSTRAINT_NAME C TABLE_NAME ------------------------------ - ------------------------------ SEARCH_CONDITION -------------------------------------------------------------------------------- SYS_C004978 C TEST_TAB "ID" IS NOT NULLTak więc jedynym ograniczeniem jest ograniczenie sprawdzające NOT NULL. Teraz usuńmy ten ostatni wiersz i dodajmy ograniczenie PK.
SQL> delete from test_tab where val='my fifth row'; 1 row deleted. SQL> commit; Commit complete. SQL> alter table test_tab add constraint test_tab_pk primary key (id); Table altered.Teraz upewnię się, że mam trochę danych do przetestowania.
SQL> insert into test_tab (val) values ('after pk constraint'); 1 row created. SQL> insert into test_tab (id,val) values (6,'explicitly set id=6'); 1 row created. SQL> commit; Commit complete. SQL> select * from test_tab; ID VAL ---------- -------------------- 1 my first row 2 my second row 4 specified ID=4 3 my row after ID=4 5 after pk constraint 6 explicitly set id=6 6 rows selected.Więc wyraźnie dodałem ID=6. Jeśli tak jest, gdy jawnie dodałem ID=4, moja następna wstawka spróbuje użyć ID=6, a przy ograniczeniu PK zostanie zgłoszony wyjątek.
SQL> insert into test_tab (val) values ('after ID=6'); insert into test_tab (val) values ('after ID=6') * ERROR at line 1: ORA-00001: unique constraint (PEASLAND.TEST_TAB_PK) violatedMorał tej historii jest taki, że jeśli użyjesz opcji ON DEFAULT, bądź przygotowany na radzenie sobie z kolizją wartości tożsamości. Wartość domyślna to ZAWSZE zamiast WŁĄCZONE DOMYŚLNIE. W przypadku opcji ALWAYS Oracle zawsze będzie używać generatora numerów sekwencyjnych. Jeśli spróbujesz określić wartość identyfikatora, wystąpi wyjątek.
SQL> create table test_tab2(id number generated always as identity, val varchar2(20)); Table created. SQL> insert into test_tab2(id,val) values (1,'first row'); insert into test_tab2(id,val) values (1,'first row') * ERROR at line 1: ORA-32795: cannot insert into a generated always identity columnWidok *_TAB_COLUMNS może pokazać, które kolumny w tabeli są kolumnami IDENTITY.
SQL> select column_name,identity_column from user_tab_columns where table_name='TEST_TAB'; COLUMN_NAME IDE --------------- --- ID YES VAL NOJeśli używasz kolumny IDENTITY w tabelach, pamiętaj o przeprowadzeniu testów, aby upewnić się, że rozumiesz, że działa ona poprawnie w Twojej aplikacji. Byłem zaskoczony, że ograniczenie PK lub UNIQUE nie zostało automatycznie uwzględnione, co pozwoliło mi dodać zduplikowaną wartość.