一、HELLO World
1.我的第一個PL/SQL程序
--打印Hello World
set serveroutput on
--打開輸出開關
declare
--PLSQL程序以declare開頭
--這裏是說明部分(變量、光標、例外等),本程序沒有
begin
--程序以begin開始,end;結束
--程序體
dbms_output.put_line('Hello World');
--dbms_output是一個程序包,這個程序包給我們提供了很多方法來使用
--準確的說,put_line()這個方法就是一個存儲過程,而這個存儲過程,可以接收一個參數
end;
/
-- /表示退出編輯環境並執行這個PLSQL程序
2.執行看看
3.使用SQL Plus查看程序包的結構
desc 程序包的名稱
二、到底什麼是PL/SQL?
Procedure Language/SQL,用中文來說就是過程化的SQL,它是Oracle數據庫對SQL語言過程化的擴展,過程化的擴展是指在SQL命令語言(增刪改查)中增加了過程化處理語句(如分支、循環等),使SQL語言具有過程處理的能力。PL/SQL是面向過程語言。
三、PL/SQL完整的程序結構
declare
說明部分
begin
語句序列
exception
例外處理語句
end;
/
接下來介紹每一部分具體的書寫方法。
四、說明部分
1.定義基本變量
2.數據類型:
char, varchar2, date, number, boolean, long
3.舉例
str char(15); –定義一個變量,變量的名字是str,類型是字符類型,長度是15位。
isnot boolean := true; –定義一個變量,變量的名字是isnot,類型是布爾類型,初始值是true。
num bunber(7,2); 定義一個變量,名字是num,是一個數字,並且有兩位的小數。
4.注意:
PL/SQL中變量的賦值是使用 := 而不是 =
PL/SQL中賦值的另一種方法是使用into關鍵字
5.在SQL Devloper中實戰一下
--使用基本變量類型
set serveroutput on
declare
--定義基本變量類型
--基本數據類型
pnum number(7,2);
--字符串變量
pstr varchar2(20);
--日期變量
pdate date;
begin
--賦值
pnum:=999;
pstr:='this is str';
pdate:=sysdate;
dbms_output.put_line(pnum);
dbms_output.put_line(pstr);
dbms_output.put_line(pdate);
--我們可以對變量進行運算
--計算明天的日期
dbms_output.put_line(pdate+1);
end;
/
四(補充)、兩種比較特殊的變量-引用型變量、記錄型變量
1.引用型變量
my_name emp.ename%type;
my_name是變量的名稱,emp.ename%type是my_name的類型。
emp是員工表,ename是員工姓名的列。
emp.ename%type的意思就是引用emp表的ename列的類型作爲我的變量的類型。
這樣做的好處是我不用知道你的類型,你的類型變了,因爲我是引用的你的類型,我的類型就會自己改變。
2.引用型變量的實戰
--引用型變量
set serveroutput on
declare
--定義引用型變量:查詢並打印7839的姓名和薪水
--pname varchar2(20);
--pmoney number;
pname emp.ename%type;
pmoney emp.sal%type;
begin
--得到7839的姓名和薪水
--PL/SQL中賦值的另一種方法是使用into關鍵字
select ename,sal into pname,pmoney from emp where empno = 7839;
dbms_output.put_line(pname||'的薪水是'||pmoney);
end;
/
3.記錄型變量
emp_rec emp%rowtype;
emp_rec是變量名,emp是表,rowtype表示行類型。
取表中一行的類型作爲emp_rec變量的類型,而我們知道表中的一行有多個數據(類型),我們就可以把emp_rec理解爲一個數組,數組中的每個元素,代表每一列。
使用:emp_rec.ename := ‘ADAMS’;
4.記錄型變量的實戰
--記錄型變量
set serveroutput on
declare
--定義記錄型變量:查詢並打印7839的姓名和薪水
emp_rec emp%rowtype;
--注意emp_rec代表的是一行的信息
begin
--得到一行的信息
select * into emp_rec from emp where empno = 7839;
dbms_output.put_line(emp_rec.ename||'的薪水是'||emp_rec.sal);
end;
/
五、IF語句
1.形式
IF 條件 THEN 語句1;
語句2;
END IF;
或者:
IF 條件 THEN 語句序列1;
ELSE 語句序列2;
END IF;
或者:
IF 條件 THEN 語句;
ELSIF 語句 THEN 語句;
ELSE 語句;
END IF;
2.實戰
--使用IF語句判斷用戶輸入的數字
--如何使用IF語句執行判斷
--如何PL/SQL接收一個鍵盤輸入(只要是從鍵盤輸入的都是一個字符串)
set serveroutput on
--使用accept接收一個鍵盤輸入(prompt是彈出提示)
--num是一個地址值,含義是在該地址上保存了輸入的值
accept num prompt '請輸入數字'
declare
pnum number := #
begin
--執行IF語句進行判斷
if pnum = 0 then dbms_output.put_line('輸入的是:0');
elsif pnum = 1 then dbms_output.put_line('輸入的是:1');
elsif pnum = 2 then dbms_output.put_line('輸入的是:2');
else dbms_output.put_line('輸入的是:其他');
end if;
end;
/
六、循環語句
1.格式
while total<=25000 loop
xxxxxx;
end loop;
或者
loop
exit when 條件
xxxx;
end loop;
或者
for i in 1..10 loop
語句序列;
end loop;
(這裏1..10表示的是1到10連續的數)
2.實戰
--循環
set serveroutput on
declare
pwhilenum number := 1;
ploopnum number :=1;
pfornum number :=1;
begin
--使用while循環打印1-10
while pwhilenum<=10 loop
dbms_output.put_line('使用while循環:'||pwhilenum);
pwhilenum := pwhilenum + 1;
end loop;
--使用loop循環打印1-10
loop
dbms_output.put_line('使用loop循環:'||ploopnum);
ploopnum := ploopnum + 1;
exit when ploopnum >= 11;
end loop;
--使用for循環打印1-10
for pfornum in 1..10 loop
dbms_output.put_line('使用for循環:'||pfornum);
end loop;
end;
/
3.注意
推薦使用第二種循環,第二種循環在控制光標的時候比較方便。
七、光標(cursor)
1.相當於一個結果集(Result Set)
2.定義
cursor 光標名 [可以帶參數] is select語句;
示例:
cursor c1 is select ename from emp;
3.使用光標
open c1; (打開光標,執行查詢,得到集合)
fetch c1 into pename; (q取一行到變量pename中)
close c1; (關閉光標,釋放資源)
4.圖解
我們可以用一個循環把光標中所有的信息取出來。
5.補充–光標的屬性
(1)%found %notfound
如果光標取到了值,光標的屬性%found就是true,否則就是false;%notfound相反。
(2)%isopen 判斷光標時候打開
(3)%rowcount 影響行數(不是光標的總行數,比如光標中一共有100行,我已經取走了10行,那麼%rowcount=10而不是100)
另外,默認的情況下,Oracle數據庫只允許在同一個會話中打開300個光標。(修改:alter system set open_cursors =400 scope = both;)
6.實戰
--使用光標查詢員工姓名和工資,並打印
set serveroutput on
declare
--定義一個光標
cursor c1 is select ename,sal from emp;
--爲上面這個光標定義對應的變量,方便以後使用
pname emp.ename%type;
psal emp.sal%type;
begin
--打開光標
open c1;
loop
--取一條記錄
fetch c1 into pname,psal;
--如果沒有取到,說明取完了,退出循環---光標屬性的使用
exit when c1%notfound;
dbms_output.put_line(pname||'的薪水是:'||psal);
end loop;
--關閉光標
close c1;
end;
/
6.補充–帶參數的光標
--帶參數的光標
--查詢某個部門中員工的姓名
set serveroutput on
declare
--定義帶參數的光標
cursor c1(dno number) is select ename from emp where deptno=dno;
pname emp.ename%type;
begin
--打開光標(帶參數)
open c1(10);
loop
fetch c1 into pname;
exit when c1%notfound;
dbms_output.put_line(pname);
end loop;
--關閉光標
close c1;
end;
/
八、PL/SQL的實際應用
給員工漲工資,總裁漲1000,經理漲800,其他漲400。
注意:Oracle數據庫默認開始事務,默認的事務級別是read committed。
--給員工漲工資,總裁漲1000,經理漲800,其他漲400
set serveroutput on
declare
--定義光標代表給哪些員工漲工資(表emp中的job列已事先重命名爲empjob)
cursor c1 is select empno,empjob from emp;
pno emp.empno%type;
pjob emp.empjob%type;
begin
--打開光標
open c1;
loop
fetch c1 into pno,pjob;
exit when c1%notfound;
--判斷員工職位
if pjob = 'PRESIDENT' then update emp set sal = sal + 1000 where empno = pno;
elsif pjob = 'MANAGER' then update emp set sal = sal +800 where empno = pno;
else update emp set sal = sal + 400 where empno = pno;
end if;
end loop;
--關閉光標
close c1;
--對於oracle數據庫默認的事務級別是read committed,所以在數據改變後一定要進行提交
commit;
end;
/
九、例外
1.例外是程序設計語言提供的一種功能,用來增強程序的健壯性和容錯性。
系統例外+自定義例外
2.系統例外
(1)No_data_found 沒有找到數據
(2)Too_many_rows select…..into語句匹配多個行
(3)Zero_Divide 被零除
(4)Value_error 算數或轉換錯誤
(5)Timeout_on_resource 在等待資源時發生超時
3.系統例外示例
--系統例外:no_data_found
set serveroutput on
declare
--定義一個變量
pname emp.ename%type;
begin
--查詢員工姓名
select ename into pname from emp where empno = 1234;
exception
--捕獲例外(注意這裏捕獲所有的例外,防止例外被拋給數據庫)
when no_data_found then dbms_output.put_line('沒有該員工');
when others then dbms_output.put_line('其他例外');
end;
/
4.自定義例外
定義變量,類型是exception。
使用raise拋出自定義例外