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

12c colonne IDENTITÀ

Vivo e lavoro vicino a una struttura Microsoft. Pertanto, molti dei nostri attuali dipendenti sono ex dipendenti Microsoft che provengono da un background di SQL Server. SQL Server consente di creare una tabella con una colonna IDENTITY. Oracle 12c ora ti consente di fare lo stesso. Questo dovrebbe aiutare coloro che stanno effettuando la transizione da SQL Server a Oracle. Consente inoltre a un'azienda di trasferire più facilmente un'applicazione da SQL Server o qualsiasi altro database che consenta la colonna IDENTITY a Oracle.

Per prima cosa creerò una tabella con la colonna IDENTITY e la popolerò con alcune righe di dati.

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.
 

Si noti che non ho inserito alcun valore nella colonna ID. Ora interroghiamo la tabella.

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

Come puoi vedere, i miei valori ID sono stati aggiunti come potresti aspettarti. Nella mia creazione della tabella, ho definito questa colonna IDENTITY con:    GENERATED BY DEFAULT ON NULL

La clausola BY DEFAULT significa che Oracle assegnerà automaticamente il valore successivo nella sequenza se lo ometti nell'istruzione INSERT. Se lo includi, Oracle utilizzerà il valore specificato. Considera questo:

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
 

Come puoi vedere, perché ho dichiarato esplicitamente ID=4 e Oracle ha lasciato passare quel valore. Cosa succede quando provo a inserire il valore successivo, che dovrebbe essere 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
Quanto sopra ha funzionato come mi aspettavo. È stato utilizzato il successivo valore ID disponibile. Ma il prossimo inserto utilizzerà '4' o '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
Uh Oh! Il valore duplicato è stato consentito. Mi sarei aspettato che fosse creato un vincolo di chiave primaria per rafforzare il concetto di valore di "identità", ma ciò non accade. Quali vincoli esistono?
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
Quindi l'unico vincolo è un vincolo di controllo NOT NULL. Ora rimuoviamo l'ultima riga e aggiungiamo un vincolo 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.
Ora mi assicurerò di avere alcuni dati con cui testare.
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.
Quindi ho aggiunto esplicitamente ID=6. Se è come quando ho aggiunto esplicitamente ID=4, il mio prossimo inserto tenterà di usare ID=6 e con il vincolo PK in atto, verrà generata un'eccezione.
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
Quindi la morale della storia è che se usi ON DEFAULT, preparati a gestire le collisioni del valore dell'identità. L'impostazione predefinita è SEMPRE invece di PREDEFINITO. Con ALWAYS, Oracle utilizzerà sempre il generatore di numeri di sequenza. Se si tenta di specificare un valore id, si verificherà un'eccezione.
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
La vista *_TAB_COLUMNS può mostrarti quali colonne in una tabella sono colonne IDENTITY.
SQL> select column_name,identity_column from user_tab_columns where table_name='TEST_TAB';
COLUMN_NAME     IDE
--------------- ---
ID              YES
VAL             NO
Se utilizzi la colonna IDENTITY nelle tue tabelle, fai attenzione a eseguire il test per assicurarti di comprendere che funziona correttamente per la tua applicazione. Sono rimasto sorpreso dal fatto che un vincolo PK o UNIQUE non sia stato incluso automaticamente, il che mi ha permesso di aggiungere un valore duplicato.