Oracle-PL/SQL編程語言
-
變量定義
declare 定義變量 begin 處理業務邏輯 end; -- 案例 -- 聲明方法 -- 賦值操作可以使用:=也可以使用into查詢語句賦值 declare -- 定義一個i 類型爲number(數字或小數)長度爲2 賦值爲10 i number(2) := 10; -- 定義一個s 類型varchar2(字符串)長度爲10 賦值爲'小明' s varchar2(10) := '小明'; -- 定義一個ena 類型是emp表下的ename列的類型長度也是 ena emp.ename%type; -- 引用型變量 -- 存放emp表中的一行記錄 emprow emp%rowtype; -- 記錄型變量 begin -- 輸出i的值 dbms_output.put_line(i); -- 輸出s的值 dbms_output.put_line(s); -- 把查詢出來的結果 賦值給ena (into 變量名) select ename into ena from emp where empno = 7788; -- 輸出ena的值 dbms_output.put_line(ena); -- 把查詢出來的結果 賦值給emprow (into 變量名) select * into emprow from emp where empno = 7788; -- 輸出emprow哪一行中的數據 (|| 輸出多個值得連接符) dbms_output.put_line(emprow.ename || '的工作爲: ' || emprow.job); end;
-
if判斷
declare 定義變量 begin if 判斷 then 邏輯代碼塊 elsif 判斷 then 邏輯代碼塊 else 邏輯代碼塊 end if; end; -- 案例 -- 輸入小於18的數字, 輸出未成年 -- 輸入大於18小於40的數字, 輸出中年人 -- 輸入大於40的數字, 輸出老年人 declare -- i的值是輸入的 (&後面隨便寫個字母單詞都行) i number(3) := &i; begin if i < 18 then dbms_output.put_line('未成年'); elsif i < 40 then dbms_output.put_line('中年人'); else dbms_output.put_line('老年人'); end if; end;
-
loop循環
-- while循環 declare 定義變量 begin while 判斷 loop 邏輯 end loop; end; -- exit循環 declare 定義變量 begin loop exit when 判斷; 邏輯 end loop; end; -- for循環 declare begin for 變量 in 範圍 loop 邏輯 end loop; end; -- 案例 -- 用三種方式輸出1到10的數字 -- where循環 declare i number(2) := 1; begin -- i 大於 10 時 退出循環 while i < 11 loop dbms_output.put_line(i); i := i + 1; end loop; end; -- exit循環 declare i number(2) := 1; begin loop -- i 大於 10 時 退出循環 exit when i > 10; dbms_output.put_line(i); i := i + 1; end loop; end; -- for循環 declare begin -- 循環1到10的值 for i in 1..10 loop dbms_output.put_line(i); end loop; end;
-
遊標
declare cursor 遊標名稱 is 結果集; 定義一個記錄型變量 begin open 遊標名稱; loop fetch 遊標名稱 into 記錄型變量; exit when 遊標名稱%notfound; 業務邏輯 end loop; close 遊標名稱; end; -- 案例 -- 遊標: 可以存放多個對象, 多行記錄. -- 輸出emp表中所有員工的姓名 declare -- 把emp表中的全部記錄, 存儲到c1遊標中 cursor c1 is select * from emp; -- 定義一個記錄型變量 emprow emp%rowtype; begin -- 打開遊標 open c1; loop -- 把c1中遍歷的每一行 都 賦值給emprow fetch c1 into emprow; -- 當它查不到的時候退出 exit when c1%notfound; -- 輸出名稱 dbms_output.put_line(emprow.ename); end loop; -- 關閉遊標 close c1; end; -- 給指定部門員工漲工資 declare -- 定義一個帶參數的遊標, 參數作爲條件 cursor c2(eno emp.deptno%type) is select empno from emp where deptno = eno; -- 定義一個引用型變量 en emp.empno%type; begin -- 注意:打開的時候, 必須賦值 open c2(10); loop -- 把c2中遍歷的每一行 都 賦值給en fetch c2 into en; -- 當它查不到的時候退出 exit when c2%notfound; -- 執行更新語句 update emp set sal = sal + 100 where empno = en; -- 提交事務 commit; end loop; close c2; end;
-
存儲過程的使用
-- 存儲過程 -- 存儲過程: 存儲過程就是提前已經編譯好的一段pl/sql語言, 放置在數據庫端, -- 可以直接被調用. 這一段pl/sql一般都是固定步驟的業務. create or replace procedure 方法名(參數) is begin 業務邏輯 end; -- 案例 -- 給指定員工漲100塊錢 create or replace procedure p1(eno emp.empno%type) -- 參數不寫in 或者 out 默認是in is begin update emp set sal = sal + 100 where empno = eno; commit; end; -- 測試p1 declare begin -- 調用方法 傳遞參數 p1(7788); end;
-
存儲函數
create or replace function f_yearsal(參數) return 返回值類型 is 定義變量 begin 邏輯 return 返回值; end; -- 案例 -- 通過存儲函數實現計算指定員工的年薪 -- 存儲過程和存儲函數的參數都不能帶長度 -- 存儲函數的返回值類型不能帶長度 create or replace function f_yearsal(eno emp.empno%type) return number is s number(10); begin select sal * 12 + nvl(comm, 0) into s from emp where empno = eno; return s; end; -- 測試f_yearsal -- 存儲函數在調用的時候, 返回值需要接收. declare s number(10); begin s := f_yearsal(7788); dbms_output.put_line(s); end;
-
out類型參數的講解
-- out類型參數如何使用 -- 使用存儲過程來算年薪 create or replace procedure p_yearsal(eno emp.empno%type, yearsal out number) is s number(10); c emp.comm%type; begin select sal * 12, nvl(comm, 0) into s, c from emp where empno = eno; yearsal := s + c; end; -- 測試p_yearsal declare yearsal number(10); begin p_yearsal(7788, yearsal); dbms_output.put_line(yearsal); end; -- in和out類型參數的區別是什麼? -- 凡是涉及到into查詢語句賦值或者:=賦值操作的參數, 都必須使用out來修飾.
-
存儲過程和存儲函數的區別
/* 存儲過程和存儲函數的區別 語法區別: 關鍵字不一樣. 存儲函數比存儲過程多了兩個return. 本質區別: 存儲函數有返回值, 存儲過程沒有返回值. 如果存儲過程想實現由返回值的業務, 我們就必須使用out類型的參數. 即便是存儲過程使用了out類型的參數, 其本質也不是真的有了返回值. 而是在存儲過程內部給out類型參數賦值, 在執行完畢後, 我們直接拿到輸出類型參數的值. */ -- 我們可以使用存儲函數有返回值的特性, 來自定義函數. -- 而存儲過程不能用來自定義函數. -- 案例需求: 查詢出員工姓名, 員工所在部門名稱. -- 使用傳統方式來實現案例需求 select e.ename, d.dname from emp e, dept d where e.deptno = d.deptno; -- 使用存儲函數來實現提供一個部門編號, 輸出一個部門名稱. create or replace function fdna(dno dept.deptno%type) return dept.dname%type is dna dept.dname%type; begin select dept.dname into dna from dept where deptno = dno; return dna; end; -- 使用fdna存儲函數來實現案例需求: 查詢出員工姓名, 員工所在部門名稱. select e.ename, fdna(e.deptno) from emp e;
-
觸發器案例
/* 觸發器, 就是制定一個規則, 在我們做增刪改操作的時候, 只需要滿足該規則, 自動觸發, 無需調用. 語句級觸發器: 不包含for each row的觸發器. 行級觸發器: 包含for each row的就是行級觸發器. 加for each row是爲了使用:old或者:new對象或者一行記錄. */ -- 語句觸發器 create or replace trigger 觸發器名稱 after -- 執行後觸發 操作 on 表名稱 declare begin 邏輯 end; -- 行級觸發器 create or replace trigger 觸發器名稱 before -- 執行前觸發 操作 on 表名稱 for each row declare begin 邏輯 end; -- 案例 -- 語句觸發器 -- 插入一條記錄, 輸出一個新員工入職 create or replace trigger t1 after -- 執行後觸發 insert -- insert操作 on person declare begin dbms_output.put_line('一個新員工入職'); end; -- 觸發t1 insert into person values(1, '小紅'); commit; -- 行級觸發器 -- 不能給員工降薪 -- raise_application_error(-20001~-20999之間, '錯誤提示信息'); create or replace trigger t2 before -- 執行前觸發 update -- update操作 on emp for each row declare begin -- 修改前的工資 大於 修改後的工資 if :old.sal > :new.sal then -- 拋異常 raise_application_error(-20001, '不能給員工降薪'); end if; end; -- 觸發t2 update emp set sal = sal - 1 where empno = 7788; commit;
-
使用觸發器實現主鍵自增
-- 觸發器實現主鍵自增. [行級觸發器] -- 分析: 在用戶做插入操作之前, 拿到即將插入的數據. -- 給該數據中的主鍵列賦值. create or replace trigger auid before insert on person for each row declare begin select s_person.nextval into :new.pid from dual; end; -- 使用auid實現主鍵自增 insert into person (pname) values ('小明'); commit;