資料庫中觸發器和索引的使用
阿新 • • 發佈:2018-12-26
觸發器
什麼是觸發器?
觸發器是一種過程,與表關係密切,用於保護表中的資料。當一個表被修改(insert、update或delete)時,觸發器字動執行。觸發器課實現多個表之間資料的一致性和完整性。
觸發器的型別有3種:
DML觸發器:Oracle可以在DML語句進行觸發,可以在DML操作前或操作後進行觸發,並且可以對每個行或語句操作上進行觸發。
替代觸發器:由於在Oracle裡,不能直接對由兩個以上的表建立的檢視進行操作,所以給出了替代觸發器。它就是Oracle 8專門為進行檢視操作的一種處理方法。
系統觸發器:Oracle從8i開始提供了第三種類型的觸發器叫系統觸發器。它可以在Oracle資料庫系統的事件中進行觸發,如Oracle系統的啟動與關閉等。
建立DML觸發器:
DML觸發器由DML語句激發,並且由該語句的型別決定DML觸發器的型別
可以定義DML觸發器進行insert、update、delete操作
DML觸發器可以在上述操作之前或之後激發,也可以在行或語句操作上激發
觸發器的語法:
觸發器的基本使用應用例項:
建立DML觸發器 偽記錄 ":old"和":new" ":old" 代表操作完成前的舊記錄 ":new" 代表操作完成後的新記錄 在執行三種DML語句時 ":old"和":new"的存在情況 建立行級觸發器 (for each row)應用例項: 在表emp_sal與emp1表關聯,建立觸發器 當emp1表中一個人的工資發生改變時,記錄該事件-- 當有員工的工資發生變化時,觸發事件修改該員工對應的部門工資資料 create or replace trigger dept_sal_trigger --觸發的時機 after --觸發的事件 update or insert or delete on emp1 --把員工對應的部門工資進行修改 declare cursor total_sal is select sum(sal) total_sal,deptno from emp1 group by deptno; dept_s dept_sal%rowtype; begin -- delete from dept_sal; for dept_s in total_sal loop update dept_sal set total_sal=dept_s.total_sal where deptno=dept_s.deptno; -- insert into dept_sal values(dept_s.deptno,dept_s.total_sal); end loop; -- 不要新增commit; EXCEPTION when OTHERS THEN rollback; end;
--當有人的工資發生改變時,需要做記錄
create or replace trigger emp_sal_trigger
after update on emp1
for each row --行級觸發器
begin
insert into emp_sal values(:old.empno, :new.sal, emp_sal_seq.nextval,sysdate,:old.sal);
exception
when others then dbms_output.put_line('新增失敗');
end;
測試程式碼:update emp1 set sal = sal*1.1; --指定行級觸發器
commit;
注意:觸發器中不能有commit和rollback語句觸發器中的謂詞
應用例項:
--當有人的工資發生改變時,需要做記錄
--當公司多了一個僱員的時候,新增記錄中只有新的工資(沒有old.sal,沒有new.sal)
--當有人離職時,需要把該員工的工資修改記錄刪除
create or replace trigger emp_sal_trigger
after update or insert or update on emp1
for each row --行級觸發器
begin
if updating
then insert into emp_sal values(:old.empno, :new.sal, emp_sal_seq.nextval,sysdate,:old.sal);
elsif inserting
then insert into emp_sal values(:new.empno,:new.sal,emp_sal_seq.nextval,sysdate,0);
else
delete from emp_sal where empno=:old.empno;
end if;
exception
when others then dbms_output.put_line('新增失敗');
end;
測試程式碼:
--執行(測試)語句
--新增一條資料
insert into emp1 values(9527,'TOM','CLERK',7902,sysdate,1200,null,20);
COMMIT;
--修改工資
UPDATE emp1 set sal=sal*1.5 where empno=9527;
COMMIT;
--員工離職
delete from emp1 where empno=9527;
COMMIT;
對觸發器本身的刪除和修改
--觸發器禁用
alter trigger emp_sal_trigger disable;
--觸發器開啟
alter trigger emp_sal_trigger enable;
--刪除觸發器
drop trigger emp_sal_trigger;
--查詢當前使用者的所有觸發器
select * from user_triggers;
執行結果:
索引的語法:
/*
主鍵約束/唯一約束 : 系統會自動建立索引,以SYS_開始
1. 為一個表的列或組合列建立索引後,讀取的速度加快
2. 但寫的速度卻減慢了,因為插入,修改和刪除資料後,還要更新索引
3. 索引也需要空間,系統要佔用大約為表1.2倍的硬碟和記憶體空間來儲存索引,增加了空間負擔
索引建立的原則
1. 在大表上建立索引才有意義
2. 在where子句或是連線條件上經常引用的列上建立索引
3. 索引的層次不要超過4層
提高查詢效率是以消耗一定的系統資源為代價的,索引不能盲目的建立,這是考驗一個dba是否優秀的很重要的指標
索引分類:
1. 按照資料儲存方式,分為B*樹,反向索引,點陣圖索引
2. 按照索引列的個數分為,單列索引,複合索引
3. 按照索引列值的唯一性,分為唯一索引和非唯一索引
此外還有函式索引,全域性索引,分割槽索引等.
*/
--檢視有多少張表
select * from user_tables;
--查看錶t10結構
select column_name,data_type,data_length,nullable,data_default from all_tab_columns where lower(table_name)='t10';
--查看錶t10內容
select * from t10 ;
--建立索引
create index idx_t10_name on t10(name);
--刪除索引
drop index idx_t10_name;
--檢視所有索引(從字典資料表中查詢)
select index_name,table_name from user_indexes where lower(index_name)='idx_t10_id_name' ;
--建立複合索引
create index idx_t10_id_name on t10(id,name);
--在pet表的adopt_time欄位上建立降序唯一索引adopt_time_index
create unique index adopt_time_index on pet(adopt_time desc);
--在pet表的type_id欄位上建立點陣圖索引type_id_bitmap_index
create bitmap index type_id_bitmap_index on pet(type_id);
--在pet表的health、love欄位上建立組合索引health_love_index
create index health_love_index on pet(health,love);
--建立基於函式TO_CHAR(adopt_time,'YYYY')索引to_char_index
create index to_char_index on pet(TO_CHAR(adopt_time,'YYYY'));
--在pet表的master_id 欄位上建立反向鍵索引master_id_reverse_index
create index master_id_reverse_index on pet(master_id) reverse;
--刪除在pet表上建立的反向鍵索引master_id_reverse_index
drop index master_id_reverse_index;
建立索引的列的特點:
1.經常需要搜尋的列
2.主鍵列
3.經常用在連結的列
4.經常需要根據範圍搜尋的列
5.經常需要排序的列
6.經常出現在where子句的列
不應該建立索引的列:
1.查詢中很少使用或參考的列
2.只有很少資料值的列
3.定義為lob型別的列
4.修改效能遠遠大於檢索效能
避免限制索引:
1.避免使用不等操作符(<>、!=)
2.避免使用is null or is not null
3.避免在where子句中使用函式
4.避免在比較時使用不匹配的資料型別