第八章 游標和觸發器 初識游標 在PL/SQL塊中執行SELECT、INSERT、DELETE和UPDATE語句時,ORACLE會在記憶體中為其分配上下文區(Context Area),即緩衝區。游標是指向該區的一個指針,或是命名一個工作區(Work Area),或是一種結構化數據類型。它為應用等量齊 ...
第八章 游標和觸發器
初識游標
在PL/SQL塊中執行SELECT、INSERT、DELETE和UPDATE語句時,ORACLE會在記憶體中為其分配上下文區(Context Area),即緩衝區。游標是指向該區的一個指針,或是命名一個工作區(Work Area),或是一種結構化數據類型。它為應用等量齊觀提供了一種對具有多行數據查詢結果集中的每一行數據分別進行單獨處理的方法,是設計嵌入式SQL語句的應用程式的常用編程方式。
定位行,逐行跳動
游標分類
1. 顯式 游標用於處理SELECT語句返回的多行數據;人為創建,干預
2. 隱式 游標用於處理SELECT INTO和非查詢的DML語句;系統自動創建,管理
常用屬性 CURSOR
%ISOPEN
用於確定游標是否已經打開。如果游標已經打開,則返回值為TRUE;否則返回FALSE
%FOUND
檢查是否從結果集中提取到數據。如果提取到數據,則返回值為TRUE;否則返回FALSE
%NOTFOUND
與%FOUND屬性恰好相反,如果提取到數據,則返回值為FALSE;否則返回TRUE
%ROWCOUNT
返回到當前行為止已經提取到的實際行數
顯示游標格式:
1. 定義游標
CURSOR cursor_name IS select_SQL;
2. 打開游標
OPEN cursor_name;
3. 提取數據
FETCH cursor_name INTO variable1,variable2,...;
當運行fetch後,游標才開始工作,記錄當前行,有數據則下移,然後置%FOUND,%NOTFOUND的值
4. 關閉游標
CLOSE cursor_name;
顯示游標:
游標動態傳參,顯示游標
隱式for迴圈游標:
隱含游標,當執行一條非查詢的DML語句或者SELECT...INTO語句時,都會創建一個隱含游標
1. 隱含游標的名稱是SQL,不能對SQL游標顯式執行OPEN、FETCH和CLOSE語句。
2. Oracle隱式地打開、提取,並總是自動地關閉SQL游標
3. 隱含游標的屬性
SQL%FOUND
SQL%NOTFOUND
SQL%ROWCOUNT
SQL%ISOPEN
示例
declare
v_stuId number := '&input_stuId';
begin
delete from student where stu_id=v_stuId;
if sql%found then
DBMS_OUTPUT.PUT_LINE('找到員工');
else
DBMS_OUTPUT.PUT_LINE('未找到員工');
end if;
end;
初始觸發器
觸發器是指被隱含執行的存儲過程,它可以使用PL/SQL進行開發
當發生特定事件(如修改表、創建對象、登錄到資料庫)時,Oracle會自動執行觸發器的相應代碼
觸發器的類型
1、DML觸發器
在對資料庫表進行DML(insert,update,delete)操作時觸發,並且可以對每行或者語句操作上進行觸發。
2、替代觸發器
是oracle8專門為進行視圖操作的一種觸發器
3、系統觸發器
對資料庫系統事件進行觸發,如啟動、關閉等
註意事項:
1. 觸發器不接受參數。
2. 一個表上最多可有12個觸發器,但同一時間、同一事件、同一類型的觸發器只能有一個。並各觸發器之間不能有矛盾。
3. 在一個表上的觸發器越多,對在該表上的DML操作的性能影響就越大。
4. 觸發器最大為32KB。若確實需要,可以先建立過程,然後在觸發器中用CALL語句進行調用。
5. 觸發器中不能包含事務控制語句(COMMIT,ROLLBACK,SAVEPOINT)。因為觸發器是觸發語句的一部分,觸發語句被提交、回退時,觸發器也被提交、回退了。在觸發器主體中調用的任何過程、函數,都不能使用事務控制語句。
表頭複製
CREATE TABLE dept_log AS SELECT * FROM dept WHERE 1=2;
DML觸發器
刪除示例:
create or replace trigger tr_del_student
--指定觸發時機為刪除操作前觸發
before delete
on student
--說明創建的是行級觸發器
for each row
begin
--將修改前數據插入到日誌記錄表,要確保SQL可以正常工作
insert into student_log values(:old.stu_id,:old.stu_name,:old.stu_age,:old.stu_sex,:old.stu_class,:old.stu_create_date);
end;
修改示例
create or replace trigger tr_update_student
--指定觸發時機為修改操作後觸發
after update
on student
for each row
begin
-- 記錄修改後的值
insert into student_log
values(:new.stu_id,:new.stu_name,:new.stu_age,:new.stu_sex,:new.stu_class,:new.stu_create_date);
end;
刪除觸發器
drop trigger trigger_name
系統觸發器
創建日誌記錄表
create table log_event(
log_type varchar2(20),
username varchar2(20),
logonTime date,
logoffTime date
);
登錄觸發器
create or replace trigger logon_trigger
after logon on database
begin
insert into log_event(log_type,username,logonTime)
values('logon',ora_login_user,sysdate);
end;
登出觸發器
create or replace trigger logoff_trigger
before logoff on database
begin
insert into log_event(log_type,username,logoffTime)
values('logoff',ora_login_user,sysdate);
end;