sql >> Database teknologi >  >> RDS >> Oracle

12c IDENTITY kolonner

Jeg bor og arbejder tæt på en Microsoft-facilitet. Som sådan er mange af vores nuværende medarbejdere tidligere Microsoft-medarbejdere, der kommer fra en SQL Server-baggrund. SQL Server lader dig oprette en tabel med en IDENTITY-kolonne. Oracle 12c lader dig nu gøre det samme. Dette skulle hjælpe dem, der er ved at lave overgangen fra SQL Server til Oracle. Det gør det også lettere for en virksomhed at overføre en applikation fra SQL Server eller enhver anden database, der tillader kolonnen IDENTITY, til Oracle.

Først vil jeg oprette en tabel med IDENTITET-kolonnen og udfylde den med nogle rækker af 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.
 

Bemærk, at jeg ikke har indsat nogen værdier i ID-kolonnen. Lad os nu forespørge i tabellen.

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

Som du kan se, er mine ID-værdier tilføjet, som du kunne forvente. I min tabeloprettelse definerede jeg denne IDENTITET-kolonne med:    GENERERET AF DEFAULT PÅ NULL

BY DEFAULT-sætningen betyder, at Oracle automatisk vil tildele den næste værdi i sekvensen, hvis du udelader den i din INSERT-sætning. Hvis du inkluderer det, vil Oracle bruge din angivne værdi. Overvej dette:

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, fordi jeg udtrykkeligt sagde ID=4 og Oracle lod den værdi passere. Hvad sker der, når jeg forsøger at indsætte den næste værdi, som skal være 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
Ovenstående fungerede som jeg havde forventet. Den næste tilgængelige ID-værdi blev brugt. Men vil den næste indsættelse bruge '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
Åh åh! Duplikatværdien blev tilladt. Jeg ville have forventet, at der blev skabt en Primær Nøgle-begrænsning for at håndhæve konceptet om en "identitetsværdi", men det sker ikke. Hvilke begrænsninger findes der?
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 eneste begrænsning er en NOT NULL check begrænsning. Lad os nu fjerne den sidste række og tilføje 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 skal jeg sørge for, at jeg har nogle data at teste 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å jeg tilføjede eksplicit ID=6. Hvis dette er som da jeg eksplicit tilføjede ID=4, vil min næste indsættelse forsøge at bruge ID=6 og med PK-begrænsningen på plads, vil der blive kastet en undtagelse.
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 historien er, at hvis du bruger ON DEFAULT, skal du være forberedt på at håndtere identitetsværdikollisioner. Standard er ALTID i stedet for PÅ STANDARD. Med ALTID vil Oracle altid bruge sekvensnummergeneratoren. Hvis du forsøger at angive en id-værdi, vil der forekomme en undtagelse.
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
Visningen *_TAB_COLUMNS kan vise dig, hvilke kolonner i en tabel der er IDENTITY-kolonner.
SQL> select column_name,identity_column from user_tab_columns where table_name='TEST_TAB';
COLUMN_NAME     IDE
--------------- ---
ID              YES
VAL             NO
Hvis du bruger IDENTITET-kolonnen i dine tabeller, skal du være omhyggelig med at teste for at sikre, at du forstår, at den fungerer korrekt til din applikation. Jeg var overrasket over, at en PK eller UNIQUE begrænsning ikke automatisk blev inkluderet, hvilket tillod mig at tilføje en dubletværdi.
  1. Eksempler på konvertering af 'tid' til 'datetime' i SQL Server (T-SQL)

  2. Oracle SQL:Forstår du adfærden af ​​SYS_GUID(), når den er til stede i en inline-visning?

  3. Hvordan får man det sidste indsatte id?

  4. Hvordan Random() virker i PostgreSQL