Tabloda unique bir alana ihtiyaç duyduğumuz da 12c öncesinde bu sorunu sequence kullanarak çözüyorduk. 12c ile birlikte identity olarak tanımlayabileceğimiz ve otomatik olarak bu unique değeri oracle’ ın kendisinin vermesini sağlayabileceğimiz bir kolon tipi getirildi.
Öncelikle 12c öncesindeki durumu simüle edelim, sonrasında 12c versiyonunda bu işi nasıl yapabiliyoruz ona bakalım.
Öncelikle testimiz de kullanacağımız numaratörümüzü create edelim.
1 2 3 4 5 |
===> CREATE SEQUENCE kamil.testseq1 MINVALUE 1 MAXVALUE 99999999 START WITH 1 INCREMENT BY 1 Sequence created. |
Test tablomuzu create edelim;
1 2 |
===> create table kamil.testtable (id number, name varchar2(5)) Table created. |
Oluşturduğumuz sequence’ i kullanarak tablomuzu kayıt atalım;
1 2 3 4 5 6 7 8 9 10 11 12 13 |
===> INSERT INTO kamil.testtable (id, name) VALUES (kamil.testseq1.NEXTVAL, 'test1') 1 row created. ===> INSERT INTO kamil.testtable (id, name) VALUES (kamil.testseq1.NEXTVAL, 'test2') 1 row created. ===> INSERT INTO kamil.testtable (id, name) VALUES (kamil.testseq1.NEXTVAL, 'test3') 1 row created. ===> INSERT INTO kamil.testtable (id, name) VALUES (kamil.testseq1.NEXTVAL, 'test4') 1 row created. ===> INSERT INTO kamil.testtable (id, name) VALUES (kamil.testseq1.NEXTVAL, 'tes5') 1 row created. ===> commit Commit complete. |
Kayıtları select edelim;
1 2 3 4 5 6 7 8 9 10 11 |
===> select * from kamil.testtable ID NAME ---------- ------ 3 test1 4 test2 5 test3 6 test4 7 tes5 5 rows selected. |
Tablomuzdaki id alanını dışardan bir sequence’ den ürettiğimiz sayı ile doldurduğumuz dan dolayı kolon üzerinde unique liğide sağlamış oluyoruz. Bu örnek en yalın haliyle bir tablodaki bir kolunu unique bir sıra ile otomatik olarak nasıl doldurabileceğimizi anlatıyor.
12c ile ne değişti peki ona bakalım, öncelikle bu işlem için artık bir sequence oluşturmamıza gerek yok. Identity kolon içeren tablo create ederken kullanabileceğimiz 3 farklı yöntem bulunmaktadır;
GENERATED BY DEFAULT AS IDENTITY
GENERATED BY DEFAULT ON NULL AS IDENTITY
GENERATED ALWAYS AS IDENTITY
Şimdi sıra ile bu syntax lar arasındaki farklara bakalım;
• Generated by default as identity
Default olarak kullanılan şeklidir. Set edildiği kolona sıradan değer atayarak doldurur. Bunu kullanırken identity olarak create etmiş olduğunuz kolona sizde dışardan spesifik olarak değer atayabilirsiniz. Insert ederken bu kolona bir değer gödermezseniz, bu alanın değeri oracle tarafından tablo create edilirken internal olarak oluşturmuş olduğu sequence tarafından doldurulur. Test için bir tablo create edelim ;
1 2 3 |
===> create table kamil.identity1 ( id number generated by default as identity, name varchar2(5) ) Table created. |
Öncelikle id kolonunu belirtmeden data insert edelim ve id alanının otomatik olarak dolduğunu görelim;
1 2 3 4 5 6 |
===> insert into kamil.identity1 (name) values ('test1') 1 row created. ===> insert into kamil.identity1 (name) values ('test2') 1 row created. ===> commit Commit complete. |
Tablomuzu kontrol edelim ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
===> select * from kamil.identity1 ID NAME ---------- ----- 1 test1 2 test2 2 rows selected. ===> insert into kamil.identity1 values (10,'test1') 1 row created. ===> insert into kamil.identity1 values (11,'test2') 1 row created. ===> commit Commit complete. |
Tabloya bakalım tekrar;
1 2 3 4 5 6 7 8 9 10 |
===> select * from kamil.identity1 ID NAME ---------- ----- 1 test1 2 test2 10 test1 11 test2 4 rows selected. |
“generated by default as identity” ile tabloyu oluşturduğumuz da ilgili kolona biz değer atamak istiyorsak veya sistem tarafından otomatik olarak değer atanmasını istiyorsak kullanabiliriz.
Ancak generated by default as identity olarak oluşturulmuş olan kolona “NULL” olarak data insert edemezsiniz. Etmeye çalıştığımız da aşağıdaki hatayı alırız ;
===> insert into kamil.identity1 values (NULL,’test2′)
insert into kamil.identity1 values (NULL,’test2′)
Error at line 1
ORA-01400: cannot insert null into(“KAMIL”.”IDENTITY1″.”ID”)
Script Terminated on line 21.
Identity olan kolondaki değerleri sonradan da update edebilirsiniz.
1 2 |
===> update kamil.identity1 set id = 2 4 rows updated. |
• Generated by default on null as identity
Tabloya, identity kolonu üzerinde NULL değer assign etmemiz gerektiğinde ON NULL clause ile birlikte identity kolon create edebiliriz. Insert scripti içeriside NULL göndermeniz demek ID alanının da NULL olacağı anlamına gelmez, bu durumda da oracle ID alanına kaldığı yerden değer atamaya devam edecektir. Burdaki temel fark syntax olarak bu kullanıma da izin veriyor olmasıdır. Kolonun type’ ı zaten identity olduğundan dolayı zaten NULL olması beklenmemelidir.
1 2 3 |
===> create table kamil.identity2 ( id number generated by default on null as identity, name varchar2(5) ) Table created. |
Tabloya hem identity alanı boş olarak hemde null olarak data insert etmeyi deneyelim. (aşağıda her 3 durum içinde örnek insert scriptini görebilirsiniz) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
===> insert into kamil.identity2 (name) values ('test1') 1 row created. ===> insert into kamil.identity2 values (10,'test2') 1 row created. ===> insert into kamil.identity2 values (NULL,'test3') 1 row created. ===> commit Commit complete. ===> select * from kamil.identity2 ID NAME ---------- ----- 1 test1 10 test2 2 test3 3 rows selected. |
Identity olan kolondaki değerleri sonradan da update edebilirsiniz.
1 2 |
===> update kamil.identity2 set id = 2 3 rows updated. |
• Generated always as identity
Son olarak “generated always as identity” opsiyonu ile identity kolon oluşturduğumuz da, ilgili kolon user tarafından update edilemez hiçbir şekilde değiştirilemez durumda olacaktır. (adından da anlaşılacağı üzere) always as identity ile ilgili kolonun yönetimi tamamiyle oracle’ a bırakılmış demektir. Identity olarak create edilmiş olan kolonu dışardan insert veya update etmeye kalktığımızda hata alırız.
Yukarıdaki testin bir benzerini burada da yapalım ;
1 2 3 |
===> create table kamil.identity3 ( id number generated always as identity, name varchar2(5) ) Table created. |
Id kolonuna müdahale etmeden diğer kolonlara data insert edebilirsiniz.
1 2 |
===> insert into kamil.identity3 (name) values ('test1') 1 row created. |
Id kolonuna da dışardan değer girmek istediğiniz de ;
1 2 3 4 |
===> insert into kamil.identity3 values (10,'test2') insert into kamil.identity3 values (10,'test2') Error at line 1 ORA-32795: cannot insert into a generated always identity column |
Veya, identity kolonuna NULL olarak insert etmek istediğiniz de ;
1 2 3 4 |
===> insert into kamil.identity3 values (NULL,'test3') insert into kamil.identity3 values (NULL,'test3') Error at line 1 ORA-32795: cannot insert into a generated always identity column |
Hatasını alırsınız. Tabloda 1 tane başarılı insert yapabildik. Bakalım ;
1 2 3 4 5 6 |
===> select * from kamil.identity3 ID NAME ---------- ----- 1 test1 1 row selected. |
Şimdi id kolonunu update etmeye çalışırsak ;
1 2 3 4 |
===> update kamil.identity3 set id = 2 update kamil.identity3 set id = 2 Error at line 1 ORA-32796: cannot update a generated always identity column |
Yine hata aldığımızı göreceksiniz.
Bir ufak bilgi ,identity kolon tanımlarken sıra değerlerinin kaçtan başlayacağını ve bir sonraki değerin ne şekilde artmasını istiyorsanz tarifleyebilirsiniz. Örneğin ;
1 2 3 |
===> create table kamil.identity4 ( id number generated by default on null as identity start with 10 increment by 5 maxvalue 999, name varchar2(5) ) Table created. |
İdentity’ yi sağlayan yapı daha önceki versiyonlarda olduğu gibi burda da sequence, sadece burdaki sequence create etme ve yönetme işini oracle sizin yerinize yapıyor ve yönetiyor. Biraz daha detaylandıralım ;
Yukarıda kullandığımız insertlerden bir tanesinin execution planına bakalım ;
insert into kamil.identity3 (name) values (‘test1’);
Execution planında ISEQ$$_93163 adında bir squence görüyoruz. Kontrol edelim ;
1 2 3 4 5 6 7 8 |
===> col sequence_owner format A15 ===> col sequence_name format A15 ===> select sequence_owner, sequence_name from dba_sequences where sequence_name ='ISEQ$$_93163' SEQUENCE_OWNER SEQUENCE_NAME --------------- --------------- KAMIL ISEQ$$_93163 1 row selected. |
Sequenceler arasında da bunu görebiliyoruz. Sistem tarafından oluşturulmuş olan bu sequenceleri user sequence’ leri ile karıştırmamak lazım zira bunu diğerlerindeki alter edemezsiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
===> ALTER SEQUENCE KAMIL.ISEQ$$_93163 INCREMENT BY 50 MINVALUE 150 MAXVALUE 1000 CACHE 20 NOCYCLE NOORDER NOKEEP GLOBAL ALTER SEQUENCE KAMIL.ISEQ$$_93163 INCREMENT BY 50 MINVALUE 150 MAXVALUE 1000 CACHE 20 NOCYCLE NOORDER NOKEEP GLOBAL Error at line 1 ORA-32793: cannot alter a system-generated sequence |
Yine aynı şekilde sistem tarafından oluşturulmuş olan sequence’ i drop edemezsiniz ;
1 2 3 4 |
===> drop sequence ISEQ$$_93163 drop sequence ISEQ$$_93163 Error at line 1 ORA-32794: cannot drop a system-generated sequence |
Identity alanında bir değişiklik yapmak isterseniz bu değişikliği sequence’ i alter ederek değil tabloyu alter ederek yapabilirsiniz ;
1 2 |
===> alter table kamil.identity3 modify id generated always as identity (INCREMENT BY 5 maxvalue 9999) Table altered. |
Bir diğer bilgi ;
Database ‘ de kullanmış olduğunuz identity kolonları select etmek içinse aşağıdaki view’ i kullanabilirsiniz ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
col owner format A6 col table_name format a12 col column_name format a12 col generation_type format a15 col sequence_name format a14 select owner, table_name, column_name, generation_type, sequence_name from DBA_TAB_IDENTITY_COLS OWNER TABLE_NAME COLUMN_NAME GENERATION_TYPE SEQUENCE_NAME ------ ------------ ------------ --------------- -------------- KAMIL IDENTITY1 ID BY DEFAULT ISEQ$$_93159 KAMIL IDENTITY2 ID BY DEFAULT ISEQ$$_93161 KAMIL IDENTITY3 ID ALWAYS ISEQ$$_93163 KAMIL IDENTITY4 ID BY DEFAULT ISEQ$$_93165 4 rows selected. |
Tabloda aynı zamanda IDENTITY_OPTIONS kolonuda varki oda sequence’ in sistem tarafından nasıl oluşturulduğunu göstermektedir.
CDB_TAB_IDENTITY_COLS view’ i yukarıdakine ek olarak CON_ID kolonunu içerirki oda container bazında select ettiğiniz de ilgili tablonun hangi container’ da olduğunu adreslemektedir.
1 2 3 4 5 6 7 8 9 10 |
SQL> desc CDB_TAB_IDENTITY_COLS; Name Null? Type ----------------------------------------- -------- ----------------------- OWNER NOT NULL VARCHAR2(128) TABLE_NAME NOT NULL VARCHAR2(128) COLUMN_NAME NOT NULL VARCHAR2(128) GENERATION_TYPE VARCHAR2(10) SEQUENCE_NAME NOT NULL VARCHAR2(128) IDENTITY_OPTIONS VARCHAR2(298) CON_ID NUMBER |
Yukarıda identity özelliğini kullanarak tablo create ettiğiniz de, bu tablo için oluşturulmuş olan sequence’ i drop edemeyeceğinizi belirtmiştik. Burada tabloyu drop ettiğiniz de sequence’ de otomaitk olarak drop olacaktır.
1 2 |
===> drop table kamil.identity3 Table dropped. |
Sequence’ i tekrar kontrol ettiğimiz de ;
1 2 |
===> select sequence_owner, sequence_name from dba_sequences where sequence_name ='ISEQ$$_93163' no rows selected. |
Artık olmadığını göreceksiniz.
Identity kullanımını ile ilgili detayları böylelikle özetlemiş olduk.
Reference;
12C New Feature : Identity Columns (Doc ID 1618440.1)