/*
8、遊標
顯示遊標:指的是遊標使用之前必須得先聲明定義,一般是對查詢語句的結果事進行定義遊標,然後通過打開遊標循環獲取結果集內的記錄,或者可以根據業務需求跳出循環結束遊標的獲取。循環完成後,可以通過關閉遊標,結果集就不能再獲取了。全部操作完全由開發者自己編寫完成,自己控制。
隱式遊標:指的是PL/SQL自己管理的遊標,開發者不能自己控制操作,只能獲得它的屬性信息。
*/
/*
顯示遊標 使用步驟
1、聲明遊標
declare cursor cursor_name(遊標名) is select_statement(查詢語句);
2、打開遊標
open cursor_name;
3、讀取遊標中數據
fetch cursor_name into record變量;
4、關閉遊標
close cursor_name;
*/
--8.1.1 創建遊標給員工的薪水加1000
declare
cursor emp_addsal is select * from emp;--1 聲明遊標 emp_addsal
emprow emp%rowtype;--定義emprow接收每行的數據
begin
open emp_addsal;--2 打開遊標
loop-- 循環讀取遊標中的數據
fetch emp_addsal into emprow;--3 讀取遊標中數據 到 emprow
exit when emp_addsal%notfound;--如果數據讀取結束退出循環
update emp set sal = (emprow.sal+1000) where empno = emprow.empno;--給對應員工工資加1000
end loop;
close emp_addsal;--關閉遊標
commit;--提交數據
end;
/
select * from emp;--查詢員工工資
/*
顯式遊標的屬性
1、%NOTFOUND。表示遊標獲取數據的時候是否有數據提取出來,沒有數據返回TRUE,有數據返回false。經常用來判斷遊標是否全部循環完畢,如案例1%NOTFOUND爲true的時候,說明循環完畢,跳出LOOP循環。
2、%FOUND。正好和%NOTFOUND相反,當遊標提取數據值時有值,返回TRUE,否則返回FALSE。
3、%ISOPEN。用來判斷遊標是否打開。
4、%ROWCOUNT。表示當前遊標FETCH INTO獲取了多少行的記錄值,用來做計數用的。
*/
--8.1.2 查看顯示遊標的屬性
declare
cursor emp_addsal is select * from emp;--1 聲明遊標 emp_addsal
emprow emp%rowtype;--定義emprow接收每行的數據
begin
open emp_addsal;--2 打開遊標
loop-- 循環讀取遊標中的數據
fetch emp_addsal into emprow;--3 讀取遊標中數據 到 emprow
exit when emp_addsal%notfound;--如果數據讀取結束退出循環
if emp_addsal%found then--這裏if 判斷是多餘的 只是爲了顯示found的作用
dbms_output.put_line(emp_addsal%rowcount);
end if;
end loop;
close emp_addsal;--關閉遊標
end;
/
--8.2 隱式遊標 sql%found 上一條查詢語句包含返回數據
declare
emprow emp%rowtype;
begin
select * into emprow from emp where empno = 7369;
if sql%found then
dbms_output.put_line('找到編號7369的員工,薪水上漲10%');
--update emp set sal = 1.1*sal where empno = 7369;--寫法1
update emp set sal = 1.1*emprow.sal where empno = emprow.empno;--寫法2
commit;--提交
else
dbms_output.put_line('沒有找到編號7369的員工');
end if;
end;
/
/*
9、觸發器:Oracle觸發器是使用者對Oracle數據庫的對象做特定的操作時,觸發的一段PL/SQL程序代碼,叫做觸發器。觸發的事件包括對錶的DML操作,用戶的DDL操作以及數據庫事件等。
觸發器分類:
1、數據操作(DML)觸發器。
create [ or replace] trigger tr_name(觸發器名)
before|after
delete| insert | update [of column1,column2...]
[or delete |insert| update of colum1,colum2...]
on table_name(表名)
[for each row]
[follows tr_name1(其它觸發器名)]
[when 條件]
declare
--聲明部分
begin
--觸發器內容部分
end;
2、數據定義操作(DDL)觸發器。
create [ or replace] trigger tr_name(觸發器名)
before|after
ddl_event|database_event
on SCHEMA(數據庫對象)|DATABASE(數據庫)
[follows tr_name1(其它觸發器名)]
[when 條件]
declare
--聲明部分
begin
--觸發器內容部分
end;
3、用戶和系統事件觸發器。
4、INSTEAD OF 觸發器。
5、複合觸發器。
*/
--9.1.1 數據操作(DML)觸發器。 表級觸發器 不添加 for each row場景
create or replace trigger tr_emp_update
before update on emp
begin
if to_char(sysdate,'dd')=28 then
raise_application_error(-20000,'每月28號不允許修改員工信息');--自定義異常錯誤號範圍 20000-20999
end if;
end;
/
update emp set sal = 10000;--測試觸發器
drop trigger tr_emp_update;--刪除觸發器
--9.1.2 數據操作(DML)觸發器。 表級觸發器 行級觸發器 對比 for each row
create or replace trigger tb_tr_emp_update
before update on emp
begin
dbms_output.put_line('測試表級觸發器觸發次數');
end;
/
update emp set sal = 10000;--觸發器響應一次
rollback;--回滾操作
drop trigger tb_tr_emp_update;--刪除觸發器
create or replace trigger row_tr_emp_update
before update on emp
for each row--行級觸發器
begin
dbms_output.put_line('測試行級觸發器觸發次數');
end;
/
update emp set sal = 10000;--觸發器響應多次
rollback;--回滾操作
drop trigger row_tr_emp_update;--刪除觸發器
--9.1.3 數據操作(DML)觸發器。insert 行級觸發器 new屬性
create or replace trigger tr_emp_insert
before insert on emp
for each row--new 和 old屬性只能出現在行級觸發器中 insert觸發器只有new屬性
begin
if :new.empno=9999 then
raise_application_error(-20000,'不允許使用9999員工號');--自定義異常錯誤號範圍 20000-20999
end if;
end;
/
insert into emp(empno) values(9999);--測試觸發器
drop trigger tr_emp_insert;--刪除觸發器
--9.1.4 數據操作(DML)觸發器。delete 行級觸發器 old 屬性
create or replace trigger tr_emp_delete
before delete on emp
for each row--new 和 old屬性只能出現在行級觸發器中 delete觸發器只有old屬性
begin
if :old.empno=7369 then
raise_application_error(-20000,'不允許刪除員工號7369的員工');--自定義異常錯誤號範圍 20000-20999
end if;
end;
/
delete from emp where empno = 7369;--測試觸發器
drop trigger tr_emp_delete;--刪除觸發器
--9.1.5 數據操作(DML)觸發器。update 行級觸發器 new屬性 old 屬性
create or replace trigger tr_emp_update
before update on emp
for each row--new 和 old屬性只能出現在行級觸發器中 delete觸發器只有old屬性
begin
if :old.empno=7369 and :new.ename='zhangsan' then
raise_application_error(-20000,'不允許修改員工號7369的員工姓名爲張三');--自定義異常錯誤號範圍 20000-20999
end if;
end;
/
update emp set ename = 'zhangsan' where empno = 7369;--測試觸發器
drop trigger tr_emp_update;--刪除觸發器
--9.1.6 數據操作(DML)觸發器。 before after關鍵字
create or replace trigger tr_emp_before
before delete on emp
begin
dbms_output.put_line('before觸發器');
end;
/
create or replace trigger tr_emp_after
after delete on emp
begin
dbms_output.put_line('after觸發器');
end;
/
delete from emp where empno = 9999;--測試觸發器
drop trigger tr_emp_before;--刪除觸發器
drop trigger tr_emp_after;--刪除觸發器
--9.1.7 數據操作(DML)觸發器。 follows 關鍵字
create or replace trigger tr_emp_before1
before delete on emp
begin
dbms_output.put_line('before觸發器1');
end;
/
create or replace trigger tr_emp_before2
before delete on emp
follows tr_emp_before1
begin
dbms_output.put_line('before觸發器2');
end;
/
create or replace trigger tr_emp_before3
before delete on emp
follows tr_emp_before2
begin
dbms_output.put_line('before觸發器3');
end;
/
delete from emp where empno = 9999;--測試觸發器
drop trigger tr_emp_before1;--刪除觸發器
drop trigger tr_emp_before2;--刪除觸發器
drop trigger tr_emp_before3;--刪除觸發器
--9.1.7 數據操作(DML)觸發器。 when 關鍵字 必須同 行級觸發器一起使用
create or replace trigger tr_emp_before1
before delete on emp
for each row
when (to_char(sysdate,'dd')=28)
begin
dbms_output.put_line('when關鍵字測試');--觸發條件 when條件滿足 刪除條件成立
end;
/
delete from emp where empno = 7369;--測試觸發器
rollback;--回滾操作
drop trigger tr_emp_before1;--刪除觸發器
--9.2.1 數據定義操作(DDL)觸發器。對象級操作 創建觸發器禁止對emp表的表結構進行修改
create or replace trigger tr_emp_ddl
before alter on schema
begin
if dictionary_obj_name='EMP' and sysevent='ALTER' then --傳值需要大寫!!!
raise_application_error(-20001,'不允許修改emp表結構');
end if;
end;
/
alter table emp add remark varchar2(200);--測試觸發器
drop trigger tr_emp_ddl;--刪除觸發器
--9.2.2 數據定義操作(DDL)觸發器。對象級操作 創建觸發器禁止對emp表的表結構進行修改,刪除
create or replace trigger tr_emp_ddl
before alter or drop on schema
begin
if dictionary_obj_name='EMP' and sysevent='ALTER' then --傳值需要大寫!!!
raise_application_error(-20001,'不允許修改emp表結構');
end if;
if dictionary_obj_name='EMP' and sysevent='DROP' then --傳值需要大寫!!!
raise_application_error(-20001,'不允許刪除emp表結構');
end if;
end;
/
alter table emp add remark varchar2(200);--測試觸發器
drop table emp;--測試觸發器
drop trigger tr_emp_ddl;--刪除觸發器
--9.2.3 數據定義操作(DDL)觸發器。 使用sys用戶 數據庫級操作 定義數據庫登陸觸發器
create table login_log--數據庫登陸日誌表
(
logid VARCHAR2(20),
loginuser VARCHAR2(100),
logindate DATE
);
create sequence loginseq;--創建登陸序列
create or replace trigger tr_db_ddl
after logon on database--logon 登陸操作
begin
insert into login_log values(loginseq.nextval,sys.login_user,sysdate);
end;
/