Hello World
set serveroutput on; declare --說明部分 begin --程序 dbms_output.put_line('Hello World'); end; /
什么是PL/SQL?
- PL/SQL是Oracle對sql語言的過程化擴展
- 指在SQL命令語言中增加了過程處理語句(如分子、循環等),使SQL語言具有過程處理能力
把SQL語言的數據操縱能力與過程語言的數據處理能力結合起來,PLSQL面向過程但比過程語言簡單、高效、靈活和實用。
PL/SQL程序結構
declare 說明部分 (變量說明,光標申明,例外說明) begin 語句序列 (DML語句)... exception 例外處理語句 end; /
變量說明(char,varchar2,date,number,boolean,long)
varl char(15); //說明變量名,數據類型和長度后用分號結束說明語句
married boolean
:=true;
psal number(7,2);
my_name emp.ename%type; //引用型變量,即my_name的類型與emp表中ename列的類型一樣
emp_rec emp%rowtype; //記錄型變量
引用型變量:
--查詢7839姓名和薪水 set serveroutput on declare --定義變量保存姓名和薪水 --pname varcher2(20); --psal number; pname emp.ename%type; psal emp.sal%type; begin --into 賦值 注意查詢與賦值順序 select ename,sal into pname,psal from emp where empno=7839; --打印 dbms_output.put_line(pname||'的薪水是:'||psal); end; /
記錄型變量
--查詢7839姓名和薪水 set serveroutput on declare --定義記錄型變量,代表一行 emp_rec emp%rowtype; begin select * into emp_rec from emp where empno=7839; --打印 dbms_output.put_line(emp_rec.ename||'的薪水是:'||emp_rec.sal); end; /
if語句
if 條件 then 語句; elsif 語句 then 語句; end if;
判斷用戶從鍵盤輸入的數字:
--接收鍵盤輸入 set serveroutput on --num 是一個地址值,在該地址上保存了輸入的值的地址 accept num prompt '請輸入一個數字'; declare --定義變量保存輸入的數字 pnum number := # begin if pnum = 0 then dbms_output.put_line('您輸入的是0'); elsif pnum = 1 then dbms_output.put_line('您輸入的是1'); else dbms_output.put_line('其他數字'); end if; end; /
循環
loop exit[when 條件] ... end loop;
for i in 1..3 loop 語句序列; end loop;
打印1~10
--打印1~10 set serveroutput on declare pnum number :=1; begin loop exit when pnum>10; SYS.dbms_output.put_line(pnum); --pnum 每次+1 不能使用++ pnum := pnum + 1 ; end loop; end; /
光標(cursor)==resultset
說明光標語法:
cursor 光標[ (參數名 數據類型[,參數名 數據類型]...)]
is select 語句 ;
用於存儲一個查詢返回的多行數據
cursor c1 is select ename from emp ;
打開光標: open c1 ;(打開光標執行查詢)
取一行光標的值: fetch c1 into pename;(取一行到變量中)
關閉光標:close c1;(關閉光標釋放資源)
注意:上面的pename必須與emp表中的ename列類型一致;
--查詢並打印員工的姓名和薪水 /* 1、光標屬性 %isopen %rowcount(影響的行數) %found %notfound */ set serveroutput on declare --定義光標 cursor cemp is select ename,sal from emp; pename emp.ename%type; psal emp.sal%type; begin open cemp; loop --取一條記錄 fetch cemp into pename,psal; --退出條件 exit when cemp%notfound; SYS.dbms_output.put_line(pename||'的薪水是:'||psal); end loop; close cemp; end; /
給員工漲薪水:總裁PRESIDENT 漲1000,經理MANAGER漲800,普通員工漲400
--給員工漲薪水:總裁PRESIDENT 漲1000,經理MANAGER漲800,普通員工漲400 set serveroutput on declare cursor cemp is select empno,empjob from emp; pempno emp.empno%type; pjob emp.empjob%type; begin open cemp; loop --取出一條記錄 fetch cemp into pempno,pjob; exit when cemp%notfound; if pjob = 'PRESIDENT' then update emp set sal = sal+1000 where empno=pempno; elsif pjob = 'MANAGER' then update emp set sal = sal+800 where empno=pempno; else update emp set sal = sal+400 where empno=pempno; end if; end loop; --事務提交 close cemp; end; /
查詢某個部門的員工
--查找某個部門員工 set serveroutput on declare --定義光標保存某個部門的員工姓名 cursor cemp(dno number) is select ename from emp where deptno=dno; pname emp.ename%type; begin --光標傳實參部門id為10 open cemp(10); loop fetch cemp into pname; exit when cemp%notfound; SYS.dbms_output.put_line(pname); end loop; close cemp; end; /
例外:
java例外機制:向上拋,不處理,最終拋給虛擬機。
Oracel 的異常處理
系統定義例外
no_data_found :沒有找到數據
too_many_rows :select ...into語句匹配多個行
zero_divide:算術或轉換錯誤
timeout_on_resource:在等待資源時,發生超時
PLSQL中應該處理所有例外
--被0除 set serveroutput on declare pnum number; begin pnum :=1/0; exception when zero_divide then dbms_output.put_line('0不能被整除'); when others then dbms_output.put_line('其他例外'); end; /
自定義例外
--查詢50號部門的員工姓名 set serveroutput on declare cursor cemp is select ename from emp where deptno=50; pname emp.ename%type; --自定義例外 no_emp_found exception; begin open cemp; fetch cemp into pname; if cemp%notfound then --拋出異常 raise no_emp_found; end if; close cemp; exception when no_emp_found then dbms_output.put_line('沒有找到員工信息'); when others then dbms_output.put_line('其他例外'); end; /
統計每年入職的員工人數
--使用PLSQL統計每年入職的員工 /* SQL語句:select to_char(hiredate,'yyyy') from emp --> 光標--->循環 --->退出條件,notfound 變量:1、初始值;2、如何得到? count80 number :=0; .... */ set serveroutput on declare cursor cemp is select to_char(hiredate,'yyyy') from emp; phiredate varchar2(4); count80 number :=0; count81 number :=0; count82 number :=0; count87 number :=0; begin open cemp; loop --取出一個員工信息 fetch cemp into phiredate; exit when cemp%notfound; --判斷 if phiredate='1980' then count80 := count80+1; elsif phiredate='1981' then count81 := count81+1; elsif phiredate='1982' then count81 := count82+1; else count87 := count87+1; end if; end loop; close cemp; --輸出 SYS.dbms_output.put_line('1980:'||count80); SYS.dbms_output.put_line('1981:'||count81); SYS.dbms_output.put_line('1982:'||count82); SYS.dbms_output.put_line('1987:'||count87); end; /
使用PLSQL根據部門號統計各個部門員工薪水在3000以下、3000~6000、6000以上的人數,並計算各部門工資總額。將結果存入msg表中。
/* SQL語句 部門:select deptno from dept; --> 光標 部門中員工的薪水: select sal from emp where deptno=?? --> 帶參數的光標 變量:1. 初始值 2. 如何得到 每個段的人數 count1 number; count2 number; count3 number; 部門的工資總額: salTotal number; 1. select sum(sal) into salTotal from emp where deptno=?? 2. 累加 */ set serveroutput on declare --部門 cursor cdept is select deptno from dept; pdeptno dept.deptno%type; --部門中員工的薪水 cursor cemp(dno number) is select sal from emp where deptno=dno; psal emp.sal%type; --每個段的人數 count1 number; count2 number; count3 number; --部門的工資總額: salTotal number; begin open cdept; loop --取一個部門 fetch cdept into pdeptno; exit when cdept%notfound; --初始化 count1:=0;count2:=0;count3:=0; --得到部門的工資總額 select sum(sal) into salTotal from emp where deptno=pdeptno; --取部門中員工的薪水 open cemp(pdeptno); loop --取一個員工的薪水 fetch cemp into psal; exit when cemp%notfound; --判斷薪水的范圍 if psal < 3000 then count1:=count1+1; elsif psal>=3000 and psal<6000 then count2:=count2+1; else count3:=count3+1; end if; end loop; close cemp; --保存結果 insert into msg values(pdeptno,count1,count2,count3,nvl(salTotal,0)); end loop; close cdept; commit; dbms_output.put_line('完成'); end; /