Oracle數據庫基本操做(四) —— PLSQL編程

  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;

  常見的系統的例外:

    • zero_divide : 除零例外
    • value_error : 類型轉換
    • no_data_found : 沒有找到數據例外
    • too_many_rows : 查詢出多行記錄,可是賦值給了單行變量

二、例外使用示例

 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 觸發器名;

  四、觸發器的類型

  • 行級觸發器:一條SQL語句,影響了多少行記錄,觸發器就會執行多少次;
    • 兩個內置對象:
      • :new 新的記錄
      • :old 舊的記錄
  • 語句級觸發器:一條SQL語句,不管影響了多少行記錄,都只觸發一次;

  五、使用示例

 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; 
相關文章
相關標籤/搜索