Oracle
 sql >> Base de données >  >> RDS >> Oracle

12c Colonnes IDENTITÉ

Je vis et travaille à proximité d'un site Microsoft. Ainsi, bon nombre de nos employés actuels sont d'anciens employés de Microsoft issus d'une formation SQL Server. SQL Server vous permet de créer une table avec une colonne IDENTITY. Oracle 12c vous permet désormais de faire de même. Cela devrait aider ceux qui effectuent la transition de SQL Server vers Oracle. Cela permet également à une entreprise de transférer plus facilement une application de SQL Server, ou de toute autre base de données qui autorise la colonne IDENTITY, vers Oracle.

Je vais d'abord créer une table avec la colonne IDENTITY et la remplir avec quelques lignes de données.

SQL> créer une 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 ligne created.SQL> insert into test_tab (val) values ​​('my second row'); 1 ligne created.SQL> commit;Commit complete.
 

Notez que je n'ai inséré aucune valeur dans la colonne ID. Interrogeons maintenant la table.

SQL> select * from test_tab;ID VAL---------- --------------------1 ma première ligne2 ma deuxième ligne 
 

Comme vous pouvez le voir, mes valeurs d'identification ont été ajoutées comme vous pouvez vous y attendre. Lors de la création de ma table, j'ai défini cette colonne IDENTITY avec :    GENERATED BY DEFAULT ON NULL

La clause BY DEFAULT signifie qu'Oracle affectera automatiquement la valeur suivante dans la séquence si vous l'omettez dans votre instruction INSERT. Si vous l'incluez, Oracle utilisera la valeur que vous avez spécifiée. Considérez ceci :

SQL> insérez dans les valeurs de test_tab (4,'identifié spécifié=4');1 ligne créée.SQL> commit;Commit complete.SQL> select * from test_tab; ID VAL---------- --------------------         1 ma première ligne         2 ma deuxième ligne         4 ID spécifié=4
 

Comme vous pouvez le voir, parce que j'ai explicitement indiqué ID =4 et Oracle a laissé passer cette valeur. Que se passe-t-il lorsque j'essaie d'insérer la valeur suivante, qui devrait être 3 ?

SQL> insérez dans les valeurs test_tab (val) ('my row after ID=4');1 ligne créée.SQL> commit;Commit complete.SQL> select * from test_tab; ID VAL---------- --------------------         1 ma première ligne         2 ma deuxième ligne         4 ID spécifié=4         3 ma ligne après ID =4
Ce qui précède a fonctionné comme je m'y attendais. La prochaine valeur d'ID disponible a été utilisée. Mais la prochaine insertion utilisera-t-elle '4' ou '5' ?
SQL>  insert into test_tab (val) values ​​("ma cinquième ligne") ; 1 ligne créée.SQL> commit;Commit complete.SQL> select * from test_tab ; ID VAL---------- --------------------         1 ma première ligne         2 ma deuxième ligne         4 ID spécifié=4         3 ma ligne après ID =4         4 ma cinquième rangée
Oh-oh ! La valeur en double était autorisée. Je me serais attendu à ce qu'une contrainte de clé primaire soit créée pour appliquer le concept de valeur "d'identité", mais cela ne se produit pas. Quelles contraintes existent ?
SQL> sélectionnez nom_contrainte,type_contrainte,nom_table,condition_recherche dans contraintes_utilisateur ;CONSTRAINT_NAME                C TABLE_NAME--------------------------- --- - ------------------------------SEARCH_CONDITION--------------- -------------------------------------------------- ---------------SYS_C004978                    C TEST_TAB"ID" N'EST PAS NULL
La seule contrainte est donc une contrainte de vérification NOT NULL. Supprimons maintenant cette dernière ligne et ajoutons une contrainte PK.
SQL> delete from test_tab where val='my cinquième ligne';1 ligne supprimée.SQL> commit;Commit complete.SQL> alter table test_tab add restrict test_tab_pk primary key (id);Table modifiée.
Maintenant, je vais m'assurer d'avoir des données à tester.
SQL> insérer dans les valeurs test_tab (val) ('après la contrainte pk'); 1 ligne créée.SQL> insérer dans les valeurs test_tab (id, val) ( 6,'explicitly set id=6');1 ligne créée.SQL> commit;Commit complete.SQL> select * from test_tab; ID VAL---------- --------------------         1 ma première ligne         2 ma deuxième ligne         4 ID spécifié=4         3 ma ligne après ID =4         5 après la contrainte pk        6 id défini explicitement =66 lignes sélectionnées.
J'ai donc explicitement ajouté ID=6. Si c'est comme lorsque j'ai ajouté explicitement ID=4, ma prochaine insertion tentera d'utiliser ID=6 et avec la contrainte PK en place, une exception sera levée.
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 :contrainte unique (PEASLAND.TEST_TAB_PK) violée
Donc, la morale de l'histoire est que si vous utilisez ON DEFAULT, soyez prêt à gérer les collisions de valeurs d'identité. La valeur par défaut est TOUJOURS au lieu de ON DEFAULT. Avec ALWAYS, Oracle utilisera toujours le générateur de numéros de séquence. Si vous essayez de spécifier une valeur d'identifiant, une exception se produira.
SQL> créer une table test_tab2(numéro d'identifiant généré toujours comme identité, val varchar2(20));Table créée.SQL> insérer dans test_tab2(id,val) values ​​(1,'first row');insert into test_tab2(id,val) values ​​(1,'first row')                      *ERREUR à la ligne 1 :ORA-32795 :impossible d'insérer dans une colonne d'identité toujours générée
La vue *_TAB_COLUMNS peut vous montrer quelles colonnes d'une table sont des colonnes IDENTITY.
SQL> select column_name,identity_column from user_tab_columns where table_name='TEST_TAB';COLUMN_NAME     IDE-------------- - ---ID              OUIVAL             NON
Si vous utilisez la colonne IDENTITY dans vos tables, veillez à tester pour vous assurer que vous comprenez qu'elle fonctionne correctement pour votre application. J'ai été surpris qu'une contrainte PK ou UNIQUE ne soit pas automatiquement incluse, ce qui m'a permis d'ajouter une valeur en double.