目錄
概述:
PL/SQL是過程化的結構查詢語言(Procedural Language/Structured Query Language),它可以彌補SQL語句的不足。
在PL/SQL中可以通過IF和LOOP語句控制程序的執行流程,並且可以定義變量,以便利用這些變量在語句之間傳遞數據信息。
PL/SQL是Oracle的專用語言,是對標準SQL語言的擴展,SQL語句可以嵌套在PL/SQL程序代碼中,將SQL的數據處理能力和PL/SQL的過程處理能力結合在一起。
什麼是PL/SQL?
PL/SQL塊的主要組成部分:
聲明部分、執行部分、異常處理部分。
格式:
說明:
注意規範:
標識符的命名規範
變量與數據類型
基本數據類型:Boolean、Binary_interger、Pls_interger、Number、Int、Char、Varchar2、Date、Long
詳細使用可自行查閱資料
聲明變量:
variable_name data_type [ [NOT NULL]:=default_value_expression]; --有初始值
variable_name data_type [ [NOT NULL] DEFAULT default_value_expression];--無初始值
NOT NULL表示變量不允許爲空
變量定義舉例:
SET SERVEROUTPUT ON --顯示結果
declare
v_name varchar2(8):=‘PJ’; --變量聲明
V_nowtime date:=sysdate;
begin
dbms_output.put_line(v_name); --顯示輸出
dbms_output.put_line(v_nowtime);
end;
/ --執行程序塊
注意:使用DBMS_OUTPUT包來顯示查詢結果或文本行時,需先執行SET SERVEROUTPUT ON語句。
標量變量
%TYPE變量
var_name emp.ename%type;
又如何從表中拿到數據放進變量中呢 格式:into 變量名
select ename into v_name
from emp
where empno=7369;
複合類型的變量
定義格式 :v_name recode_name;
select * into v_name from 表名 --將表裏面所有數據放入變量
自定義記錄類型 (類似於結構體定義)
聲明格式: type record_name is record(
字段名1 類型;
字段名2 類型;
.....
);
例:將emp表中工號爲7369的職工的姓名(ename)、工種(job)、工資(sal)輸出顯示。
條件語句
if...then(單分支)
if <expression1> then --expression1判斷條件
pl/sql_statement;--符合if條件後要執行的pl/qsl語句
end if;
if...then..else(雙分支)
if <expression1> then
pl/sql_statement1;
else
pl/sql_statement2;
end if;
if...then ...elsif(多分支)
if < expression1> then
pl/sql_statement1;
elsif < expression2> then ---注意這裏是elsif,和我們平常的習慣可能不同
pl/sql_statement2;
……
else
pl/sql_statement3;
end if;
case (不使用選擇器)
case
when expression 1 then pl/sql_statement1; --判斷每個when子句的條件
when expression 2 then pl/sql_statement2;
....
when expression n then pl/sql_statementn;
[else expression n+1 then pl/sql_statement;]
end;
case(使用選擇器)
case <selector>
when <expression1> then pl/sql_statement1; --獲取選擇器的值,和每個when子句進行比較判斷
when <expression 2> then pl/sql_statement2;
....
when <expression n> then pl/sql_statementn;
[else <expression n+1> then pl/sql_statement;]
end;
循環語句
LOOP循環
loop
statements;--循環體
exit when condition;--跳出判斷
end loop;
WHILE循環
while condition --適用於事先無法知道控制循環終止變量值的情況。
loop
statements;
end loop;
FOR循環
for loop_variable_name in [reverse] lower_bound..upper_bound
-- loop_variable_name 是指定循環計數器,可以使用已經有的,也可以使用一個新的。
-- 省略reverse,就是升序,不省略就是逆序。
-- for循環會自己,自增或自減1.不能在循環體裏動態的去改變loop_variable_name的值
loop
statements;
end loop;
遊標的使用
SQL 提供遊標機制來實現在程序設計語言中處理集合。
遊標的作用就相當於指針,通過遊標程序設計語言就可以一次處理查詢結果集中的一行。
在Oracle中,遊標可以分爲兩大類:靜態遊標和REF遊標。
隱式遊標
在執行一個SQL語句時,Oracle會自動創建一個隱式遊標。這個遊標是內存中處理該語句的工作區域,在其中存儲了執行SQL語句的結果。通過遊標的屬性可獲知SQL語句的執行結果,以及遊標的狀態信息
遊標的主要屬性:
當使用隱式遊標時,需要在前面加SQL(默認的遊標名)
cursor for loop語句:對SQL語句返回的結果集進行處理
for 遊標變量 in select語句
loop
DML操作
end loop;
顯式遊標
--定義遊標:
Cursor 遊標名 is select語句; --不帶參數的遊標
Cursor 遊標名(參數名1 類型名1,參數名2 類型名2,……) is select語句; --帶參數的遊標
--打開遊標
open 遊標名;
open 遊標名(實參值1,實參值2,……)
--提取遊標數據
fetch 遊標名 into 記錄變量名;
--關閉遊標。
close 遊標名;
舉例:
遊標for循環
遊標通常是與循環聯合使用。實際上,PL/SQL還提供了一種將兩者綜合在一起的語句,即遊標FOR循環語句。遊標FOR循環是顯式遊標的一種快捷使用方式,它使用FOR循環依次讀取結果集中的數據。當FOR循環開始時,遊標會自動打開(不需要使用OPEN方法),每循環一次系統自動讀取遊標當前行的數據(不需要使用FETCH),當退出FOR循環時,遊標被自動關閉(不需要使用CLOSE)
--在SCOTT模式下顯示工資排名前5的員工的編號、姓名和工資。
declare
cursor emp_cur is select empno,ename,sal from
(select empno,ename,sal from emp order by sal desc) where rownum<6;
begin
for i in emp_cur loop
dbms_output.put_line(i.empno|| ' ' || i.ename|| ' '|| i.sal);
end loop;
end;
/
異常處理
在編寫PL/SQL程序時,不可避免地會出現一些錯誤。在Oracle系統中使用異常來處理這些錯誤,這些異常都可以包括在PL/SQL程序的EXCEPTION塊中。Oracle系統提供了許多內置的異常,用戶也可以根據自己的需要定義異常
Oracle系統中的異常可以分爲3類:
預定義的異常:Oracle提供,用戶無需在程序中定義,由Oracle自動引發。
非預定義異常:數據庫本身不知道、不能控制的錯誤。需要用戶在程序中定義,然後由Oracle自動引發。
用戶定義的異常:違反了業務邏輯,程序員可以明確定義並引發。
預定義的異常
舉例:
使用SQLCODE、SQLERRM函數進行異常處理
非預定義異常
在一個異常產生、被捕獲並處理之前,它必須被定義。Oracle定義了幾千個異常,絕大多數只有錯誤編號和相關描述,僅僅命名了21個最常被用到的異常,即系統預定義異常。這些異常的名稱被儲存在STANDARD,UTL_FILE,DBMS_SQL這幾個系統包中。
使用pragma exception_init語句可以爲錯誤關聯一個名字
--已知Oracle中一錯誤代碼ORA-01400: 無法將 NULL 插入,
--請將該錯誤代碼與NULL_INSERT_ERROR進行關聯,並利用Scott模式下的表(
--例如,emp或dept)操作,舉例報出該錯誤。
declare
null_insert_error exception;
pragma exception_init(null_insert_error,-1400);
begin
insert into emp(empno) values(NULL);
exception
when null_insert_error then
dbms_output.put_line('無法將NULL插入');
end;
用戶定義的異常
程序開發人員可以根據具體的業務邏輯規則,自定義一個異常。這樣,當用戶操作違反了業備邏輯規則後,就引發一個自定義異常,從而中斷程序的正常執行,並轉到自定義的異常處理部分。
--定義異常處理
declare
異常名 exception;
--觸發異常處理
raise 異常名;
--處理異常,在exception,中處理
--自定義一個異常,在SCOTT模式下,如果查找到EMP表中的某一員工
--(員工編號由用戶任意輸入)的佣金(COMM字段)爲0時,則顯示自定義錯誤消息“該員工的佣金爲0”。
declare
v_sal emp.sal%type;
e_sal exception;
v_eno emp.empno%type:=&no;
begin
select sal into v_sal from emp where empno=v_eno;
if emp_cur.sal=0 then --觸發異常的邏輯判斷
raise e_sal;
exception
when e_sal then
dbms_output.put_line('該員工的佣金爲0!');
end;
/