Oracle數據庫的基本使用和高級查詢

1.Oracle體系結構

本次使用的是Oracle18c數據庫版本 java學習交流Q羣:1004577069

1>數據庫
	Oracle數據庫時數據的物理存儲,這就包括(數據庫文件ORA或者DBF,控制文件,聯機日誌,參數文件).其實Oracle數據庫的概念和其他數據庫不一樣,這裏的數據庫時一個操作系統只有一個庫.可以看作是Oracle就只有一個大數據庫
2>實例
	一個Oracle實例(Oracle Instance)有一系列的後臺進程(Background Processes)和內存結構(Memory Stryctures)組成一個數據庫可以有N個實例
3>用戶
	用戶時在實例下創建的,不同實例可以創建相同名字的用戶
4>表空間
	表空間是Oracle對物理數據庫上相關數據文件(ORA或者DBF文件)的邏輯映射一個數據庫在邏輯被劃分成一到若干個表空間,每個表空間包含了在邏輯上相關聯的一組結構.每個數據庫至少有一個表空間(system表空間)
	每個表空間由同一磁盤上的一個或者多個文件組成,這些文件叫數據文件(datafile)一個數據文件只能屬於一個表空間
5>數據文件
	數據文件是數據庫的物理存儲單位,數據庫的數據是存儲在表空間中的,真正是在某一個或者多個數據文件中而一個表空間可以由一個或者多個數據文件組成,一個數據文件只能屬於一個表空間。一旦數據文件被加入到某個表空間後,就不能刪除這個文件,如果要刪除某個數據文件,只能刪除其所屬於的表空間纔行
	注:表的數據,是有用戶放入到某一個表空間的,而這個表空間會隨機把這些數據放到一個或者多個數據文件中
	由於oracle數據庫不是普通的概念,oracle是有用戶和表空間數據進行管理和存放的但是表不是由表空間去查詢的,而是用戶去查詢的因爲不同用戶可以在同一個表空間建立同一個名字的表,這裏區分的就是用戶了

2.創建表空間

表空間
表空間:ORACLE數據庫的邏輯單元,數據庫----表空間 一個表空間可以與多個數據文件(物理結構)關聯
一個數據庫可以建立多個表空間,一個表空間可以建立多個用戶一個用戶可以建立多個表

	create tablespace itxu datafile 'c:\itxu.dbf' size 100m autoextend on next 10m
	itxu:爲表空間名稱
	datafile:指定表空間對應的數據文件
	size:後定義的表空間的初始大小
	autoextend on:自動增長,當表空間存儲都佔滿,自動增長
	next:後指定的是一次增長的大小

3.用戶

1.創建用戶
	create user itxu
	identified by '010313'
	default tablespace itxu
identified by:後邊是用戶的密碼
default tablespace:後邊是表名稱空間
oracle數據庫與其他是數據庫產品區別在於,表和其他的數據庫對象都是存儲在用戶下的

4.用戶賦權限

新建的用戶沒有權限,登錄後會提示
Oracle中已存在三個重要的角色: connect角色,resource角色,dba角色

CONNECT角色:是授予最終用戶的典型權利,最基本的
	ALTER SESSION----修改會話
	CREATE CLUSTER----建立聚簇
	CREATE DATABASE LINK---建立數據庫鏈接
	CREATE SEQUENCE----建立序列
	CREATE SESSION----建立會話
	CREATE SYNONYM-----建立同義詞
	CREATE VIEW-----建立視圖
RESOURCE角色:是授予開發人員的
	CREATE CLUSER-----建立聚簇
	CREATE PROCEDURE----建立過程
	CREATE SEQUECE----建立序列
	CREATE TABLE-----建表
	CREATE TRIGGER---建立觸發器
	CREATE TYPE-----建立類型
	
BDA角色:擁有全部特權,是系統最高權限,只有BDA纔可以創建數據庫結構,並且系統權限也需要DBA授出,且DBA用戶可以操作全體用戶的任意基表,包括刪除
grant dba to itxu
進入system用戶下給用戶賦予dba權限,否則無法登陸

5.Oracle數據類型

1>Varchar,varchar2:表示一個字符串
2>NUMBER:NUMBER(n)表示一個整數,長度是n/NUMBER(m,n):表示一個小數,總長度是m,小數是n,整數是m-n
3>DATA:表示日期類型
4>CLOB:大對象,表示大文本數據類型,可存4G
5>BLOB:大對象,表示二進制數據,可存4G

6.表的管理

1>建立表

	create table 表名(
    字段1 數據類型 [default 默認值],
    字段2 數據類型 [default 默認值],
        .....
	字段n 數據類型 [default 默認值]
    );
    範例:創建person表
    create table person(
    	pid number(10),
        name varchar2(10),
        gender number(1) default 1,
        birthday date
    );

2>.表刪除/修改

表刪除
	語法:DROP TABLE 表名
		drop table person;
表的修改
	在sql中使用alter可以修改表
		 添加語法: ALTER TABLE 表名稱 ADD(列名1 類型[DEFAULT 默認值],列名1 類型[DEFAULT 默認值]....);
		 修改語法: ALTER TABLE 表名稱 MODIFY(列名1 類型[DEFAULT 默認值],列名1 類型[DEFAULT 默認值]...)
		 修改列名: ALTER TABLE 表名稱 RENAME 列名1 TO 列名2
	範例:在person表中添加address列
	alter table person add(address varchar2(10));
	範例:在person表deaddress列的長度修改爲20
	alter table person modify (address varchar2(20));

3>.數據庫的CRUD操作

3>數據庫表數據的更新
	 INSERT(添加)
		標準寫法:INSERT INTO 表名[(列名1,列名2)...]VALUES(值1,值2,....);
		簡單寫法O:INSERT INTO 表名 VALUES(值1,值2...);
	注意:使用簡單的寫法必須按照表中的字段的順序來插入值,而且如果有爲空的字段使用null
	insert into person(pid,name,gender,birthday)values(1,'張三',1,NULL);
	 UPDATE(修改)
		全部修改: UPDATE 表名 SET 列名1=值1,列名2=值2,...
		局部修改: UPDATE 表名 SET 列名1=值1,列名2=值2,...WHERE 修改條件
	 DELETE(刪除)
		語法: DELETE FORM 表名 WHERE 刪除條件;
		在刪除語句中如果不指定刪除條件的話就會刪除所有的數據,因爲ORACLE的事務對數據庫的變更處理,我們必須做提交事務才能讓數據真正的插入到數據庫中,在同樣在執行完數據庫變更的操作後還可以把事務進行回滾,這樣就不會插入到數據庫.如果事務提交後則不可以再回滾
		提交:COMMIT	回滾:ROLLBACK

4>.序列
4>序列
在很多數據庫中都存在一個自動增長的列,如果現在想要在Oracle中完成自動增長的功能,則只能依靠序列完成,所有的自動增長操作需要用戶手動完成處理

語法: CREATE SEQUENCE 序列名
		[INCREMENT BY n]	--默認增加幾個
		[START WITH n]		--序列從幾開始默認是1
		[{MAXVALUE/MINVALUE n|NOMAXVALUE}]
		[{CYCLE|NOCYCLE}]
		[{CACHE n|NOCACHE}];
	範例:創建一個seqpersonid序列,驗證自動增長的操作
		CREATE SEQUENCE seqpersonid;
		序列創建完成之後,所有的自動增長應該由用戶自己處理,所以在序列中提供了以下的兩種操作:
			nextval:取得序列的下一個內容
			currval:取得序列的當前內容
		SELECT sqlpersonid.currval from dual;
		SELECT sqlpersonid.nextval from dual;
		在插入數據時需要自增的主鍵可以這樣使用
	insert into person values(sqlpersonid.nextval,'張三',1,null);
		在實際項目中每一張表會配一個序列,但是表和序列是沒有必然聯繫的,一個序列被哪一張表都可以使用但是我們一般一張表用一個序列
		序列的管理一般使用工具來管理

7.單行函數

1.字符函數

接收字符輸入返回字符或者數值,dual是僞表
	1).把小寫的字符轉化爲大寫的字符
	select upper('hello') from dual;
	2).把大寫字符轉化爲小寫的字符
	select lower('HELLO')from dual;

2.數值函數

1).四捨五入函數:ROUND()
	默認情況下ROUND四捨五入取整可以自己指定保留的位數
	select round(26.18) from dual;
	2).直接截取:TRUNC()
	直接截取不看後面的數字是否是大於5
	select trunc(56.16 -1) from dual;
	3).求餘數MOD()
	select mod(10,3)from dual;

3.日期函數

Oracle中提供了很多和日期相關的函數,包括日期的加減等等
	---查詢出emp表中所有員工入職距離現在多少天
	select sysdate-e.hiredate from emp e;
	---算出明天此刻
	select sysdate+1 from dual;
	---查詢出emp表中所有員工入職距離現在幾個月
	select months_between(sysdate,e.hiredate)from emp e;
	---查詢出emp表中所有員工入職距離現在幾年
	select months_between(sysdate,e.hiredate)/12 from emp e;
	---查詢出emp表中所有員工入職距離現在有多少個禮拜
	select (sysdate-e.hiredate)/7 from emp e;

4.轉換函數

	--日期轉字符串
select to_char(sysdate,'fm yyyy-MM-dd hh24:mi:ss')from dual;
	--字符串轉日期
select to_date(' 2019-7-24 23:53:54','fm yyyy-MM-dd hh24:mi:ss')from dual;

5.通用函數

1).空值處理
	select e.sal*12+nvl(e.comm,0) from emp e; 
	2).Decode函數
	該函數類似if...else if...else
	語法:DECODE(col/expression,[seach1,result],[seach2,result2])...[default])
		Col/expression:列名或表達式
		Search1,Search2...用於比較的條件
		Result1:返回值
		如果col/expression和Searchi匹配就返回resulti,否則返回default的默認值
			3).case when
	select t.empno,t.ename,
		case 
			when t.job='CLERK'then '業務員'
				else
					'無業'
			end
		from emp t;

8.多行函數(聚合函數)

1>.統計記錄數COUNT()
	查詢出員工的數量
    select count(*)from emp;
2>.最小值	MIN()
	查詢員工的最低工資
	select min(sal) from emp;
3>.最大值 MAX()
	查詢員工的最高工資
	select max(sal) from emp;
4>.查詢平均值AVG()
	查詢出員工的平均工資
	select avg(sal)from emp;
5>.求和函數SUM()
	查詢出20號部門的員工的工資總和
	select sum(sal)from emp t where t.deptno=20;

9.分組統計

分組統計需要使用GROUP BY來分組
語法:SELECT *|列名 FROM 表名{WHERE 查詢條件}{GROUP BY分組字段}ORDER BY 列名1 ASC/DESC
1>查詢出每個部門的人數
select deptno,count(ename)from emp group by deptno;
2>查詢出每個部門的平均工資
select deptno,avg(sal) from emp group by deptno;
3>查詢出部門編號,和部門下的人數
	select deptno,count(ename)from emp;
ORA-00937:不是單組分組函數
	1.如果使用分組函數,SQL只可以把GROUP BY分組條件字段和分組函數查詢出來,不能有其他字段
	2.如果使用分組函數,不適用GROUP BY只可以查詢出來分組函數的值
	select deptno,ename,count(ename)from emp group by deptno;
ORA-00979:不是GROUP BY表達式
4>按部門分組,查詢出部門名稱和部門員工數量
	select d.deptno,d.dname,count(ename) from emp e,dept d where e.deptno=d.deptno group by d.deptno,d.dname;
5>查詢出部門人數大於5人的部門
	select d.deptno,d.name,count(ename)from emp e,dept d where e.deptno=d.deptno group by d.deptno,d.dname having count(ename)>5;
6>查詢出部門平均工資大於2000的部門
select deptno,avg(sal)from emp group by deptno having avg(sal)>2000;

10.多表查詢

1>多表連接基本查詢
	使用一張以上的表就是多表查詢
	語法:SELECT{DISTINCT}* |列名...FROM 表名 別名,表名1 別名{WHERE 限制條件 ORDER BY 排序字段 ASC|DESC}
	如果多張表進行一起查詢而且每張表的數據很大的話笛卡爾積就會變的非常大,對性能造成影響,想要去掉笛卡爾積我們需要關聯查詢
	在兩張表中我們發現有一個共同的字段是deptno,deptno就是兩張表的關聯的字段,我們可以使用這個字段來做限制條件,兩張表的關聯查詢字段一般是其中一張的表的主鍵,另外一張表的外鍵
select * from emp,dept where emp.deptno=dept.deptno;
2>外連接
	1).右連接
		當我們在做基本的查詢的時候,查詢出所有的部門下的員工我們發現編號爲40的部門下沒有員工,但是要求把該部門也展示出來,我們發現上面的基本查詢時辦不到的
		select e.empno,ename,d.deptno,d.dname,from emp e,dept d
where e.deptno(+)=d.deptno;
		使用(+)表示左連接或者右連接,當(+)在左邊表的關聯字段上時是左連接,如果是右邊表的關聯字段是右連接
		查詢出所有員工的上級領導
		select e.empno,e.ename,m.empno,m.ename from emp e,emp m
where e.mgr=m.empno(+);

11.子查詢

子查詢:在一個查詢的內部還包括着另一個查詢,則稱爲子查詢
查詢出比編號 7654 薪資高的員工
	select * from emp where emp.sal>(select t.sal from emp t where t.empno='7654');
	1>.子查詢的操作分爲三類
		單列子查詢:返回的結果是一列或者是一個內容
		單行子查詢:返回多個列,有可能是一個完整的記錄
		多行子查詢:返回多條記錄
查詢出比員工7654的工資高,同時從事和7788的工作一樣的員工
	select * from emp e1 where e1.sal>
	(select e.sal from emp e where e.empno='7654')and e1.job=
	(select e2.job from emp e2 where e2.empno='7788');
查詢出每個部門的最低工資和最低工資的對應人和部門名稱
select d.dname,a.minsal,e.ename from 
(select deptno,min(sal) minsal from emp  group by deptno)a,emp e
where d.deptno=a.deptno and e.sal=a.min;

12.ROWNUM分頁查詢

ROWNUM:表示行號,實際上此行號是一個列但是這個列是一個僞列,此列可以在每張表出現
	查詢emp表中帶有rownum列
	select rownum,t.* from emp t;
--就會在該行上加上一個行號行號從1開始,一次遞增,不能跳着走
---emp表工資倒敘排列後,每頁五條記錄,查詢第二頁
--排序操作會影響rownum的順序
select rownum,emp.* from emp order by emp.sal desc;
--如果涉及到排序,但是還要使用rownum的話我們可以再次嵌套循環
select rownum,t.* from(
select rownum,emp.* from emp order by emp.sal desc)t;
--emp表工資倒敘排列後,每頁五條記錄,查詢第二頁
--rownum行號不能寫上一個大於正數
select * from(
select rownum rn,e.* from(
select * from emp  order by sal desc)e 
where rownum<11)
where rn>5

第一種寫法:
select * from (select rownum rm,e.* from (select * from emp)e where rownum<11)b where b.rm>5;
第二種寫法:
select * from(select rownum r,emp.* from emp )b where b.r>5 and
b.r<11;

13.視圖

1>視圖就是封裝了一條複雜查詢的語句
	1).語法:CREATE VIEW 視圖名稱 AS 子查詢
建立視圖,視圖中包含了編號爲20的所有員工信息
 create view empvd20 as select * from emp t where t.deptno=20;
視圖創建完成可以使用視圖來查詢視圖中所有的信息
select * from empvd20 t;
	2).語法:CREATE OR REPLACE VIEW 視圖名稱 AS 子查詢
如果視圖已經存在我們可以使用語法2來創建視圖,這樣已有的視圖就會被全部的覆蓋
create or replace view empvd20 as select * from emp t where t.deptno=20;
	3).我們也可以通過修改視圖來修改原來的數據但是我們並不希望這樣做一般的視圖都會設置爲只讀屬性
	語法:CRETAE OR REPLACE VIEW 視圖名稱 AS 子查詢 WITH READ ONLY
	create or replace view empvd20 as seelct * from emp t where t.deptno=20 with reda only;

14.PL/SQL基本語法

什麼是PL/SQL?
PLSQL是Oracle對sql語言的過程化擴展,指在SQL命令語言中增加了過程處理語句(如分支,循環等)使SQL語言具有過程處理能力把SQL語言的操縱能力與過程語言的數據處理能力結合起來使得PLSQL面向過程但比過程語言簡單,高效,靈活和實用
範例1:爲職工漲工資,每個人漲10%的工資
update emp seet sa=sal*1.1;


1>PL/SQL程序語法
	程序語法:
	 declare 
	 	說明部分(變量說明,遊標,例外說明)
	 begin
	 	語句序列(DML語句)
	 exception
	 	例外處理語句
	 End;
2>常量和變量定義
	在程序的聲明的階段可以來定義常量和變量
	1).變量的基本類型就是Oracle中的建表時字段的變量如:char,varchar2,date,number,boolean,long
	定義語法:var1 char(15);
	Psal number(9,2);
	說明變量名,數據類型和長度後用分號結束說明語句
	常量定義:married constant boolean:=true;
	2).引用變量
	Myname emp.ename%type;
	引用型變量,即my_name的類型與emp表中的ename列的類型一樣在Sql中使用into來賦值
	declare
		emprec emp.ename%type;
	begin
		select t.ename into emprec from emp t where t.empno=7369;
		dbms_output.put_line(emprec);
	3).記錄型變量
	Emprec  emp%rowtype 
	記錄變量分量的引用 
	emp_rec.ename:='ADAMS'; 
    declare   
    	p emp%rowtype;
    begin   
    	select * into p from emp t where t.empno = 7369;   			dbms_output.put_line(p.ename || ' ' || p.sal); 
    end; 
3>if分支
	語法 1:IF 條件 THEN 語句 1;
	語句 2;
	END IF; 
    語法 2:IF 條件 THEN 語句序列 1;
	ELSE 語句序列 2;        
	END IF;  
    語法 3:IF 條件 THEN 語句; 
    ELSIF  語句  THEN  語句; 
    ELSE 語句;
    END IF;
範例 1:如果從控制檯輸入 1 則輸出我是 1
    declare   
	pnum number := &num; 
	begin   
	if pnum = 1 then 
	dbms_output.put_line('我是1'); 
	end if; 
	end; 
範例 2:如果從控制檯輸入 1 則輸出我是 1否則輸出我不是 1 
	declare   
	mynum number := &num; 
	begin   
	if mynum = 1 then 
	dbms_output.put_line('我是1'); 
	else 
	dbms_output.put_line('我不是1'); 
	end if; 
	end; 
	範例 3:判斷人的不同年齡段 18歲以下是未成年人,18歲以上 40以下是成年人,40以上是老年人 
	declare   
	mynum number := &num; 
	begin   
	if mynum < 18 then 
	dbms_output.put_line('未成年人'); 
	elsif mynum >= 18 and mynum < 40 then 
    dbms_output.put_line('中年人'); 
	elsif mynum >= 40 then 
	dbms_output.put_line('老年人'); 
	end if; 
	end;
4>LOOP循環語句
	語法1:WHILE total<=25000 LOOP
		....
		total=total+salary;
		END LOOP;
	語法2:LOOP
		EXIT[when 條件];
		....
		END LOOP;
	語法3:FOR 1 IN 1..3 LOOP
		END LOOP
範例:使用語法 1 輸出 1 到10 的數字 
		declare   
		step number := 1; 
		begin   
		while step <= 10 loop
         dbms_output.put_line(step);
         step := step + 1;   
         end loop;
         end; 
範例:使用語法 2 輸出 1 到10 的數字 
		declare   
		step number := 1; 
		begin   
		loop     
		exit when step > 10;     
		dbms_output.put_line(step);
         step := step + 1;  
         end loop; end; 
範例:使用語法 3 輸出 1 到10 的數字 
		declare   
			step number := 1;
         begin   
         	 for step in 1 .. 10 
         	 loop     														dbms_output.put_line(step);   
         	 end loop; 
         end; 
5>遊標Cursor
	在寫java程序中有集合的概念,那麼在pl/sql中也會用到多條記錄,這個時候我們就要用到遊標,遊標可以存儲查詢返回的多條數據
	語法:CURSOR 遊標名[(參數名 數據類型,參數名 數據類型,...)]IS SELECT 語句;
	如:cursor c1 is select ename from emp;
	1).遊標的使用步驟
		1.打開遊標:open cl;(打開遊標執行查詢)
		2.取一行遊標的值:fetch into pjob;(取一行到變量中)
		3.關閉遊標:close c1;(關閉遊標釋放資源)
		4.遊標的結束方式:exit when c1%notfound
		5.注意上面的pjob必須與emp表中的job類型一致
範例1:使用遊標的方式輸出emp表中員工的姓名和編號
	declare
		cursor pc is select * from emp;
		pemp emp% rowtype;
	begin
		open oc;
		loop
			fetch pc
				into pemp;
			exit when pc%notfound;
			dbms_output.put_line(pemp.empno||pemp.ename);
		end loop;
		close pc;
	end;
範例 2:按員工的工種漲工資,總裁 1000 元,經理漲 800 元其,他人員漲 400 元。 備份出一張新表爲 myemp;
create table myemp as select * from emp; 
declare   
	cursor pc is select * from myemp; 
	addsal myemp.sal%type;   
	pemp   myemp%rowtype; 
begin   
	open pc;   
		loop     
			fetch pc
            	into pemp;
					exit when pc%notfound; 
				if pemp.job = 'PRESIDENT' then  
                	addsal := 1000;    
				elsif pemp.job = 'MANAGER' then   
                	addsal := 800;    
				else 
               		addsal := 400; 
				end if;     
					update myemp t set t.sal = t.sal + addsal where t.empno = pemp.empno;
		end loop;   
		close pc; 
end;
範例 3:寫一段PL/SQL 程序,爲部門號爲 10 的員工漲工資。 
declare   
		cursor pc(dno myemp.deptno%type) is select empno from myemp where deptno = dno;
pno myemp.empno%type; 
begin   
	open pc(20); 
	loop     
		fetch pc 
			into pno;  
				exit when pc%notfound;  
update myemp t set t.sal = t.sal + 1000 where t.empno = pno;   		end loop;  
	close pc; 
end;
6>存儲過程
	存儲過程是在大型數據庫系統中,一組爲了完成特定功能的SQL語句集,經編譯後存儲在數據庫中,用戶通過制定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它,存儲過程是數據庫中的一個重要對象,任何一個設計良好的數據庫應用程序應該用到存儲過程
	創建存儲過程的語法:
	CRETAE[or replace]PROCEDURE 過程名[(參數名 in/out 數據類型)]
	AS
	Begin
		PLSQL子程序體;
	End;
	或者
	CRETAE[or replace]PROCEDURE 過程名[(參數名 in/out數據類型)]
	is
	begin
		PLSQL子程序體;
	End過程名
	範例1:創建一個輸出helloworld的存儲過程
	create or replce procedure helloworld is
	begin 
		dbms_output.put_line('helloworld');
	end helloword;
	
	調用存儲過程
	在plsql中調用存儲過程
	begin
		--call the procedure
	 	helloworld;
	end;
	範例2:給指定的員工工資100工資,並打印出漲前和漲後的工資
	分析:我們需要使用帶有參數的存儲過程
	create or replace procedure addSall(eno in number)is pemp myemp%rowtype;
	begin
		select * into pemp from myemp where mep=eno;
		update myemp set sal=sal+100 where empno=eno;
		dbms_output.put_line('漲工資前'||pemp.sal||'漲工資後'||(pemp.sal+100));
		end addSall;
	調用
	begin
		addsall(eno=>7902);
		commit;
	end;
7>存儲函數
	create or replace function 函數名(Name is type,Name in type...)retun 數據類型 is 結果變量 數據類型;
	begin
		return(結果變量)
	end 函數名;
	存儲過程和存儲函數的區別
	一般來講,過程和函數的區別在於函數可以有一個返回值,而過程沒有返回值但過程和函數都可以通過out指定一個活多個輸出參數.我們可以利用out產生,在過程和函數中實現返回多個值
範例:使用存儲函數來查詢指定員工的年薪
	cretae or replace function empincome(eno in emp.empno%type)return number is 
		psal emp.sal%type;
		pcomm emp.comm%type;
	begin
		select t.sal into psal from emp t where t.empno=eno;
		return psal*12 +nvl(pcomm,0);
	end;
使用存儲過程來替換上面的例子 
	create or replace procedure empincomep(eno in emp.empno%type, income out number) is psal emp.sal%type;
    	pcomm emp.comm%type;
    begin   
    	select t.sal, t.comm into psal, pcomm from emp t where t.empno = eno;   
    income := psal*12+nvl(pcomm,0);
    end empincomep; 
調用:
	declare 
		income number;
	begin 
		empincomep(7369,income);
		dbms_output.put_line(income);
	end;
8>觸發器
	數據庫觸發器是一個與表相關的,存儲的PL/SQL程序。每當一個特定的數據操作語句(Insert,update,delete)在指定的表上發出時,Oracle自動的執行觸發器中定義的語句序列
	觸發器可用於:
		·數據確認
		·實施複雜的安全性檢查
		·做審計,跟蹤表上所做的數據操作等
		·數據的備份和同步
	觸發器的類型:
		語句級觸發器:在指定的操作語句之前或之後執行一次,不管這條語句影響多少行
		行級觸發器(FOR EACH ROW):觸發語句作用的每一條記錄都被觸發在行級觸發器中使用old 和new僞記錄變量,識別值的狀態
		語法:
		CREATE [or REPLACE]TRIGGER 觸發器名稱
			{BEFORE|AFTER}
			{DELETE|INSERT|UPDATE[OF列名]}
		ON 表名
			[FOR EACH ROW[WHEN(條件)]]
		begin
			PLSQL塊;
		END觸發器名;
範例:插入員工後打印一句話"一個新員工插入"
	create or replace tigger testTigger
		after insert on person
	declare
		--local variables here
		
	begin
		dbms_output.put_line('一個新的員工被插入');
	end testTrigger;
範例:不能在休息的時候插入員工
	create or replace trigger validInsertPerson
		before insert on person
	declare
		weelend varchar2(10);
	begin
		select to_char(sysdate,'day')into weekend from dual;
		if weekend in('星期一')then
			raise_application_error(-20001,'不能在非法時間插入員工');
		end if;
		end validInsertPerson;
在觸發器中觸發語句與僞記錄變量的值
觸發語句		:old			     :new
Insert 		所有的字段都是null		將要插入的數據
Update 		更新以前該行的值	   更新以後的值
delete 		刪除以前該行的值	   所有的字段都輸null的

範例:判斷員工漲工資之後的工資的值一定要大於漲工資之前的工資 
create or replace trigger addsal4p  
	before update of sal on myemp   
		for each row begin   
			if :old.sal >= :new.sal then 
    	raise_application_error(-20002, '漲前的工資不能大於漲後的工資'); 
  	end if; 
  end;
調用
update myemp t set t.sal=t.sal-1;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章