Procedure Language 其實是Oracle對SQL語言的能力擴展,讓SQL語言擁有了if條件判斷,for循環等處理。java
1、PLSQL基本語法sql
1 DECLARE 2 -- 聲明部分 3 變量名 變量類型 := 初始值 4 變量名 emp.sal % TYPE -- 引用類型的變量 5 emp % rowtype -- 記錄型變量 6 BEGIN 7 -- 業務邏輯 8 END ;
一、變量的聲明與使用數據庫
1 -- 已知數據類型的賦值聲明 2 DECLARE 3 i NUMBER := 100 ; 4 BEGIN 5 -- 輸出語句至關於 System.out.print(); 6 dbms_output.put_line('Hello World!' || i) ; 7 END ; 8 9 -- 未知數據類型的類型聲明 10 -- 輸出7369的工資 11 12 DECLARE 13 vsal emp.sal % TYPE ; 14 BEGIN 15 -- 給變量賦值 16 SELECT sal INTO vsal FROM emp WHERE empno = 7369 ; 17 dbms_output.put_line(vsal) ; 18 END ; 19 20 -- 記錄型變量聲明與賦值 21 -- 輸出7369的全部信息 22 DECLARE 23 vrow emp % rowtype ; 24 BEGIN 25 SELECT * INTO vrow FROM emp WHERE empno = 7369 ; 26 dbms_output.put_line(vrow.empno||' '|| vrow.ename); 27 END ;
二、if條件判斷語法與使用app
1 -- 根據不一樣年齡輸出信息 2 DECLARE 3 -- 由客戶端輸入 4 age number := &aaa; 5 BEGIN 6 IF age <= 18 THEN 7 dbms_output.put_line('未成年人'); 8 ELSIF age > 18 AND age <= 24 THEN 9 dbms_output.put_line('年輕人'); 10 ELSIF age > 24 AND age < 48 THEN 11 dbms_output.put_line('中年人'); 12 ELSE 13 dbms_output.put_line('老年人'); 14 END IF; 15 END;
三、三種循環ide
1 /* 2 三種循環 3 for 變量名 in 起始值..結束值 loop 4 5 end loop; 6 ---------------------------------- 7 while 條件 loop 8 9 end loop; 10 ----------------------------------- 11 loop 12 exit when 退出的條件 13 循環體 14 end loop; 15 */ 16 17 -- for 循環 18 -- 輸出1-10 19 DECLARE 20 21 BEGIN 22 FOR i IN 1..10 LOOP 23 dbms_output.put_line(i); 24 END LOOP; 25 END; 26 -- 輸出10-1 27 DECLARE 28 29 BEGIN 30 FOR i IN REVERSE 1..10 LOOP 31 dbms_output.put_line(i); 32 END LOOP; 33 END; 34 35 -- while 循環 36 DECLARE 37 i NUMBER := 1; 38 BEGIN 39 WHILE i <= 10 loop 40 dbms_output.put_line(i); 41 i := i+1; 42 END LOOP; 43 END; 44 45 -- 簡單循環 46 DECLARE 47 i NUMBER := 1; 48 BEGIN 49 LOOP 50 EXIT WHEN i > 10; 51 dbms_output.put_line(i); 52 i := i+1; 53 END LOOP; 54 END;
2、遊標函數
一、遊標概述 oop
1.1 遊標: (光標/指針) 是對查詢結果集的封裝, 至關因而jdbc中的ResultSetfetch
1.2 語法:spa
1 -- 聲明遊標 2 CURSOR 遊標名 IS 查詢語句; 3 CURSOR 遊標名(參數名 參數類型) IS 查詢語句 WHERE 列名 = 參數名;
1.3 開發步驟:指針
1.打開遊標 open 遊標名
2.從遊標中提取數據:
fetch 遊標名 into 變量
遊標名%notfound 沒有數據
遊標名%found 找到數據
3.關閉遊標 close 遊標名
二、使用示例:
1 -- 無參 2 -- 輸出全部員工的信息 3 DECLARE 4 -- 聲明遊標 5 CURSOR vemps IS SELECT * FROM emp; 6 -- 聲明變量 7 vrow emp % rowtype; 8 BEGIN 9 --1. 打開遊標 10 open vemps; 11 --2. 提取數據 12 LOOP 13 FETCH vemps INTO vrow; 14 -- 判斷是否有數據 15 EXIT WHEN vemps % notfound; 16 -- 打印數據 17 dbms_output.put_line('姓名:'||vrow.ename||' 工資:'||vrow.sal); 18 END LOOP; 19 20 -- 關閉遊標 21 CLOSE vemps; 22 END; 23 ---------------------------------------------------------------- 24 -- for 變量遊標 25 DECLARE 26 -- 聲明遊標 27 CURSOR vemps IS SELECT * FROM emp; 28 -- 聲明記錄型變量 29 vrow emp % rowtype; 30 BEGIN 31 -- 循環遍歷遊標 32 FOR vrow IN vemps 33 LOOP 34 dbms_output.put_line('姓名:'||vrow.ename||' 工資:'||vrow.sal); 35 END LOOP; 36 END; 37 38 -- =============================================================== 39 -- 有參 40 -- 輸出指定部門的員工信息 41 DECLARE 42 -- 聲明遊標 43 CURSOR vemps(vdeptno NUMBER) IS SELECT * FROM emp WHERE deptno = vdeptno; 44 -- 聲明記錄型變量 45 vrow emp % rowtype; 46 BEGIN 47 -- 1. 打開遊標 48 OPEN vemps(20); 49 -- 2.循環遍歷遊標 50 LOOP 51 FETCH vemps into vrow; 52 EXIT when vemps % notfound; 53 -- 打印數據 54 dbms_output.put_line('姓名:'||vrow.ename||' 工資:'||vrow.sal); 55 END LOOP; 56 -- 3. 關閉遊標 57 CLOSE vemps; 58 END;
3、例外
一、例外概述
例外 (意外): 至關因而java異常
語法:
1 declare 2 聲明部分 3 begin 4 業務邏輯 5 exception 6 處理例外 7 when 例外1 then 8 9 when 例外2 then 10 11 when others then 12 13 end;
常見的系統的例外:
二、例外使用示例
1 DECLARE 2 i NUMBER; 3 vrow emp % rowtype; 4 BEGIN 5 -- i := 5/0; 6 -- i := 'aaa'; 7 -- select * into vrow from emp where empno = 1234566; 8 select * into vrow from emp; 9 EXCEPTION 10 WHEN too_many_rows THEN 11 dbms_output.put_line('查詢出多行記錄,可是賦值給了單行變量'); 12 WHEN no_data_found THEN 13 dbms_output.put_line('發生了沒有找到數據例外'); 14 WHEN value_error THEN 15 dbms_output.put_line('發生類型轉換的例外'); 16 WHEN zero_divide THEN 17 dbms_output.put_line('發生除零的例外'); 18 WHEN others THEN 19 dbms_output.put_line('發生未知的例外'); 20 END;
三、自定義例外
語法:
1 DECLARE 2 -- 聲明例外 3 例外名稱 EXCEPTION ; 4 BEGIN 5 -- 拋出例外 6 raise 例外名稱 ; 7 EXCEPTION 8 -- 捕獲例外 9 WHEN 例外名稱 THEN 10 .... 11 END ;
使用示例:
1 -- 查詢指定編號的員工,若沒有找到,則拋出自定義例外 2 DECLARE 3 -- 聲明遊標 4 CURSOR vemps IS SELECT * FROM emp WHERE empno = 1234 ; 5 -- 記錄型變量 6 vrow vemps % rowtype ; 7 -- 定義例外 8 no_emp_found EXCEPTION ; 9 BEGIN 10 --1.打開遊標 11 OPEN vemps ; 12 --2.提取記錄 13 FETCH vemps INTO vrow ; 14 -- 判斷是否有數據 15 IF vemps % notfound THEN 16 -- 拋出例外 17 raise no_emp_found ; 18 END IF ; 19 -- 關閉遊標 20 CLOSE vemps ; 21 EXCEPTION 22 WHEN no_emp_found THEN 23 dbms_output.put_line('沒有找到對應的員工') ; 24 END ;
4、存儲過程
一、概述
存儲過程: 其實是將一段已經編譯好的PLSQL代碼片段,封裝在數據庫中。
做用:
1. 提升執行效率
2. 提升代碼複用性
語法:
1 create [or replace] procedure 過程名稱[(參數1 in|out 參數類型,參數2 in|out 參數類型)] 2 is | as 3 -- 聲明 4 begin 5 -- 業務 6 end;
二、使用示例
1 -- 給指定員工漲薪,並打印漲薪前和漲薪後的工資 2 -- 員工編號 : 輸入參數 3 -- 漲多少 : 輸入參數 4 /* 5 1. 查詢當前工 6 2. 打印漲薪前工資 7 3. 漲工資 8 4. 打印漲薪後的工資 9 5. 提交數據 10 */ 11 create or replace procedure proc_updatesal(vempno in number,vcount in number) 12 is 13 -- 聲明變量記錄當前工資 14 vsal number; 15 begin 16 --1. 查詢當前工資 17 select sal into vsal from emp where empno=vempno; 18 --2. 打印漲薪前工資 19 dbms_output.put_line('漲薪前:'||vsal); 20 --3. 漲工資 21 update emp set sal=vsal+vcount where empno=vempno; 22 -- 4. 打印漲薪後的工資 23 dbms_output.put_line('漲薪後:'||(vsal+vcount)); 24 --5. 提交數據 25 commit; 26 end; 27 28 -- 調用存儲過程 29 -- 方式1: 30 call proc_update_sal(7369,100); 31 32 -- 方式2: 33 declare 34 35 begin 36 proc_updatesal(7369,100); 37 end; 38 39 s 40 -- 獲取指定編號員工的年薪 41 /* 42 編號: in 輸入 43 年薪: out 輸出 44 */ 45 create or replace procedure proc_getyearsal(vempno in number,vyearsal out number) 46 is 47 48 begin 49 select sal*12+nvl(comm,0) into vyearsal from emp where empno=vempno; 50 end; 51 52 -- plsql代碼片段中調用 53 declare 54 yearsal number; 55 begin 56 proc_getyearsal(7369,yearsal); 57 dbms_output.put_line(yearsal); 58 end; 59 60 61 -- 封裝存儲過程,輸出的是遊標類型, 全部員工 62 /* 63 sys_refcursor : 系統引用遊標 64 */ 65 create or replace procedure proc_getemps(vemps out sys_refcursor) 66 is 67 68 begin 69 -- 打開遊標, 誰調用誰關閉 70 open vemps for select * from emp; 71 end; 72 73 declare 74 vemps sys_refcursor; 75 vrow emp%rowtype; 76 begin 77 -- 調用存儲過程 78 proc_getemps(vemps); 79 80 loop 81 fetch vemps into vrow; 82 exit when vemps%notfound; 83 dbms_output.put_line(vrow.ename); 84 end loop; 85 -- 關閉遊標 86 close vemps; 87 end;
5、存儲函數
一、存儲函數概述
存儲函數: 其實是將一段已經編譯好的PLSQL代碼片段,封裝在數據庫中。
做用:
1. 提升執行效率
2. 提升代碼複用性
語法:
1 create [or replace] function 函數名稱(參數1 in|out 參數類型) return 返回類型 2 is 3 4 begin 5 6 end;
存儲過程和存儲函數:
1. 函數有返回值,過程沒有返回值
2. 函數能夠直接在SQL語句中使用,過程不能夠
3. 函數能實現的功能,過程能實現
4. 過程能實現的功能,函數也能實現
5. 函數和過程本質上沒有區別 一般狀況下,咱們本身開發封裝的是存儲過程
二、使用示例
1 -- 存儲函數:獲取年薪 2 create or replace function func_getyearsal(vempno number) return number 3 is 4 vyearsal number; 5 begin 6 select sal*12+nvl(comm,0) into vyearsal from emp where empno=vempno; 7 return vyearsal; 8 end; 9 10 -- 調用 11 declare 12 yearsal number; 13 begin 14 yearsal := func_getyearsal(7369); 15 dbms_output.put_line(yearsal); 16 end; 17 18 select emp.*,func_getyearsal(emp.empno) from emp;
6、觸發器
一、數據庫觸發器是一個與表相關的、存儲的PL/SQL程序。每當一個特定的數據操做語句(insert,update,delete)在指定的表上發出是,Oracle自動地執行觸發器中定義的語句序列。
二、做用:
三、語法:
1 CREATE [OR REPLACE] TRIGGER 觸發器名稱 2 {BEFORE | AFTER} 3 {INSERT | UPDATE | DELETE} 4 ON 表名 5 [ FOR EACH ROW [WHEN(條件)]] 6 DECLARE 7 .... 8 BEGIN 9 PLSQL塊 10 END 觸發器名;
四、觸發器的類型
五、使用示例
1 -- 若用戶向表中插入數據以後, 打印一句話 2 create or replace trigger tri_test1 3 after 4 insert 5 on emp 6 declare 7 8 begin 9 dbms_output.put_line('有人插入了....'); 10 end; 11 12 insert into emp(empno,ename) values(9527,'華安'); 13 -- 執行一條更新工資的語句 14 15 -- 週二老闆不在,不能辦理員工入職(不能向員工表中插入數據) 16 -- 觸發器 17 -- before insert 18 -- 判斷今天是不是週二 19 select trim(to_char(sysdate,'day')) from dual; 20 21 create or replace trigger tri_checkday 22 before 23 insert 24 on emp 25 declare 26 vday varchar2(20); 27 begin 28 -- 查詢當前周幾 29 select trim(to_char(sysdate,'day')) into vday from dual; 30 -- 判斷是否爲週二,若爲週二,則須要中斷插入操做 31 if vday = 'tuesday' then 32 -- -20000 - -20999 33 raise_application_error(-20001,'週二老闆不在,不能插入'); 34 end if; 35 end; 36 37 insert into emp(empno,ename) values(9527,'華安'); 38 39 select * from emp; 40 41 -- 語句級觸發器 42 create trigger tri_test3 43 before 44 update 45 on emp 46 declare 47 48 begin 49 dbms_output.put_line('語句級觸發器'); 50 end; 51 52 -- 行級觸發器 53 create or replace trigger tri_test4 54 before 55 update 56 on emp 57 for each row 58 declare 59 60 begin 61 dbms_output.put_line('行級觸發器,舊的工資:'||:old.sal||' 新的工資:'||:new.sal); 62 end; 63 64 update emp set sal=sal+100; 65 66 -- 6個月 ---> 人事 加薪 ---> 加10塊錢 ---> 老闆簽字 67 -- 校驗員工薪資 調整後的工資必定要 大於 薪資調整前的工資 68 -- 觸發器: before update on emp 69 -- 行級觸發器 70 create or replace trigger tri_checksal 71 before 72 update 73 on emp 74 for each row 75 declare 76 77 begin 78 -- 調整後的工資 <= 薪資調整前的工資 ,則中斷更新操做 79 -- :new.sal <= :old.sal 80 if :new.sal <= :old.sal then 81 raise_application_error(-20002,'坑爹的,降薪啦!'); 82 end if; 83 end; 84 85 update emp set sal=sal-100; 86 87 /* 88 使用觸發器模擬相似auto_increment功能 89 當用戶插入的時候,若爲sid爲null,則給sid賦值一個編號 90 */ 91 create table stu( 92 sid number primary key, 93 name varchar2(20) 94 ); 95 96 -- 建立一個序列 97 create sequence seq_stu; 98 99 -- 觸發器: before insert on stu 100 -- 行級觸發器 101 create or replace trigger tri_auto 102 before 103 insert 104 on stu 105 for each row 106 declare 107 108 begin 109 -- 從序列中查詢一個數字出來,賦值給sid 110 select seq_stu.nextval into :new.sid from dual; 111 end; 112 113 -- 一樣一張表,有時候本身指定id, 有時候須要數據庫自動生成id 114 insert into stu values(null,'zs'); 115 insert into stu values(4,'zs'); 116 select * from stu;