索引index
是對數據庫表中一列或多列的值進行排序的一種數據結構,是某個表中某個列或若干列值的集合和相應的指向表中物理標識這些值的數據頁的邏輯指針清單,其爲表數據提供快速檢索路徑,可大大提高數據檢索的性能,但相對不利於DML操作,oracle 建議一個表上索引數量不要超過7個。
索引的特點:
大大加快數據檢索
索引由oracle自動維護使用,對用戶透明
索引獨立於數據存放,其是否存在不影響數據本身
索引需要佔用物理空間,並隨索引的多少和數據量的增加而增加
創建和維護索引需耗費時間,並隨索引的多少盒數據量的增加而增加
索引的結構 emp :4kb/record,0.16k for empno & rowid for each record
索引塊的數量
每個數據塊可用空間=8192*0.9(1-pctfree)*0.88(1-開銷)=6488b
SQL> create table cc (a char(8));
Table created.
SQL> begin
2 for i in 1..50000 loop
3 insert into cc values (i);
4 commit;
5 end loop;
6 end;
7 /
PL/SQL procedure successfully completed.
SQL> create index ind_cc on cc(a);
Index created.
SQL> analyze table bb computestatistics;
Table analyzed.
SQL> select leaf_blocks,blevel fromdba_indexes where index_name='IND_CC';
LEAF_BLOCKS BLEVEL
----------- ----------
140 1
BB表leaf塊中索引條目結構
行頭2B |
a列長度1B |
A列列值8b |
Rowid長度1B |
Rowid值6B |
BB表leaf塊的數量=139
SQL> select 6488/18 from dual;
6488/18
----------
360.444444
【一個塊放360行記錄】
SQL> select 50000/360 from dual;
50000/360
----------
138.888889【50000需要139個Leaf塊】
BB表Bran塊中索引條目結構
行頭2B |
A列長度 |
A列列值8B |
葉塊地址長度1B |
葉塊地址4B |
BB表Branch塊的數量=139/(6488/16)
SQL> select6488/16 from dual;
6488/16
----------
405.5
【一個塊中可以放405行的branch索引】
SQL> createtable bb (a char(8));
Table created.
SQL> begin
2 forI in 1..500000 loop
3 insert into bb values (I);
4 endloop;
5 end;
6 /
PL/SQL proceduresuccessfully completed.
SQL> analyze table bb computestatistics;
Table analyzed.
SQL> select leaf_blocks,blevel fromdba_indexes where index_name='IND_BB';
no rows selected
SQL> create index ind_bb on bb(a);
Index created.
SQL> commit;
Commit complete.
SQL> select leaf_blocks,blevel fromdba_indexes where index_name='IND_BB';
LEAF_BLOCKS BLEVEL
----------- ----------
1393 2
按索引鍵分類:單列索引,組合索引
單列索引是在表的某個列上所建立的索引;
組合索引是在表的某些列上所建立的索引,where 子句可按最左前綴規則引用其部分或全部列;多個單列索引效率低於一個組合索引。
SQL> alter table trans1 drop constraintkey01 ;
Table altered.
SQL> create index index1_trans1 ontrans1 (tranno);
Index created.
SQL> create index index2_trans1 ontrans1 (tranno,itemname,price);
【建立單列索引和組合索引】
Index created.
SQL> select * from trans1;
TRANNO ITEMNAME PRICE SALEDATE
---------- ---------- -----------------------------
7 777 700 2006-01-02 00:00:00
3 333 300 2007-05-30 00:00:00
2 555 200 2007-05-30 00:00:00
6 777 700 2018-01-02 00:00:00
SQL> select * from trans1 wheretranno=2;
TRANNO ITEMNAME PRICE SALEDATE
---------- ---------- -----------------------------
2 555 200 2007-05-30 00:00:00
SQL> select * from trans1 where tranno=3and itemname='333';
TRANNO ITEMNAME PRICE SALEDATE
---------- ---------- ---------- -------------------
3 333 300 2007-05-30 00:00:00
SQL> select * from trans1 where tranno=6and itemname='777' and price=700;
TRANNO ITEMNAME PRICE SALEDATE
---------- ---------- -----------------------------
6 777 700 2018-01-02 00:00:00
【按照最左前綴規則,僅上述查詢可利用到索引;(最常用列應放在組合索引最左邊)】
SQL>select * from trans1 where itemname='555';
TRANNO ITEMNAME PRICE SALEDATE
---------- ---------- -----------------------------
2 555 200 2007-05-30 00:00:00
按數據結構分類:聚簇索引,非聚簇索引
聚簇索引即建立在聚簇上的索引,創建聚簇索引時,需要對;已有表數據重新進行排序(若表中已有數據),即刪除原始的表數據後再將排序結果按物理順序插回。故聚簇索引建立完畢後,建立聚簇索引的列中的數據已經全部按序排列。
一個表只能包含一個聚簇索引,但該索引可以包含多個列。
在B-樹中,聚簇索引的葉層就是數據頁。
非聚簇索引類似書本索引,索引與數據存放在不同物理區域,建立非聚簇索引時數據本身並不進行排序。
一個表中可含多個非聚簇索引。
在B-樹中,非聚簇索引的葉層仍是索引頁,其以指針指向數據頁實際頁實際存儲位置。
SQL> create index index_clu_emp_dept oncluster clu_emp_dept;
create index index_clu_emp_dept on clusterclu_emp_dept
*
ERROR at line 1:
ORA-00943: cluster does not exist
SQL> create cluster clu_emp_dept(deptnum number(4)) tablespace data01;
Clustercreated.
SQL>CREATE index index_clu_emp_dept on cluster clu_emp_dept;
Indexcreated.
SQL>select cluster_name,tablespace_name,single_table from dba_clusters wherecluster_name='CLU_EMP_DEPT';
CLUSTER_NAME TABLESPACE_NAME SINGLE_TAB
------------------------------------------------------------ ----------
CLU_EMP_DEPT DATA01 N
按唯一性分類:唯一性索引,非唯一性索引
唯一索引保證表中沒有兩行在定義索引的列上具有重複值,oracle自動爲主鍵和唯一鍵列創建唯一索引;主鍵本身就是唯一索引,反之不成立(唯一索引允許一個null值),唯一性索引比非唯一性索引效率高,故在一般情況下,在無重複值的列上應儘量建立唯一性索引。【主鍵約束不允許爲空,唯一約束允許爲空】
若爲某個表的某個列創建了唯一值索引,則即使這個列沒有唯一值約束,也會被強制限制不能插入重複記錄。
SQL> select table_name,index_name fromdba_indexes where table_name='TRANS1';
TABLE_NAME INDEX_NAME
------------------------------ ------------------------------
TRANS1 INDEX1_TRANS1
TRANS1 INDEX2_TRANS1
SQL> drop index index1_trans1;
Index dropped.
SQL> drop index index2_trans1;
Index dropped.
SQL> create unique index index_unique ontrans1 (tranno);
Index created.
索引操作
SQL> alter index index_trans1 rename toindex_trans1_01;
alter index index_trans1 rename toindex_trans1_01
*
ERROR at line 1:
ORA-01418: specified index does not exist
SQL> alter index index_unique rename toindex_trans1_01;
Index altered.
SQL> drop index index_trans1_01;
SQL> select object_name from dba_objectswhere object_type='INDEX';
SQL> SELECT INDEX_NAME FROM DBA_INDEXES;
【查詢系統中所有索引】
INDEX_NAME
------------------------------
SYS_C005978
SYS_C005979
II
SYS_IL0000054779C00002$$
JJ
X
KEY00
SYS_C006203
KEY02
KEY03
KEY04
KEY05
SYS_C006204
SYS_C006205
SYS_C006206
SYS_C006207
IND_BB
IND_CC
SQL> select table_name,index_name fromdba_indexes where table_name='TRANS1';
【查詢指定表上所建的全部索引】
SQL> select table_name,index_name fromdba_indexes where table_name='TRANS1';
TABLE_NAME INDEX_NAME
------------------------------------------------------------
TRANS1 INDEX_UNIQUE
SQL> selectindex_name,index_type,table_name,table_type,tablespace_name from dba_indexeswhere index_name='INDEX_TRANS1';
【查詢指定索引的類型,索引所對應的表,及存儲該索引的表空間】
SQL> selectindex_name,index_type,table_name,table_type,tablespace_name from dba_indexes whereindex_name='INDEX_UNIQUE';
INDEX_NAME INDEX_TYPE TABLE_NAME
------------------------------ ---------------------------------------------------------
TABLE_TYPE TABLESPACE_NAME
----------- ------------------------------
INDEX_UNIQUE NORMAL TRANS1
TABLE SYSTEM
SQL> select index_name,table_name,column_name from dba_ind_columns whereindex_name='INDEX_UNIQUE';
【查詢指定索引所對應的列】
INDEX_NAME TABLE_NAME
------------------------------------------------------------
COLUMN_NAME
----------------------------------------------------------------------------------------------------
INDEX_UNIQUE TRANS1
TRANNO
序列生成器(sequence generator)
用於產生一個不重複的整數值序列供應用使用,序列以指定步長增加或減少序列值,直到達到序列規定的最大或最小值,序列生成器避免了在應用層實現序列而引起的性能瓶頸。
SQL> create sequence seq_test;【建立序列生成器】
Sequence created.
Increment(增量,增加;增額;盈餘) by 3【指定增長步長,負數遞減,不能爲0(默認遞增,步長爲1)】
Start with 100【指定初始值(默認爲1)】
Maxvalue 900 【指定遞增序列的最大值(默認爲10^27)】
Minvalue 1【指定遞減序列的最小值(默認爲-10^26)】
Cycle 【到達極值後是否重新循環開始計數(默認NO)】
SQL> select seq_test.nextval from dual;
NEXTVAL
----------
1
SQL> select seq_test.nextval from dual;
NEXTVAL
----------
2
【查看序列生成器的下個生成值,且序列生成器遞增一個步長】
SQL> select seq_test.currval from dual;
CURRVAL
----------
2
SQL> select seq_test.currval from dual;
CURRVAL
----------
2
【查看序列生成器的當前生成值,且序列生成器不遞減】
SQL> select * from dba_sequences where sequence_name='SEQ_TEST';
【查看指定序列生成器的相關情況】
SEQUENCE_OWNER SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BYC O
------------------------------------------------------------ ---------- ---------- ------------ - -
CACHE_SIZE LAST_NUMBER
---------- -----------
SYS SEQ_TEST 11.0000E+27 1 N N
20 21
SQL> desc dba_sequences;
Name Null? Type
------------------------------------------------------------- ------------------------------------
SEQUENCE_OWNER NOTNULL VARCHAR2(30)
SEQUENCE_NAME NOT NULL VARCHAR2(30)
MIN_VALUE NUMBER
MAX_VALUE NUMBER
INCREMENT_BY NOT NULL NUMBER
CYCLE_FLAG VARCHAR2(1)
ORDER_FLAG VARCHAR2(1)
CACHE_SIZE NOT NULL NUMBER
LAST_NUMBER
SQL> insert into trans1 values(seq_test.nextval,'itemname',&price,sysdate);
Enter value for price: 890
old 1: insert into trans1 values(seq_test.nextval,'itemname',&price,sysdate)
new 1: insert into trans1 values (seq_test.nextval,'itemname',890,sysdate)
【使用序列生成器】
1 row created.
SQL> select * from trans1;
TRANNO ITEMNAME PRICE SALEDATE
---------- ---------- -----------------------------
7 777 700 2006-01-02 00:00:00
3 333 300 2007-05-30 00:00:00
2 555 200 2007-05-30 00:00:00
6 777 700 2018-01-02 00:00:00
4 itemname 2345 2012-10-08 15:11:37
5itemname 890 2012-10-08 15:12:11
SQL> alter sequence seq_test incrementby 2 maxvalue 88 minvalue 8 nocycle;
alter sequence seq_test increment by 2maxvalue 88 minvalue 8 nocycle
*
ERROR at line 1:
ORA-04007: MINVALUE cannot be made toexceed the current value
SQL> alter sequence seq_test incrementby 2 maxvalue 88 minvalue 1 nocycle;
【修改生成器未來生成參數,不能修改start值】
Sequence altered.
SQL> select seq_test.nextval from dual;
NEXTVAL
----------
7
SQL> select seq_test.nextval from dual;
NEXTVAL
----------
9
SQL> drop sequence seq_test;
Sequence dropped.
SQL> alter sequence seq_test incrementby 5 maxvalue 10 minvalue 3 nocycle;
alter sequence seq_test increment by 5maxvalue 10 minvalue 3 nocycle
*
ERROR at line 1:
ORA-04007: MINVALUE cannot be made toexceed the current value
SQL> alter sequence seq_test incrementby 5 maxvalue 10 minvalue 0 nocycle;
Sequence altered.
SQL> select seq_test.nextval from dual;
NEXTVAL
----------
1
SQL> alter sequence seq_test incrementby 5 maxvalue 10 minvalue 0 nocycle;
Sequence altered.
SQL> select seq_test.nextval from dual;
NEXTVAL
----------
6
SQL> alter sequence seq_test incrementby 5 maxvalue 10 minvalue -2 nocycle;
Sequence altered.
SQL> alter sequence seq_test incrementby 5 maxvalue 10 minvalue -3 cycle;
alter sequence seq_test increment by 5maxvalue 10 minvalue -3 cycle
*
ERROR at line 1:
ORA-04013: number to CACHE must be less than one cycle
SQL> alter sequence seq_test incrementby 5 maxvalue 666666666 minvalue -3 cycle;
Sequence altered.
SQL> drop sequence seq_test;
【刪除序列生成器】
Sequence dropped.
數據庫鏈路(Link)
是在分佈式數據庫中用來表示到一個遠程數據庫的連接路徑的數據庫對象。用來方便地直接調用遠程數據庫中各種對象。
[oracle@desktop241 admin]$ vim tnsnames.ora
# tnsnames.ora Network Configuration File:/u01/app/oracle/product/10.2.0/db_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.
abc=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = desktop241.example.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ora10)
)
)
EXTPROC_CONNECTION_DATA =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
)
(CONNECT_DATA =
(SID = PLSExtProc)
(PRESENTATION = RO)
)
)
SQL> create public database link linkabconnect to system identified by "zouhao" using 'abc';
【建立數據庫鏈路】
Database link created.
SQL> select * from iii@linkab;
【通過數據庫鏈路操作遠程數據庫對象】
no rows selected
SQL> drop * from iii@linkab;
no rows selected
SQL> select * from dba_db_links;
【查詢數據庫鏈路信息】
OWNER DB_LINK USERNAM HOST CREATED
------- ----------------------------------------------- -------------------- -------------------
PUBLIC LINKABC.REGRESS.RDBMS.DEV.US.ORACLE.COM SCOTT abc 2012-10-08 17:20:10
PUBLIC LINKAB.REGRESS.RDBMS.DEV.US.ORACLE.COM SYSTEM abc 2012-10-08 17:25:44
SQL> drop public database link linkabc;
【刪除數據庫鏈路】
Database link dropped.
SQL> drop public database link linkab;
Database link dropped.
同義詞(synonym)
同義詞是爲數據庫對象或其他同義詞指定的別名。公用同義詞可被數據庫中所有用戶存取,專用同義詞僅能被指定用戶及其他被授權的用戶存取。
同義詞的特點:
可屏蔽對象的名字及其持有者;
爲分佈式數據庫的遠程對象提供位置透明性;
爲用戶簡化sql語句。
SQL> select table_name from dba_tableswhere table_name='TEST';
【查系統中存在兩個test表】
TABLE_NAME
------------------------------
TEST
TEST
SQL> select * from scott.test;
【查詢時以用戶名區分】
A1
----------
bbb
SQL> create public synonym stest for scott.test;
【建立同義詞屏蔽用戶信息】
Synonym created.
SQL> select * from stest;
【注意須先有目標表的訪問權限,才能通過該目標表上所建的公有同義詞訪問該目標表,此處sys用戶先有kitty.test的訪問權限,故可通過stest訪問該表】
A1
----------
Bbb
SQL> create public synonym ttest fortest@linck2;
【對遠程表建同義詞屏蔽數據鏈路信息】
Synonym created.
SQL> select * from dba_synonyms wheresynonym_name='STEST';
OWNER SYNONYM_NAME TABLE_OWNER TABLE_NAME
------- ------------------------------------------------------------ ------------------------------
DB_LINK
----------------------------------------
PUBLIC STEST SCOTT TEST
SQL> select * from dba_synonyms wheresynonym_name='TTEST';
【查詢系統中指定同義詞的定義】
OWNER SYNONYM_NAME TABLE_OWNER TABLE_NAME
------- ------------------------------------------------------------ ------------------------------
DB_LINK
----------------------------------------
PUBLIC TTEST TEST
LINCK2.REGRESS.RDBMS.DEV.US.ORACLE.COM
SQL> drop public synonym stest;
Synonym dropped.
SQL> drop public synonym rest;
Synonym dropped.
SQL> drop public synonym ttest;
Synonym dropped.【刪除同義詞】
程序單元(Program unit)
是指存儲過程procedure,函數function,包package和觸發器trigger。
一個過程和函數,是由SQL語句和PL/SQL語句組合在一起,爲執行某一個任務的一個可執行單位(命名PL/SQL塊)。一個過程或函數可被建立,在數據庫中存儲其編譯形式,可由用戶或數據庫應用所執行。過程和函數差別在函數總返回單個值給調用者,而過程沒有值返回給調用者。
包提供相關的過程、函數、變量和其它包結構封裝起來並存儲在一起的一種方法,以方便這些程序單元的組織,允許管理者和應用開發者利用該方法組織如此的程序,以提供更多的功能和提高性能。
觸發器是用來在某些條件被滿足時自動被觸發進行指定的數據處理的程序單元。
程序單元特點:
具有可重用性
抽象和數據隱藏
透明性和安全性
Procedure存儲過程
SQL> host vim pro_del.sql
SQL> get pro_del.sql
1 create or replace procedurepro_del
2 (v_no in emp.empno%type) is
3 begin
4 delete from emp whereempno=v_no;
5 dbms_output.put_line('theemployee'||v_no||'has deleted!');
6*end pro_del;
7 /
Procedure created.
SQL> create table emp as select * fromscott.emp;
Table created.
SQL> exec pro_del(7934);
the employee7934has deleted!
【調用指定存儲過程(或在其他程序單元中直接調用)】
PL/SQL procedure successfully completed.
SQL> select * from dba_source wherename='PRO_DEL';
OWNER NAME TYPE LINE TEXT
------- ---------- ------------ --------------------------------------------------
SYS PRO_DEL PROCEDURE 1 procedure pro_del
SYS PRO_DEL PROCEDURE 2 (v_no in emp.empno%type) is
SYS PRO_DEL PROCEDURE 3 begin
SYS PRO_DEL PROCEDURE 4 delete from emp where empno=v_no;
SYS PRO_DEL PROCEDURE 5 dbms_output.put_line('the employee'||v_n
o||'has deleted!');
SYS PRO_DEL PROCEDURE 6 end pro_del;
6 rows selected.
SQL> select * from dba_procedures whereobject_name='PRO_DEL';
OWNER OBJECT_NAMPROCEDURE_ OBJECT_ID SUBPROGRAM_IDOVERLOAD OBJECT_TYPE AGG PIP
------- ---------- ---------- ----------------------- ---------- ------------------- --- ---
IMPLTYPEOW IMPLTYPENA PAR INT DET AUTHID
---------- ---------- --- --- ---------------
SYS PRO_DEL 55799 1 PROCEDURE NO NO
NO NO NO DEFINER
SQL> drop procedure pro_del;
【刪除指定存儲過程】
Procedure dropped.
SQL> insert into employees2(salary,employee_id) values (100,120);
1 row created.
SQL> get emp.sql
1 declare
2 emp_num number(6) := 120;
3 bonus number(6) := 100;
4 merit number(4) := 50;
5 procedure raise_salary (emp_id number,
6 amount in number default 100,
7 extra in number default 50)is
8 begin
9 update employees2 set salary=salary+amount+extra
10 where employee_id=emp_id;
11 end raise_salary;
12 begin
13 raise_salary(emp_num);
14*end;
SQL> /
PL/SQL procedure successfully completed.
SQL> select * from employees2;
EMPLOYEE_ID BONUS MERIT SALARY
----------- ---------- --------------------
120 250
SQL> host vim emp.sql
SQL> get emp.sql
1 declare
2 emp_num number(6) := 120;
3 bonus number(6) := 100;
4 merit number(4) := 50;
5 procedure raise_salary (emp_id number,
6 amount in number default 100,
7 extra in number default 50)is
8 begin
9 update employees2 setsalary=salary+amount+extra
10 where employee_id=emp_id;
11 end raise_salary;
12 begin
13 raise_salary(emp_num,extra=>25);
14*end;
SQL> /
PL/SQL procedure successfully completed.
SQL> select * from employees2;
EMPLOYEE_ID BONUS MERIT SALARY
----------- ---------- --------------------
120 375
IN參數(默認)可將值傳給被調用子程序;Out參數將值返回給予程序的調用者;
INOUT參數可將初始值傳送給被調用的子程序,並將修改後的值返回給調用者。
SQL> select * from employees;
EMPLOYEE_ID SALARY BONUS MERIT
----------- ---------- --------------------
120 225 50 100
1 100
2 200
3 300
SQL> get emp.sql
1 declare
2 emp_num number(6) := 120;
3 bonus number(6) := 100;
4 merit number(4) := 50;
5 procedure raise_salary (emp_id number,
6 amount in number default 100,
7 extra in number default 50)is
8 begin
9 update employees setsalary=salary+amount+extra
10 where employee_id=emp_id;
11 end raise_salary;
12 begin
13 raise_salary(&emp_num,&amount,&extra);
14*end;
SQL> /
Enter value for emp_num: 1
Enter value for amount: 100
Enter value for extra: 100
old 13: raise_salary(&emp_num,&amount,&extra);
new 13: raise_salary(1,100,100);
PL/SQL procedure successfully completed.
SQL> select * from employees;
EMPLOYEE_ID SALARY BONUS MERIT
----------- ---------- --------------------
120 225 50 100
1 300
2 200
3 300
SQL> select func_fn(4) from dual;
【調用指定函數(或在其他程序單元中直接調用)】
FUNC_FN(4)
----------
24
SQL> set serverout on
SQL> get func_fn.sql
1 create or replace functionfunc_fn(n in number)
2 return number
3 is
4 begin
5 if n=0 then return 1;
6 else return n*func_fn(n-1);
7 end if;
8* end func_fn;
9 /
Function created.
SQL> execdbms_output.put_line(func_fn(4));
24
PL/SQL procedure successfully completed.
SQL> select * from dba_source wherename='FUNC_FN';
OWNER NAME TYPE LINE TEXT
------ ---------- ------------ --------------------------------------------
SYS FUNC_FN FUNCTION 1 function func_fn(n in number)
SYS FUNC_FN FUNCTION 2 returnnumber
SYS FUNC_FN FUNCTION 3 is
SYS FUNC_FN FUNCTION 4 begin
SYS FUNC_FN FUNCTION 5 ifn=0 then return 1;
SYS FUNC_FN FUNCTION 6 elsereturn n*func_fn(n-1);
SYS FUNC_FN FUNCTION 7 endif;
SYS FUNC_FN FUNCTION 8 endfunc_fn;
8 rows selected.
SQL> drop function func_fn;
【刪除指定函數,從內存中】
Function dropped.
Return statements
1. In functions,a RETURN statement must contain an expression,whichis evaluated (評估)when the RETURNstatement is executed.
2. In procedures,a RETURN statement does not return a value andso cannot contain anexpression.the statementreturns control to the caller before the end of the procedure.