主键与其索引对应的关系
生活随笔
收集整理的這篇文章主要介紹了
主键与其索引对应的关系
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
今天一同事討論到,他發(fā)現(xiàn)一個表有主鍵約束,且主鍵并沒有沒disable掉,但沒有唯一索引。我第一反應(yīng)是這不可能。
1. 創(chuàng)建一張表,指定ID為主鍵(不指定主鍵名): create table t_pk_uk_idx_test (id number primary key, name varchar2(100)); 1.1 查看本表的約束狀態(tài): SELECT TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE, STATUS, DEFERRABLE,VALIDATED FROM DBA_CONSTRAINTS WHERE TABLE_NAME = 'T_PK_UK_IDX_TEST'; TABLE_NAME? ? ? ? ? ? ? ? ? ?? CONSTRAINT_NAME? ? ? ? ? ? ? ? CONSTRAINT_TYPE STATUS?? DEFERRABLE? ?? VALIDATED ------------------------------ ------------------------------ --------------- -------- -------------- ------------- T_PK_UK_IDX_TEST? ? ? ? ? ? ?? SYS_C0015447 ? ? ? ? ? ? ? ? ? ? ? ? ?P? ? ? ? ? ? ?? ENABLED? NOT DEFERRABLE VALIDATED
1.2 查看建立表的語句: SELECT DBMS_METADATA.GET_DDL('TABLE','T_PK_UK_IDX_TEST','HNYD') FROM DUAL; /* ? CREATE TABLE "HNYD"."T_PK_UK_IDX_TEST" ?? (? "ID" NUMBER, ? "NAME" VARCHAR2(100), ???PRIMARY KEY ("ID") ? USING INDEX?PCTFREE 10 INITRANS 2 MAXTRANS 255 ? STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 ? PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 ? BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ? TABLESPACE "DBADATA1"? ENABLE ?? ) SEGMENT CREATION IMMEDIATE ? PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING ? STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 ? PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 ? BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ? TABLESPACE "DBADATA1" */ 1.3 查看被建立約束的語句: SELECT DBMS_METADATA.GET_DDL('CONSTRAINT','SYS_C0015447','HNYD') FROM DUAL;
? /* ? ALTER TABLE "HNYD"."T_PK_UK_IDX_TEST" ADD PRIMARY KEY ("ID") ? USING INDEX?PCTFREE 10 INITRANS 2 MAXTRANS 255 ? STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 ? PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 ? BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ? TABLESPACE "DBADATA1"? ENABLE ? */
1.4 查看被建立索引的語句: SELECT DBMS_METADATA.GET_DDL('INDEX','SYS_C0015447','HNYD') FROM DUAL; ? /* ??CREATE UNIQUE INDEX "HNYD"."SYS_C0015447" ON "HNYD"."T_PK_UK_IDX_TEST" ("ID") ? PCTFREE 10 INITRANS 2 MAXTRANS 255 ? STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 ? PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 ? BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ? TABLESPACE "DBADATA1" ? */
如果通過create table t_pk_uk_idx_test (id number primary key, name varchar2(100)); 這種方式不指定主鍵名,在建立表時,系統(tǒng)會默認分配一個名字,并建立同名的一個唯一索引,一個主鍵約束。并沒有指定“not null" ,但主鍵約束肯定不允許ID列有空值。
如果嘗試刪除這個唯一索引會報錯: SQL> drop index? "HNYD"."SYS_C0015447" ; drop index? "HNYD"."SYS_C0015447" ? ? ? ? ? ? ? ? ?? * ERROR at line 1: ORA-02429: cannot drop index used for enforcement of unique/primary key --無法刪除用于強制唯一/主鍵的索引。
SQL> ALTER TABLE "HNYD"."T_PK_UK_IDX_TEST" disable PRIMARY KEY;
Table altered
SQL> drop index "HNYD"."SYS_C0015447" ; drop index "HNYD"."SYS_C0015447" ? ? ? ? ? ? ? ? ? * ERROR at line 1: ORA-01418: specified index does not exist
?這樣Disable后,對應(yīng)的索引也被刪除,但約束還在。
SQL> SELECT TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE, STATUS, DEFERRABLE,VALIDATED FROM DBA_CONSTRAINTS WHERE TABLE_NAME = 'T_PK_UK_IDX_TEST';
TABLE_NAME? ? ? ? ? ? ? ? ? ?? CONSTRAINT_NAME? ? ? ? ? ? ? ? CONSTRAINT_TYPE STATUS?? DEFERRABLE? ?? VALIDATED ------------------------------ ------------------------------ --------------- -------- -------------- ------------- T_PK_UK_IDX_TEST? ? ? ? ? ? ?? SYS_C0015447? ? ? ? ? ? ? ? ?? P? ? ? ? ? ? ?? DISABLED NOT DEFERRABLE NOT VALIDATED
再次enable后,索引建立起來了,但發(fā)現(xiàn)索引的OBJECT_ID前后不一樣了,說明索引的確是被刪除了。
2. 那么整個過程到底發(fā)生了什么? 做一個10046 看下 SQL> alter session set events '10046 trace name context forever, level 4';
Session altered.
SQL> create table hnyd.t_pk_uk_idx_test1 (id number primary key, name varchar2(100));
Table created.
SQL> alter session set events '10046 trace name context off';
Session altered.
SQL> select value from v$diag_info WHERE name = 'Default Trace File';
VALUE -------------------------------------------------------------------------------- /u01/app/oracle/diag/rdbms/trac/trac2/trace/trac2_ora_79986.trc
?tkprof /u01/app/oracle/diag/rdbms/trac/trac2/trace/trac2_ora_79986.trc /tmp/79986.txt --前面的數(shù)字表未行號: ? 28 PARSING IN CURSOR #140461753592416 len=79 dep=0 uid=0 oct=1 lid=0 tim=1470392199306885 hv=1413582164 ad='849bb510' sqlid='99a5? ?? 901a433an' ? 29 create table hnyd.t_pk_uk ? 30 END OF STMT
503 insert into?obj$(owner#,name,namespace,obj#,type#,ctime,mtime,stime,status,remoteowner,linkname,subname,dataobj#,flags,oid$,sp? ?? are1,spare2,spare3) values(:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18) 504 END OF STMT 505 PARSE #140461752366488:c=1000,e=648,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=0,tim=1470392199365433 506 BINDS #140461752366488: 507? Bind#0 508?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 509?? oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0 510?? kxsbbbfp=7fbfcce95600? bln=22? avl=03? flg=05 511?? value=113 512? Bind#1 513?? oacdty=01 mxl=32(17) mxlc=00 mal=00 scl=00 pre=00 514?? oacflg=10 fl2=0001 frm=01 csi=873 siz=32 off=0 515?? kxsbbbfp=850f86e6? bln=32? avl=17? flg=09 516?? value="T_PK_UK_IDX_TEST1"
con$是視圖dba_constraint的基表, 存放約束編號和約束名稱。 ?867 PARSING IN CURSOR #140461752215744 len=60 dep=1 uid=0 oct=2 lid=0 tim=1470392199379315 hv=1878790044 ad='84b4fa48' sqlid='8nhg? ?? 2pdrzs3ww' 868 insert into?con$(owner#,name,con#,spare1)values(:1,:2,:3,:4) 869 END OF STMT 870 PARSE #140461752215744:c=0,e=481,p=0,cr=0,cu=2,mis=1,r=0,dep=1,og=4,plh=0,tim=1470392199379314 871 BINDS #140461752215744: 872? Bind#0 873?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 874?? oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0 875?? kxsbbbfp=7fbfcce95600? bln=22? avl=03? flg=05 876?? value=113 877? Bind#1 878?? oacdty=01 mxl=32(12) mxlc=00 mal=00 scl=00 pre=00 879?? oacflg=10 fl2=0001 frm=01 csi=873 siz=32 off=0 880?? kxsbbbfp=852d51fe? bln=32? avl=12? flg=09 881?? value="SYS_C0015449"
?895 ===================== 896 PARSING IN CURSOR #140461752211872 len=88 dep=1 uid=0 oct=9 lid=0 tim=1470392199381070 hv=1310241531 ad='84a712c8' sqlid='7q23? ?? u0x71jcrv' 897?CREATE UNIQUE INDEX "HNYD"."SYS_C0015449" on "HNYD"."T_PK_UK_IDX_TEST1"("ID") NOPARALLEL 898 END OF STMT 這里并沒結(jié)束,后面還有很多對表、對象等基表的操作關(guān)聯(lián)等。
cdef$也dba_constraint 的基表之一; 2049 insert into?cdef$(obj#,con#,type#,intcols,condlength,condition,robj#,rcon#,match#,refact,enabled,cols,defer,mtime,spare1,spare? ?? 2,spare3)values(:1,:2,:3,decode(:4,0,null,:4),decode(:5,0,null,:5),:6,decode(:7,0,null,:7),decode(:8,0,null,:8),decode(:9,0,nu? ?? ll,:9),decode(:10,0,null,:10), decode(:11,0,null,:11),:12, decode(:13,0,null,:13),:14,:15,:16,:17) 2050 END OF STMT
到這里只能說明主鍵約束與唯一索引有一定的關(guān)系,在建立主鍵時,若這個字段上沒有索引,會嘗試在這上面建立唯一索引。
3. 假如這個字段上有索引呢。重新創(chuàng)建一個表,并創(chuàng)建一個普通的組合索引。
SQL> create table t_pk_uk_idx_test2 (id number, name varchar2(100));
Table created SQL> create index idx_id_name_normal on t_pk_uk_idx_test2(id,name);
Index created
在ID列上增加主鍵約束。 SQL> alter session set events '10046 trace name context forever, level 4';
Session altered.
SQL> alter table HNYD.t_pk_uk_idx_test2 add constraint constraint_c1 primary key(ID); alter session set events '10046 trace name context off'; Table altered.
SQL>
Session altered.
SQL> select value from v$diag_info WHERE name = 'Default Trace File';
VALUE -------------------------------------------------------------------------------- /u01/app/oracle/diag/rdbms/trac/trac2/trace/trac2_ora_85746.trc
?29 select count(FA#) from SYS_FBA_TRACKEDTABLES where OBJ# = :1 and bitand(FLAGS, :2)=0 50 LOCK TABLE "HNYD"."T_PK_UK_IDX_TEST2" IN SHARE MODE? NOWAIT 79 alter table HNYD.t_pk_uk_? ? 515 PARSING IN CURSOR #139746758027104 len=60 dep=1 uid=0 oct=2 lid=0 tim=1470394710583377 hv=1878790044 ad='84b4fa48' sqlid='8nhg? ?? 2pdrzs3ww' 516 insert into con$(owner#,name,con#,spare1)values(:1,:2,:3,:4) 517 END OF STMT 518 PARSE #139746758027104:c=1000,e=424,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=0,tim=1470394710583375 519 BINDS #139746758027104: 520? Bind#0 521?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 522?? oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0 523?? kxsbbbfp=7f1953e20f50? bln=22? avl=03? flg=05 524?? value=113 525? Bind#1 526?? oacdty=01 mxl=32(13) mxlc=00 mal=00 scl=00 pre=00 527?? oacflg=10 fl2=0001 frm=01 csi=873 siz=32 off=0 528?? kxsbbbfp=710a6596? bln=32? avl=13? flg=09 529?? value="CONSTRAINT_C1"
--是否違反約束校驗 569 PARSING IN CURSOR #139746758025304 len=260 dep=1 uid=0 oct=3 lid=0 tim=1470394710608559 hv=1153179406 ad='710a6188' sqlid='fks? ?? n1dj2bs7sf' 570? select /*+ all_rows ordered dynamic_sampling(2) */ A.rowid, :1, :2, :3 from "HNYD"."T_PK_UK_IDX_TEST2" A, (select /*+ all_row? ?? s */ "ID" from "HNYD"."T_PK_UK_IDX_TEST2" A where( "ID" is not null) group by? "ID" having count(1) > 1) B where( "A"."ID" = "? ?? B"."ID") 571 END OF STMT
872 select REGEXP_SUBSTR(:1,'\s+rename\s+to\s+',1,1,'i') from dual 873 END OF STMT 874 PARSE #139746756289296:c=0,e=346,p=0,cr=0,cu=0,mis=1,r=0,dep=3,og=1,plh=0,tim=1470394710643058 875 BINDS #139746756289296: 876? Bind#0 877?? oacdty=01 mxl=128(80) mxlc=00 mal=00 scl=00 pre=00 878?? oacflg=13 fl2=206001 frm=01 csi=873 siz=128 off=0 879?? kxsbbbfp=7f1953c45e60? bln=128? avl=80? flg=05 880?? value="alter table HNYD.t_pk_uk_idx_test2 add constraint constraint_c1 primary key(ID)"
1286 PARSING IN CURSOR #139746756266776 len=350 dep=1 uid=0 oct=2 lid=0 tim=1470394710656978 hv=453737599 ad='84a1d8a0' sqlid='dmh1? ?? 7scdhqz3z' 1287?insert into cdef$(obj#,con#,type#,intcols,condlength,condition,robj#,rcon#,match#,refact,enabled,cols,defer,mtime,spare1,spare? ?? 2,spare3)values(:1,:2,:3,decode(:4,0,null,:4),decode(:5,0,null,:5),:6,decode(:7,0,null,:7),decode(:8,0,null,:8),decode(:9,0,nu? ?? ll,:9),decode(:10,0,null,:10), decode(:11,0,null,:11),:12, decode(:13,0,null,:13),:14,:15,:16,:17) 1288 END OF STMT
cdef$此處應(yīng)該就是約束的定義表: 1291? Bind#0 1292?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 1293?? oacflg=00 fl2=0001 frm=00 csi=00 siz=96 off=0 1294?? kxsbbbfp=7f1953e26b40? bln=22? avl=04? flg=05 1295?? value=94495 --------------------------表的OBJECT_ID 1296? Bind#1 1297?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 1298?? oacflg=00 fl2=0001 frm=00 csi=00 siz=0 off=24 1299?? kxsbbbfp=7f1953e26b58? bln=22? avl=04? flg=01 1300???value=15450----------------------------約束的ID 1352? Bind#16 1353?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 1354?? oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0 1355?? kxsbbbfp=7f1953e26a20? bln=22? avl=04? flg=05 1356?? value=94496 -- idx_id_name_normal的OBJECT_ID. 與約束關(guān)聯(lián)的索引
SELECT con#,obj#,enabled FROM sys.cdef$ WHERE con#=15450; select owner,object_id,object_name from dba_objects where object_id in (94495,94496)
查看此主鍵約束與表、索引的關(guān)聯(lián) SQL> SELECT con#,obj#,enabled FROM sys.cdef$ WHERE con#=15450;
? ? ? CON#? ? ?? OBJ#? ??ENABLED ---------- ---------- ---------- ? ?? 15450? ? ? 94495? ? ??94496 SQL> select owner,object_id,object_name from dba_objects where object_id in (94495,94496)? ;
OWNER? ? ? ? ? ? ? ? ? ? ? ? ?? OBJECT_ID OBJECT_NAME ------------------------------ ---------- -------------------------------------------------------------------------------- HNYD? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 94496 IDX_ID_NAME_NORMAL HNYD? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 94495 T_PK_UK_IDX_TEST2
--約束類型:?sys.cdef$ 里面type#=2 SQL> SELECT CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME FROM DBA_CONSTRAINTS WHERE TABLE_NAME = 'T_PK_UK_IDX_TEST2';
CONSTRAINT_NAME? ? ? ? ? ? ? ? CONSTRAINT_TYPE TABLE_NAME ------------------------------ --------------- ------------------------------ CONSTRAINT_C1? ? ? ? ? ? ? ? ? P? ? ? ? ? ? ?? T_PK_UK_IDX_TEST2
--嘗試刪除這個普通索引 SQL> drop index HNYD.IDX_ID_NAME_NORMAL; drop index HNYD.IDX_ID_NAME_NORMAL ? ? ? ? ? ? ? ? * ERROR at line 1: ORA-02429: cannot drop index used for enforcement of unique/primary key
---索引并非唯一的 SQL> select index_name,index_type,table_name,uniqueness from dba_indexes WHERE index_name = 'IDX_ID_NAME_NORMAL';
INDEX_NAME? ? ? ? ? ? ? ? ? ?? INDEX_TYPE? ? ? ? ? ? ? ? ? TABLE_NAME? ? ? ? ? ? ? ? ? ?? UNIQUENESS ------------------------------ --------------------------- ------------------------------ ---------- IDX_ID_NAME_NORMAL? ? ? ? ? ?? NORMAL? ? ? ? ? ? ? ? ? ? ? T_PK_UK_IDX_TEST2? ? ? ? ? ? ??NONUNIQUE
---約束名與約束編號 SQL> SELECT owner#,name,con# FROM sys.con$ oc WHERE name='CONSTRAINT_C1';
? ? OWNER# NAME? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? CON# ---------- ------------------------------ ---------- ? ? ?? 113?CONSTRAINT_C1? ? ? ? ? ? ? ? ? ? ?? 15450
此時查看表的定義為:
? CREATE TABLE "HNYD"."T_PK_UK_IDX_TEST2" ?? (? ? ? ? "ID" NUMBER, ? ? ? ? "NAME" VARCHAR2(100), ? ? ? ?? CONSTRAINT "CONSTRAINT_C1" PRIMARY KEY ("ID") ? USING INDEX?PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS ? TABLESPACE "DBADATA1"? ENABLE ?? ) SEGMENT CREATION DEFERRED ? PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING ? TABLESPACE "DBADATA1"?
所以認為這個主鍵約束,利用現(xiàn)有的索引,管理表中的數(shù)據(jù)(其實鍵約束并不一定需要有索引,比如外鍵,但外鍵沒有索引可能造成嚴重的鎖問題)。名稱與索引名并不對就。單個字段的主鍵也可以利用組合索引(本例就是利用的組合索引)。
平常說的主鍵非空、唯一,這是對的。反正我是很長一段時間誤解了,以為索引就要是唯一索引的,其實并不是。因為主鍵對數(shù)據(jù)約束了,所數(shù)據(jù)具有唯一性,主鍵對應(yīng)的索引定義并不一定要唯一,有可用的索引即可,但建立結(jié)束后,表里面的數(shù)據(jù)受約束的約束。
可能主鍵上索引的目的之一,應(yīng)該是利用其對應(yīng)的索引,在DML操作時,不用造成全表的鎖定(當插入數(shù)據(jù)時,當a會話插入數(shù)據(jù)后不提交,b會話執(zhí)行同樣的語句,會產(chǎn)生行鎖,本例分別在兩個會話執(zhí)行insert into HNYD.T_PK_UK_IDX_TEST2? select 1, 'a' from dual; 即可模擬)。
怎么測試呢: ??a. 擬將索引設(shè)置為不可用狀態(tài),再對數(shù)據(jù)操作,但失敗了,主鍵不可用后,對表無法進行DML操作
SQL> alter index IDX_ID_NAME_NORMAL unusable;
Index altered
SQL> delete hnyd.T_PK_UK_IDX_TEST2; delete hnyd.T_PK_UK_IDX_TEST2 * ERROR at line 1: ORA-01502: index 'HNYD.IDX_ID_NAME_NORMAL' or partition of such index is in unusable state
?b. 約束的是否有效狀態(tài)判斷是decode(c.enabled, NULL, 'DISABLED', 'ENABLED')), 所以也不能對將約束定義里面的存放索引對象ID清空。
?c.將sys.cdef$ 里面enable字段改成一個不合法的值。并flush共享池,不過這直接導(dǎo)致這張表不能執(zhí)行任何語句了,包括查詢。 SQL> insert into HNYD.T_PK_UK_IDX_TEST2 ? 2? ? select 2, 'a' from dual; insert into HNYD.T_PK_UK_IDX_TEST2 ? ? ? ? ? ? ? ?? * ERROR at line 1: ORA-00604: error occurred at recursive SQL level 1 ORA-01426: numeric overflow
?d.將索引從數(shù)據(jù)字典里面修改。 SQL> update sys.ind$ set obj#=-1 where? obj#=94496;
1 row updated.
SQL> insert into HNYD.T_PK_UK_IDX_TEST2 ? 2? ? select 2, 'a' from dual; insert into HNYD.T_PK_UK_IDX_TEST2 ? ? ? ? ? ? ? ?? * ERROR at line 1: ORA-00604: error occurred at recursive SQL level 1 ORA-01426: numeric overflow
SQL> update sys.ind$ set obj#=94496 where? obj#=-1;
1 row updated.
SQL> insert into HNYD.T_PK_UK_IDX_TEST2 ? 2? ? select 2, 'a' from dual; insert into HNYD.T_PK_UK_IDX_TEST2 * ERROR at line 1: ORA-00001: unique constraint (HNYD.CONSTRAINT_C1) violated
測試失敗。沒找到辦法讓主鍵約束處理可用狀態(tài),但其對應(yīng)的索引失效、者無對應(yīng)的索引情況下進行DML操作。
如果利用主鍵做為等值條件訪問,執(zhí)行計劃問題。 --如前所述,雖然這個索引與主鍵關(guān)聯(lián),但如下圖。
再創(chuàng)建一個唯一索引 SQL> create unique index hnyd.pk_pkupidxtest2_id on hnyd.T_PK_UK_IDX_TEST2(id);
Index created.
SQL> alter table T_PK_UK_IDX_TEST2?? drop? constraint CONSTRAINT_C1 ; Table altered --這里刪除約束,并不會刪除關(guān)聯(lián)的索引 SQL>?alter table T_PK_UK_IDX_TEST2 ? 2? ? add? constraint CONSTRAINT_C1 primary key (ID) using index pk_pkupidxtest2_id;
Table altered ---
再回到前面的問題,如果主鍵指定的索引不帶主鍵對應(yīng)的列會是什么效果。(步驟略) a. 刪除約束和所有索引 b. 創(chuàng)建name列上的索引 c.增加主鍵約束,指向name列的索引。 SQL> create index idx_pkukidx_name on T_PK_UK_IDX_TEST2(name);
Index created SQL>?? alter table T_PK_UK_IDX_TEST2 ? 2? ? add? constraint pk_nothing_id primary key (ID) using index idx_pkukidx_name;
SQL> alter table T_PK_UK_IDX_TEST2? add?? constraint pk_nothing_id primary key (ID) using index idx_pkukidx_name; alter table T_PK_UK_IDX_TEST2? add?? constraint pk_nothing_id primary key (ID) using index idx_pkukidx_name * ERROR at line 1: ORA-14196: Specified index cannot be used to enforce the constraint.
至此: 1. 主鍵約束,約束了數(shù)據(jù)的合法性(唯一,非空) 2. 主鍵約束一定需要與合法索引關(guān)聯(lián)(從測試看,需要這個索引帶主鍵字段),并不要求索引列和主鍵列相同,也不需要唯一索引,可以手工指定。若不指定且沒有索引可選,會自己建立與主鍵名一樣的唯一索引。 3. 索引在數(shù)據(jù)訪問的時候快速定位到數(shù)據(jù),如果主鍵上無索引(從外鍵無索引聯(lián)想)任何DML操作都會將全表鎖住。 4. 因為有了主鍵約束,基對應(yīng)列上的索引,最好建立成唯一的,唯一索引可以走“index unique scan" 速度最快,而不是索引。
5.主鍵和索引是完全不同的概念,一個是約束,一個是索引。主鍵和唯一索引沒什么可比性。
1. 創(chuàng)建一張表,指定ID為主鍵(不指定主鍵名): create table t_pk_uk_idx_test (id number primary key, name varchar2(100)); 1.1 查看本表的約束狀態(tài): SELECT TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE, STATUS, DEFERRABLE,VALIDATED FROM DBA_CONSTRAINTS WHERE TABLE_NAME = 'T_PK_UK_IDX_TEST'; TABLE_NAME? ? ? ? ? ? ? ? ? ?? CONSTRAINT_NAME? ? ? ? ? ? ? ? CONSTRAINT_TYPE STATUS?? DEFERRABLE? ?? VALIDATED ------------------------------ ------------------------------ --------------- -------- -------------- ------------- T_PK_UK_IDX_TEST? ? ? ? ? ? ?? SYS_C0015447 ? ? ? ? ? ? ? ? ? ? ? ? ?P? ? ? ? ? ? ?? ENABLED? NOT DEFERRABLE VALIDATED
1.2 查看建立表的語句: SELECT DBMS_METADATA.GET_DDL('TABLE','T_PK_UK_IDX_TEST','HNYD') FROM DUAL; /* ? CREATE TABLE "HNYD"."T_PK_UK_IDX_TEST" ?? (? "ID" NUMBER, ? "NAME" VARCHAR2(100), ???PRIMARY KEY ("ID") ? USING INDEX?PCTFREE 10 INITRANS 2 MAXTRANS 255 ? STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 ? PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 ? BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ? TABLESPACE "DBADATA1"? ENABLE ?? ) SEGMENT CREATION IMMEDIATE ? PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING ? STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 ? PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 ? BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ? TABLESPACE "DBADATA1" */ 1.3 查看被建立約束的語句: SELECT DBMS_METADATA.GET_DDL('CONSTRAINT','SYS_C0015447','HNYD') FROM DUAL;
? /* ? ALTER TABLE "HNYD"."T_PK_UK_IDX_TEST" ADD PRIMARY KEY ("ID") ? USING INDEX?PCTFREE 10 INITRANS 2 MAXTRANS 255 ? STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 ? PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 ? BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ? TABLESPACE "DBADATA1"? ENABLE ? */
1.4 查看被建立索引的語句: SELECT DBMS_METADATA.GET_DDL('INDEX','SYS_C0015447','HNYD') FROM DUAL; ? /* ??CREATE UNIQUE INDEX "HNYD"."SYS_C0015447" ON "HNYD"."T_PK_UK_IDX_TEST" ("ID") ? PCTFREE 10 INITRANS 2 MAXTRANS 255 ? STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 ? PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 ? BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) ? TABLESPACE "DBADATA1" ? */
如果通過create table t_pk_uk_idx_test (id number primary key, name varchar2(100)); 這種方式不指定主鍵名,在建立表時,系統(tǒng)會默認分配一個名字,并建立同名的一個唯一索引,一個主鍵約束。并沒有指定“not null" ,但主鍵約束肯定不允許ID列有空值。
如果嘗試刪除這個唯一索引會報錯: SQL> drop index? "HNYD"."SYS_C0015447" ; drop index? "HNYD"."SYS_C0015447" ? ? ? ? ? ? ? ? ?? * ERROR at line 1: ORA-02429: cannot drop index used for enforcement of unique/primary key --無法刪除用于強制唯一/主鍵的索引。
SQL> ALTER TABLE "HNYD"."T_PK_UK_IDX_TEST" disable PRIMARY KEY;
Table altered
SQL> drop index "HNYD"."SYS_C0015447" ; drop index "HNYD"."SYS_C0015447" ? ? ? ? ? ? ? ? ? * ERROR at line 1: ORA-01418: specified index does not exist
?這樣Disable后,對應(yīng)的索引也被刪除,但約束還在。
SQL> SELECT TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE, STATUS, DEFERRABLE,VALIDATED FROM DBA_CONSTRAINTS WHERE TABLE_NAME = 'T_PK_UK_IDX_TEST';
TABLE_NAME? ? ? ? ? ? ? ? ? ?? CONSTRAINT_NAME? ? ? ? ? ? ? ? CONSTRAINT_TYPE STATUS?? DEFERRABLE? ?? VALIDATED ------------------------------ ------------------------------ --------------- -------- -------------- ------------- T_PK_UK_IDX_TEST? ? ? ? ? ? ?? SYS_C0015447? ? ? ? ? ? ? ? ?? P? ? ? ? ? ? ?? DISABLED NOT DEFERRABLE NOT VALIDATED
再次enable后,索引建立起來了,但發(fā)現(xiàn)索引的OBJECT_ID前后不一樣了,說明索引的確是被刪除了。
2. 那么整個過程到底發(fā)生了什么? 做一個10046 看下 SQL> alter session set events '10046 trace name context forever, level 4';
Session altered.
SQL> create table hnyd.t_pk_uk_idx_test1 (id number primary key, name varchar2(100));
Table created.
SQL> alter session set events '10046 trace name context off';
Session altered.
SQL> select value from v$diag_info WHERE name = 'Default Trace File';
VALUE -------------------------------------------------------------------------------- /u01/app/oracle/diag/rdbms/trac/trac2/trace/trac2_ora_79986.trc
?tkprof /u01/app/oracle/diag/rdbms/trac/trac2/trace/trac2_ora_79986.trc /tmp/79986.txt --前面的數(shù)字表未行號: ? 28 PARSING IN CURSOR #140461753592416 len=79 dep=0 uid=0 oct=1 lid=0 tim=1470392199306885 hv=1413582164 ad='849bb510' sqlid='99a5? ?? 901a433an' ? 29 create table hnyd.t_pk_uk ? 30 END OF STMT
503 insert into?obj$(owner#,name,namespace,obj#,type#,ctime,mtime,stime,status,remoteowner,linkname,subname,dataobj#,flags,oid$,sp? ?? are1,spare2,spare3) values(:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18) 504 END OF STMT 505 PARSE #140461752366488:c=1000,e=648,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=0,tim=1470392199365433 506 BINDS #140461752366488: 507? Bind#0 508?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 509?? oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0 510?? kxsbbbfp=7fbfcce95600? bln=22? avl=03? flg=05 511?? value=113 512? Bind#1 513?? oacdty=01 mxl=32(17) mxlc=00 mal=00 scl=00 pre=00 514?? oacflg=10 fl2=0001 frm=01 csi=873 siz=32 off=0 515?? kxsbbbfp=850f86e6? bln=32? avl=17? flg=09 516?? value="T_PK_UK_IDX_TEST1"
con$是視圖dba_constraint的基表, 存放約束編號和約束名稱。 ?867 PARSING IN CURSOR #140461752215744 len=60 dep=1 uid=0 oct=2 lid=0 tim=1470392199379315 hv=1878790044 ad='84b4fa48' sqlid='8nhg? ?? 2pdrzs3ww' 868 insert into?con$(owner#,name,con#,spare1)values(:1,:2,:3,:4) 869 END OF STMT 870 PARSE #140461752215744:c=0,e=481,p=0,cr=0,cu=2,mis=1,r=0,dep=1,og=4,plh=0,tim=1470392199379314 871 BINDS #140461752215744: 872? Bind#0 873?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 874?? oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0 875?? kxsbbbfp=7fbfcce95600? bln=22? avl=03? flg=05 876?? value=113 877? Bind#1 878?? oacdty=01 mxl=32(12) mxlc=00 mal=00 scl=00 pre=00 879?? oacflg=10 fl2=0001 frm=01 csi=873 siz=32 off=0 880?? kxsbbbfp=852d51fe? bln=32? avl=12? flg=09 881?? value="SYS_C0015449"
?895 ===================== 896 PARSING IN CURSOR #140461752211872 len=88 dep=1 uid=0 oct=9 lid=0 tim=1470392199381070 hv=1310241531 ad='84a712c8' sqlid='7q23? ?? u0x71jcrv' 897?CREATE UNIQUE INDEX "HNYD"."SYS_C0015449" on "HNYD"."T_PK_UK_IDX_TEST1"("ID") NOPARALLEL 898 END OF STMT 這里并沒結(jié)束,后面還有很多對表、對象等基表的操作關(guān)聯(lián)等。
cdef$也dba_constraint 的基表之一; 2049 insert into?cdef$(obj#,con#,type#,intcols,condlength,condition,robj#,rcon#,match#,refact,enabled,cols,defer,mtime,spare1,spare? ?? 2,spare3)values(:1,:2,:3,decode(:4,0,null,:4),decode(:5,0,null,:5),:6,decode(:7,0,null,:7),decode(:8,0,null,:8),decode(:9,0,nu? ?? ll,:9),decode(:10,0,null,:10), decode(:11,0,null,:11),:12, decode(:13,0,null,:13),:14,:15,:16,:17) 2050 END OF STMT
到這里只能說明主鍵約束與唯一索引有一定的關(guān)系,在建立主鍵時,若這個字段上沒有索引,會嘗試在這上面建立唯一索引。
3. 假如這個字段上有索引呢。重新創(chuàng)建一個表,并創(chuàng)建一個普通的組合索引。
SQL> create table t_pk_uk_idx_test2 (id number, name varchar2(100));
Table created SQL> create index idx_id_name_normal on t_pk_uk_idx_test2(id,name);
Index created
在ID列上增加主鍵約束。 SQL> alter session set events '10046 trace name context forever, level 4';
Session altered.
SQL> alter table HNYD.t_pk_uk_idx_test2 add constraint constraint_c1 primary key(ID); alter session set events '10046 trace name context off'; Table altered.
SQL>
Session altered.
SQL> select value from v$diag_info WHERE name = 'Default Trace File';
VALUE -------------------------------------------------------------------------------- /u01/app/oracle/diag/rdbms/trac/trac2/trace/trac2_ora_85746.trc
?29 select count(FA#) from SYS_FBA_TRACKEDTABLES where OBJ# = :1 and bitand(FLAGS, :2)=0 50 LOCK TABLE "HNYD"."T_PK_UK_IDX_TEST2" IN SHARE MODE? NOWAIT 79 alter table HNYD.t_pk_uk_? ? 515 PARSING IN CURSOR #139746758027104 len=60 dep=1 uid=0 oct=2 lid=0 tim=1470394710583377 hv=1878790044 ad='84b4fa48' sqlid='8nhg? ?? 2pdrzs3ww' 516 insert into con$(owner#,name,con#,spare1)values(:1,:2,:3,:4) 517 END OF STMT 518 PARSE #139746758027104:c=1000,e=424,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=0,tim=1470394710583375 519 BINDS #139746758027104: 520? Bind#0 521?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 522?? oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0 523?? kxsbbbfp=7f1953e20f50? bln=22? avl=03? flg=05 524?? value=113 525? Bind#1 526?? oacdty=01 mxl=32(13) mxlc=00 mal=00 scl=00 pre=00 527?? oacflg=10 fl2=0001 frm=01 csi=873 siz=32 off=0 528?? kxsbbbfp=710a6596? bln=32? avl=13? flg=09 529?? value="CONSTRAINT_C1"
--是否違反約束校驗 569 PARSING IN CURSOR #139746758025304 len=260 dep=1 uid=0 oct=3 lid=0 tim=1470394710608559 hv=1153179406 ad='710a6188' sqlid='fks? ?? n1dj2bs7sf' 570? select /*+ all_rows ordered dynamic_sampling(2) */ A.rowid, :1, :2, :3 from "HNYD"."T_PK_UK_IDX_TEST2" A, (select /*+ all_row? ?? s */ "ID" from "HNYD"."T_PK_UK_IDX_TEST2" A where( "ID" is not null) group by? "ID" having count(1) > 1) B where( "A"."ID" = "? ?? B"."ID") 571 END OF STMT
872 select REGEXP_SUBSTR(:1,'\s+rename\s+to\s+',1,1,'i') from dual 873 END OF STMT 874 PARSE #139746756289296:c=0,e=346,p=0,cr=0,cu=0,mis=1,r=0,dep=3,og=1,plh=0,tim=1470394710643058 875 BINDS #139746756289296: 876? Bind#0 877?? oacdty=01 mxl=128(80) mxlc=00 mal=00 scl=00 pre=00 878?? oacflg=13 fl2=206001 frm=01 csi=873 siz=128 off=0 879?? kxsbbbfp=7f1953c45e60? bln=128? avl=80? flg=05 880?? value="alter table HNYD.t_pk_uk_idx_test2 add constraint constraint_c1 primary key(ID)"
1286 PARSING IN CURSOR #139746756266776 len=350 dep=1 uid=0 oct=2 lid=0 tim=1470394710656978 hv=453737599 ad='84a1d8a0' sqlid='dmh1? ?? 7scdhqz3z' 1287?insert into cdef$(obj#,con#,type#,intcols,condlength,condition,robj#,rcon#,match#,refact,enabled,cols,defer,mtime,spare1,spare? ?? 2,spare3)values(:1,:2,:3,decode(:4,0,null,:4),decode(:5,0,null,:5),:6,decode(:7,0,null,:7),decode(:8,0,null,:8),decode(:9,0,nu? ?? ll,:9),decode(:10,0,null,:10), decode(:11,0,null,:11),:12, decode(:13,0,null,:13),:14,:15,:16,:17) 1288 END OF STMT
cdef$此處應(yīng)該就是約束的定義表: 1291? Bind#0 1292?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 1293?? oacflg=00 fl2=0001 frm=00 csi=00 siz=96 off=0 1294?? kxsbbbfp=7f1953e26b40? bln=22? avl=04? flg=05 1295?? value=94495 --------------------------表的OBJECT_ID 1296? Bind#1 1297?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 1298?? oacflg=00 fl2=0001 frm=00 csi=00 siz=0 off=24 1299?? kxsbbbfp=7f1953e26b58? bln=22? avl=04? flg=01 1300???value=15450----------------------------約束的ID 1352? Bind#16 1353?? oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00 1354?? oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0 1355?? kxsbbbfp=7f1953e26a20? bln=22? avl=04? flg=05 1356?? value=94496 -- idx_id_name_normal的OBJECT_ID. 與約束關(guān)聯(lián)的索引
SELECT con#,obj#,enabled FROM sys.cdef$ WHERE con#=15450; select owner,object_id,object_name from dba_objects where object_id in (94495,94496)
查看此主鍵約束與表、索引的關(guān)聯(lián) SQL> SELECT con#,obj#,enabled FROM sys.cdef$ WHERE con#=15450;
? ? ? CON#? ? ?? OBJ#? ??ENABLED ---------- ---------- ---------- ? ?? 15450? ? ? 94495? ? ??94496 SQL> select owner,object_id,object_name from dba_objects where object_id in (94495,94496)? ;
OWNER? ? ? ? ? ? ? ? ? ? ? ? ?? OBJECT_ID OBJECT_NAME ------------------------------ ---------- -------------------------------------------------------------------------------- HNYD? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 94496 IDX_ID_NAME_NORMAL HNYD? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 94495 T_PK_UK_IDX_TEST2
--約束類型:?sys.cdef$ 里面type#=2 SQL> SELECT CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME FROM DBA_CONSTRAINTS WHERE TABLE_NAME = 'T_PK_UK_IDX_TEST2';
CONSTRAINT_NAME? ? ? ? ? ? ? ? CONSTRAINT_TYPE TABLE_NAME ------------------------------ --------------- ------------------------------ CONSTRAINT_C1? ? ? ? ? ? ? ? ? P? ? ? ? ? ? ?? T_PK_UK_IDX_TEST2
--嘗試刪除這個普通索引 SQL> drop index HNYD.IDX_ID_NAME_NORMAL; drop index HNYD.IDX_ID_NAME_NORMAL ? ? ? ? ? ? ? ? * ERROR at line 1: ORA-02429: cannot drop index used for enforcement of unique/primary key
---索引并非唯一的 SQL> select index_name,index_type,table_name,uniqueness from dba_indexes WHERE index_name = 'IDX_ID_NAME_NORMAL';
INDEX_NAME? ? ? ? ? ? ? ? ? ?? INDEX_TYPE? ? ? ? ? ? ? ? ? TABLE_NAME? ? ? ? ? ? ? ? ? ?? UNIQUENESS ------------------------------ --------------------------- ------------------------------ ---------- IDX_ID_NAME_NORMAL? ? ? ? ? ?? NORMAL? ? ? ? ? ? ? ? ? ? ? T_PK_UK_IDX_TEST2? ? ? ? ? ? ??NONUNIQUE
---約束名與約束編號 SQL> SELECT owner#,name,con# FROM sys.con$ oc WHERE name='CONSTRAINT_C1';
? ? OWNER# NAME? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? CON# ---------- ------------------------------ ---------- ? ? ?? 113?CONSTRAINT_C1? ? ? ? ? ? ? ? ? ? ?? 15450
此時查看表的定義為:
? CREATE TABLE "HNYD"."T_PK_UK_IDX_TEST2" ?? (? ? ? ? "ID" NUMBER, ? ? ? ? "NAME" VARCHAR2(100), ? ? ? ?? CONSTRAINT "CONSTRAINT_C1" PRIMARY KEY ("ID") ? USING INDEX?PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS ? TABLESPACE "DBADATA1"? ENABLE ?? ) SEGMENT CREATION DEFERRED ? PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING ? TABLESPACE "DBADATA1"?
所以認為這個主鍵約束,利用現(xiàn)有的索引,管理表中的數(shù)據(jù)(其實鍵約束并不一定需要有索引,比如外鍵,但外鍵沒有索引可能造成嚴重的鎖問題)。名稱與索引名并不對就。單個字段的主鍵也可以利用組合索引(本例就是利用的組合索引)。
平常說的主鍵非空、唯一,這是對的。反正我是很長一段時間誤解了,以為索引就要是唯一索引的,其實并不是。因為主鍵對數(shù)據(jù)約束了,所數(shù)據(jù)具有唯一性,主鍵對應(yīng)的索引定義并不一定要唯一,有可用的索引即可,但建立結(jié)束后,表里面的數(shù)據(jù)受約束的約束。
可能主鍵上索引的目的之一,應(yīng)該是利用其對應(yīng)的索引,在DML操作時,不用造成全表的鎖定(當插入數(shù)據(jù)時,當a會話插入數(shù)據(jù)后不提交,b會話執(zhí)行同樣的語句,會產(chǎn)生行鎖,本例分別在兩個會話執(zhí)行insert into HNYD.T_PK_UK_IDX_TEST2? select 1, 'a' from dual; 即可模擬)。
怎么測試呢: ??a. 擬將索引設(shè)置為不可用狀態(tài),再對數(shù)據(jù)操作,但失敗了,主鍵不可用后,對表無法進行DML操作
SQL> alter index IDX_ID_NAME_NORMAL unusable;
Index altered
SQL> delete hnyd.T_PK_UK_IDX_TEST2; delete hnyd.T_PK_UK_IDX_TEST2 * ERROR at line 1: ORA-01502: index 'HNYD.IDX_ID_NAME_NORMAL' or partition of such index is in unusable state
?b. 約束的是否有效狀態(tài)判斷是decode(c.enabled, NULL, 'DISABLED', 'ENABLED')), 所以也不能對將約束定義里面的存放索引對象ID清空。
?c.將sys.cdef$ 里面enable字段改成一個不合法的值。并flush共享池,不過這直接導(dǎo)致這張表不能執(zhí)行任何語句了,包括查詢。 SQL> insert into HNYD.T_PK_UK_IDX_TEST2 ? 2? ? select 2, 'a' from dual; insert into HNYD.T_PK_UK_IDX_TEST2 ? ? ? ? ? ? ? ?? * ERROR at line 1: ORA-00604: error occurred at recursive SQL level 1 ORA-01426: numeric overflow
?d.將索引從數(shù)據(jù)字典里面修改。 SQL> update sys.ind$ set obj#=-1 where? obj#=94496;
1 row updated.
SQL> insert into HNYD.T_PK_UK_IDX_TEST2 ? 2? ? select 2, 'a' from dual; insert into HNYD.T_PK_UK_IDX_TEST2 ? ? ? ? ? ? ? ?? * ERROR at line 1: ORA-00604: error occurred at recursive SQL level 1 ORA-01426: numeric overflow
SQL> update sys.ind$ set obj#=94496 where? obj#=-1;
1 row updated.
SQL> insert into HNYD.T_PK_UK_IDX_TEST2 ? 2? ? select 2, 'a' from dual; insert into HNYD.T_PK_UK_IDX_TEST2 * ERROR at line 1: ORA-00001: unique constraint (HNYD.CONSTRAINT_C1) violated
測試失敗。沒找到辦法讓主鍵約束處理可用狀態(tài),但其對應(yīng)的索引失效、者無對應(yīng)的索引情況下進行DML操作。
如果利用主鍵做為等值條件訪問,執(zhí)行計劃問題。 --如前所述,雖然這個索引與主鍵關(guān)聯(lián),但如下圖。
再創(chuàng)建一個唯一索引 SQL> create unique index hnyd.pk_pkupidxtest2_id on hnyd.T_PK_UK_IDX_TEST2(id);
Index created.
SQL> alter table T_PK_UK_IDX_TEST2?? drop? constraint CONSTRAINT_C1 ; Table altered --這里刪除約束,并不會刪除關(guān)聯(lián)的索引 SQL>?alter table T_PK_UK_IDX_TEST2 ? 2? ? add? constraint CONSTRAINT_C1 primary key (ID) using index pk_pkupidxtest2_id;
Table altered ---
再回到前面的問題,如果主鍵指定的索引不帶主鍵對應(yīng)的列會是什么效果。(步驟略) a. 刪除約束和所有索引 b. 創(chuàng)建name列上的索引 c.增加主鍵約束,指向name列的索引。 SQL> create index idx_pkukidx_name on T_PK_UK_IDX_TEST2(name);
Index created SQL>?? alter table T_PK_UK_IDX_TEST2 ? 2? ? add? constraint pk_nothing_id primary key (ID) using index idx_pkukidx_name;
SQL> alter table T_PK_UK_IDX_TEST2? add?? constraint pk_nothing_id primary key (ID) using index idx_pkukidx_name; alter table T_PK_UK_IDX_TEST2? add?? constraint pk_nothing_id primary key (ID) using index idx_pkukidx_name * ERROR at line 1: ORA-14196: Specified index cannot be used to enforce the constraint.
至此: 1. 主鍵約束,約束了數(shù)據(jù)的合法性(唯一,非空) 2. 主鍵約束一定需要與合法索引關(guān)聯(lián)(從測試看,需要這個索引帶主鍵字段),并不要求索引列和主鍵列相同,也不需要唯一索引,可以手工指定。若不指定且沒有索引可選,會自己建立與主鍵名一樣的唯一索引。 3. 索引在數(shù)據(jù)訪問的時候快速定位到數(shù)據(jù),如果主鍵上無索引(從外鍵無索引聯(lián)想)任何DML操作都會將全表鎖住。 4. 因為有了主鍵約束,基對應(yīng)列上的索引,最好建立成唯一的,唯一索引可以走“index unique scan" 速度最快,而不是索引。
5.主鍵和索引是完全不同的概念,一個是約束,一個是索引。主鍵和唯一索引沒什么可比性。
來自 “ ITPUB博客 ” ,鏈接:http://blog.itpub.net/27349469/viewspace-2123074/,如需轉(zhuǎn)載,請注明出處,否則將追究法律責任。
轉(zhuǎn)載于:http://blog.itpub.net/27349469/viewspace-2123074/
總結(jié)
以上是生活随笔為你收集整理的主键与其索引对应的关系的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习笔记(11):ArcGIS10.X入
- 下一篇: 搭建Hive远程模式初始化的时候报错Ac