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=4 Powyż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 row O 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) violated Morał 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ść.