sql >> Databasteknik >  >> RDS >> Oracle

12c IDENTITY kolumner

Jag bor och arbetar nära en Microsoft-anläggning. Som sådan är många av våra nuvarande anställda tidigare Microsoft-anställda som kommer från en SQL Server-bakgrund. SQL Server låter dig skapa en tabell med en IDENTITY-kolumn. Oracle 12c låter dig nu göra detsamma. Detta bör hjälpa dem som gör övergången från SQL Server till Oracle. Det gör det också lättare för ett företag att porta en applikation från SQL Server, eller någon annan databas som tillåter kolumnen IDENTITY, till Oracle.

Först skapar jag en tabell med kolumnen IDENTITY och fyller i den med några rader med data.

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.
 

Lägg märke till att jag inte infogade några värden i ID-kolumnen. Låt oss nu fråga tabellen.

SQL> select * from test_tab;
ID VAL
---------- --------------------
1 my first row
2 my second row
 

Som du kan se har mina ID-värden lagts till som du kan förvänta dig. I mitt tabellskapande definierade jag den här IDENTITET-kolumnen med:    GENERERAD AV DEFAULT PÅ NULL

BY DEFAULT-satsen innebär att Oracle automatiskt tilldelar nästa värde i sekvensen om du utelämnar det i din INSERT-sats. Om du inkluderar det kommer Oracle att använda ditt angivna värde. Tänk på detta:

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
 

Som du kan se, eftersom jag uttryckligen angav ID=4 och Oracle lät det värdet passera. Vad händer när jag försöker infoga nästa värde, som ska vara 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
Ovanstående fungerade som jag förväntade mig. Nästa tillgängliga ID-värde användes. Men kommer nästa infogning att använda '4' eller '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
Hoppsan! Dubblettvärdet tillåts. Jag hade förväntat mig att en primärnyckel-begränsning skapades för att genomdriva konceptet med ett "identitetsvärde", men det händer inte. Vilka begränsningar finns?
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 NULL
Så den enda begränsningen är en NOT NULL-kontrollrestriktion. Låt oss nu ta bort den sista raden och lägga till en PK-begränsning.
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.
Nu ska jag se till att jag har lite data att testa med.
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.
Så jag lade till ID=6 uttryckligen. Om detta är som när jag uttryckligen lade till ID=4, kommer min nästa infogning att försöka använda ID=6 och med PK-begränsningen på plats kommer ett undantag att kastas.
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
Så moralen i berättelsen är om du använder ON DEFAULT, var beredd på att hantera identitetsvärdekollisioner. Standard är ALLTID istället för PÅ DEFAULT. Med ALLTID kommer Oracle alltid att använda sekvensnummergeneratorn. Om du försöker ange ett id-värde kommer ett undantag att inträffa.
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 column
Vyn *_TAB_COLUMNS kan visa dig vilka kolumner i en tabell som är IDENTITY-kolumner.
SQL> select column_name,identity_column from user_tab_columns where table_name='TEST_TAB';
COLUMN_NAME     IDE
--------------- ---
ID              YES
VAL             NO
Om du använder kolumnen IDENTITY i dina tabeller, var noga med att testa för att säkerställa att du förstår att den fungerar korrekt för din applikation. Jag blev förvånad över att en PK- eller UNIK-begränsning inte automatiskt inkluderades vilket gjorde att jag kunde lägga till ett duplikatvärde.
  1. Anropar en Oracle-procedur med en PL/SQL-insamlingstypparameter via .NET

  2. Dela upp strängen i rader Oracle SQL

  3. PostgreSQL returnerar en funktion med en anpassad datatyp

  4. Hur man tar bort en datafil från en SQL Server-databas (T-SQL)