1.什麼是pl/sql(Procedure Language & Structured Query Language):sql
pl/sql是一種高級數據庫程序設計語言,可以在各類環境下對oracle 進行訪問,可以高效的處理數據。數據庫
2.pl/sql結構編程
declareoracle
聲名部分ide
begin函數
執行部分oop
exception性能
異常處理部分fetch
end;優化
例1:輸入一個僱員號,得出該僱員號的名字,工做,薪水
declare v_emp emp%rowtype;--聲名變量接收值 begin --根據輸入條件,將emp表中符合條件全部列的數據into到v_emp表中 select * into v_emp from emp where empno = &輸入僱員號; --輸出,須要||拼接 dbms_output.put_line(v_emp.empno||','||v_emp.ename||','||v_emp.job||','||v_emp.sal); end;
3.變量類型
類型 |
子類 |
說 明 |
範 圍 |
ORACLE限制 |
CHAR |
Character String Rowid Nchar |
定長字符串
民族語言字符集 |
0à32767 可選,確省=1 |
2000 |
VARCHAR2 |
Varchar, String NVARCHAR2 |
可變字符串 民族語言字符集 |
0à32767 4000 |
4000 |
BINARY_INTEGER |
|
帶符號整數,爲整數計算優化性能 |
|
|
NUMBER(p,s) |
Dec Double precision Integer Int Numeric Real Small int |
小數, NUMBER 的子類型 高精度實數 整數, NUMBER 的子類型 整數, NUMBER 的子類型 與NUMBER等價 與NUMBER等價 整數, 比 integer 小 |
|
|
LONG |
|
變長字符串 |
0->2147483647 |
32,767字節 |
DATE |
|
日期型 |
公元前4712年1月1日至公元后4712年12月31日 |
|
BOOLEAN |
|
布爾型 |
TRUE, FALSE,NULL |
不使用 |
ROWID |
|
存放數據庫行號 |
|
|
UROWID |
|
通用行標識符,字符類型 |
|
|
|
|
|
|
|
3.1直接定義類型
v_job varchar2(20) --直接定義一個變長字符串類型,跟sql類型所有通用,上表列出了一些
3.2 type類型
簡單來講就是利用一個現成的表的一個列的類型
v_sal emp.sal%type --v_sal用的就是emp表的sal列一摸同樣的類型
3.3 rowtype 類型
爲了方便,將一個表的全部列的類型所有用於如今定義的表中 ,就能夠用這個
v_emp emp%rowtype --上面也用過
3.4記錄類型record
格式:
type 類型名 is record (
變量 數據類型,
...
);
變量名 類型名;--變量名是聲名的 類型名就是上面的記錄類型
DECLARE type rec is record( empno emp.empno%TYPE, ename emp.ename%TYPE, job varchar2(20) ); v rec; BEGIN SELECT empno,ename,job INTO v FROM emp WHERE empno = &EMPNO; dbms_output.put_line(v.empno||','||v.ename||','||v.job); END;
4.變量賦值
變量名 := 值 或 & 鍵盤輸入的值
例2: v_ename emp.ename%type := 'SMITH'; v_empno emp.empno%type := &僱員號; (若是輸入是字符串的話 須要改加 引號!)
5.begin執行塊操做
begin內能夠進行sql的增、刪、改、查的基本操做
declare v_emp emp%rowtype; begin --將emp值傳入v_emp select * into v_emp from emp where empno = &empno; --更新sal值,給該員工漲薪10% update emp set sal = v_emp.sal*1.1 where empno = v_emp.empno; --插入一個行,固然這個插入操做跟輸入的empno就沒啥關係啦 insert into emp (empno,sal) values(8888,2222); delete from emp where empno = v_emp.empno; dbms_output.put_line(v_emp.job||','||v_emp.sal); end;
5.1 execute immediate
declare --聲名一個變量保存sql語句 v_sql varchar2(255); --聲名一個rowtype類型變量保存員工信息 v emp%rowtype; begin v_sql:='select * from emp where empno=:1'; --打印sql語句 dbms_output.put_line(v_sql); --使用execute immediate 執行select語句 execute immediate v_sql into v using 7369; --打印員工信息 dbms_output.put_line(v.empno||','||v.ename||','||v.job||','||v.sal||','||v.deptno); end;
plsql中直接寫sql和使用execute immediate的區別:直接寫sql時,表名不能使用變量的值,
execute immediate:可使用變量裏保存的表名
若是數據庫中沒有表,那麼寫sql語句在建立存儲過程或者函數時,會直接報錯
execute immediate:中能夠執行的sql語句中的表,數據庫中是能夠沒有
6.流程控制語句
每種語言沒有流程控制就等於沒有靈魂,就算不上是個語言!
6.1 條件語句
1.if語句
條件判斷語句
語法:
if 條件表達式 then
plsql代碼;
end if;
條件表達式的寫法和在sql部分的條件表達式相同
語義:表示當前條件表達式成立進,執行then 和end if之間的語句
declare --聲名一個變量 v_n number(8):=&n; begin if v_n >10 then dbms_output.put_line(v_n); end if; end;
2.if else語句
語法:
if 條件表達式 then
plsql語句1;
else
plsql語句2;
end if;
語義:表示條件表達式成立時,執行第1個plsql語句,若是條件不成立執行第2個plsql語句
3.if elsif語句
語法:
if 條件表達式1 then
plsql語句;
elsif 條件表達式2 then
plsql語句;
...
else
plsql語句;
end if;
語義:表示當某個條件表達式成立時,執行相應then後面的plsql語句,若是全部條件不成立會執行else後面plsql語句,其中else部分能夠省略;
declare --聲名一個變量用來保存從鍵盤輸出的一個成績 score number(4,1):=&成績; begin --當成績小於60時輸出不及格,成績在60~70之間時輸出及格,成績在70~80之間輸出良好,成績在80~90之間輸出優秀,成績>90時輸出很是好 if score<60 then dbms_output.put_line('不及格'); elsif score<70 then dbms_output.put_line('及格'); elsif score<80 then dbms_output.put_line('良好'); elsif score<90 then dbms_output.put_line('優秀'); else dbms_output.put_line('很是好'); end if; end;
4.case when語句
語法1:
case
when 條件表達式 then
值;
when 條件表達式 then
值;
...
when 條件表達式 then
值;
else
默認值;
end [case];
--該方式跟if一個樣 declare --聲名一個變量用來保存從鍵盤輸出的一個成績 score number(4,1):=&成績; begin --當成績小於60時輸出不及格,成績在60~70之間時輸出及格,成績在70~80之間輸出良好,成績在80~90之間輸出優秀,成績>90時輸出很是好 case when score<60 then dbms_output.put_line('不及格'); when score<70 then dbms_output.put_line('及格'); when score<80 then dbms_output.put_line('良好'); when score<90 then dbms_output.put_line('優秀'); else dbms_output.put_line('很是好'); end case; end;
語法2:
case 表達式
when 值1 then
plsql代碼;
when 值2 then
plsql代碼;
...
else
plsql代碼;
end case;
--該種方式,表達式須要得出確切的結果才能夠用,這裏瞎舉個無心義的例子 declare v_empno emp.empno%type :=&empno; v_ename emp.ename%type; begin select empno,ename into v_empno,v_ename from emp where empno = v_empno; case v_empno when 7369 then dbms_output.put_line(v_ename); when 7499 then dbms_output.put_line(v_ename); when 7521 then dbms_output.put_line(v_ename); when 7566 then dbms_output.put_line(v_ename); when 7788 then dbms_output.put_line(v_ename);
end case; end;
5.loop循環
語法:
loop
循環體語句;
exit when 退出循環條件;
循環控制語句;
end loop;
--循環打印1~9 declare --聲名一個變量,做爲循環變量 n number(2); begin --給循環變量賦值初始值 n:=1; loop --循環體語句 dbms_output.put_line(n); --退出循環條件 exit when n=9; --循環控制語句 n:=n+1; end loop; end;
--循環9-1
declare --聲名一個變量,做爲循環變量 n number(2); begin --給循環變量賦值初始值 n:=9; loop --循環體語句 dbms_output.put_line(n); --退出循環條件 exit when n=1; --循環控制語句 n:=n-1; end loop; end;
6.while循環
語法:
while 循環條件 loop
循環體語句;
循環控制語句;
end loop;
--打印1~9 declare --聲名一個變量 n number(3); begin --給循環變量賦初始值 n:=1; while n<10 loop --循環體語句 dbms_output.put_line(n); --循環控制語句 n:=n+1; end loop; end;
while循環:先判斷循環條件,若是循環條件不成立就不會執行循環體,若是條件成立執行循環體和循環控制語句
7.for循環
語法1:
for 循環變量 in [reverse] 集合(連續數字集合|查詢語句|遊標變量) loop
循環體語句;
end loop;
循環變量:是不須要在declare中聲名的,除了遍歷數字集合(循環變量就是number類型)外,其它狀況下循環變量是一個記錄類型變量
數字集合的表示: 最小值..最大值
--打印1~9 begin for i in 1..9 loop dbms_output.put_line(i); end loop; end; --打印9~1 begin for i in reverse 1..9 loop dbms_output.put_line(i); end loop; end;
--打印10號門下全部員工的詳細信息 begin for v in (select * from emp where deptno=&dno) loop dbms_output.put_line(v.ename||','||v.job||','||v.sal||','||v.deptno); end loop; end;
for循環:它用來遍歷一個有限的集合(數字集合,select結果集,遊標等),它不須要控制循環變量和退出循環條件,只須要寫循環體就能夠。
loop循環:退出循環條件,先執行循環體後判斷退出條件
while循環:循環條件,先判斷循環條件後執行循環體
for循環:不須要聲名循環變量,不須要去控制循環條件和循環控制語句,遍歷一個有限集合
1.編寫一個程序塊,從emp表中顯示名爲「SMITH」的僱員的薪水和職位 DECLARE v_emp emp%ROWTYPE; BEGIN SELECT * INTO v_emp FROM emp WHERE lower(ename) = 'smith'; dbms_output.put_line(v_emp.sal||','||v_emp.job); END; 2.編寫一個程序塊,接受用戶輸入一個部門號,從dept表中顯示該部門的名稱與所在位置 DECLARE vdeptno dept.deptno%TYPE := &部門號; vloc dept.loc%TYPE; vdname dept.dname%TYPE; BEGIN SELECT loc,dname INTO vloc,vdname FROM dept WHERE deptno = vdeptno; dbms_output.put_line(vdname||','||vloc); END; 3.編寫一個程序塊,利用%type屬性,接受一個僱員號,從emp表中顯示該僱員的總體薪水(即,薪水加佣金) DECLARE vempno emp.empno%TYPE := &僱員號; vsal emp.sal%TYPE; BEGIN SELECT sal+NVL(comm,0) INTO vsal FROM emp WHERE empno = vempno; dbms_output.put_line(vsal); END; 4.編寫一個程序塊,利用%rowtype屬性,接受一個僱員號,從emp表中顯示該僱員的總體薪水 DECLARE vemp emp%ROWTYPE; wole emp.sal%TYPE; BEGIN SELECT * INTO vemp FROM emp WHERE empno = &僱員號; wole := vemp.sal+nvl(vemp.comm,0); dbms_output.put_line(wole); END; 5.某公司要根據僱員的職位來加薪,公司決定按下列加薪結構處理: Designation Raise ------------ -------- clerk 500 salseman 1000 analyst 1500 otherwise 2000 編寫一個程序塊,接受一個僱員名,從emp表中實現上述加薪處理 -- DECLARE vemp emp%ROWTYPE; BEGIN SELECT * INTO vemp FROM emp WHERE ename='&ename'; IF lower(vemp.job) = 'clerk' THEN UPDATE emp SET sal=sal+500 WHERE ename = vemp.ename; ELSIF lower(vemp.job)= 'salseman' THEN UPDATE emp SET sal=sal+1000 WHERE ename = vemp.ename; ELSIF lower(vemp.job)= 'analyst' THEN UPDATE emp SET sal=sal+1500 WHERE ename = vemp.ename; ELSE UPDATE emp SET sal=sal+2000 WHERE ename = vemp.ename ; END IF; END; ---- BEGIN FOR i IN (SELECT * FROM emp) LOOP IF lower(i.job) = 'clerk' THEN UPDATE emp SET sal=sal+500 WHERE empno = i.empno; ELSIF lower(i.job)= 'salseman' THEN UPDATE emp SET sal=sal+1000 WHERE empno = i.empno; ELSIF lower(i.job)= 'analyst' THEN UPDATE emp SET sal=sal+1500 WHERE empno = i.empno; ELSE UPDATE emp SET sal=sal+2000 WHERE empno = i.empno; END IF; END LOOP; END; 6.編寫一個程序塊,將emp表中僱員名所有顯示出來 BEGIN FOR I IN (SELECT * FROM EMP ) LOOP DBMS_OUTPUT.PUT_LINE(I.ENAME); END LOOP; END; 7.編寫一個程序塊,將emp表中前5人的名字顯示出來 ---1 BEGIN FOR I IN (SELECT * FROM emp WHERE ROWNUM <=5) LOOP dbms_output.put_line(I.ename); END LOOP; END; ----2 DECLARE N NUMBER(2):=0; BEGIN FOR I IN (SELECT * FROM emp) LOOP dbms_output.put_line(I.ename); N:=N+1; IF N =5 THEN RETURN; END IF; END LOOP; END; 8.接受兩個數相除而且顯示結果,若是第二個數爲0,則顯示消息「除數不能爲0」 DECLARE A FLOAT(20):=&輸入被除數; B FLOAT(20):=&輸入除數; C FLOAT(50); BEGIN IF B =0 THEN dbms_output.put_line('除數不能爲0'); RETURN; ELSE C:=A/B; DBMS_OUTPUT.PUT_LINE(C); END IF; END; 9、計算下面級數當末項小於0.001時的部分和。 1/(1*2)+1/(2*3)+1/(3*4)+…+1/(n*(n+1))+ …… DECLARE n NUMBER(20):=1; poi FLOAT(20):=0; BEGIN LOOP poi := poi+1/(n*(n+1)); EXIT WHEN 1/(n*(n+1))<0.001; n:=n+1; END LOOP; dbms_output.put_line(poi); END; 10、計算s=1*2+2*3+…+N*(N+1),當N=50的值。 DECLARE s NUMBER :=0; n NUMBER :=1; BEGIN LOOP s := s+N*(n+1); EXIT WHEN n = 50; n:=n+1; END LOOP; dbms_output.put_line(s); END; 11.編寫一個PL/SQL程序塊,從emp表中對名字以「A」或"S"開始的全部僱員按他們基本薪水的10%給他們加薪 DECLARE vemp emp%ROWTYPE; BEGIN FOR i IN (SELECT * INTO vemp FROM emp WHERE ename LIKE 'A%' OR ename LIKE 'S%') LOOP UPDATE emp SET sal = sal+sal*0.01; END LOOP; END; 12、兩重循環,計算S=1!+2!+…+10!。 --------for DECLARE s NUMBER :=0; n NUMBER :=1; BEGIN FOR i IN 1..10 LOOP n:=1;---初始值須要更改成1 FOR j IN 1..i LOOP n:=n*j; END LOOP; s:=s+n; END LOOP; dbms_output.put_line(s); END; -------loop DECLARE s NUMBER:=0; n NUMBER:=1; x NUMBER:=1; BEGIN LOOP x:=x*n; s:=s+x; EXIT WHEN n=10; n:=n+1; END LOOP; dbms_output.put_line(s); END; --------while DECLARE s NUMBER:=0; n NUMBER:=1; x NUMBER:=1; BEGIN WHILE n<=10 LOOP x:=x*n; s:=s+x; n:=n+1; END LOOP; dbms_output.put_line(s); END; 13.編程序求知足不等式 1+3^2+5^2+…+N^2>2000的最小N值。 DECLARE n NUMBER:=1; s NUMBER:=1; m NUMBER:=1; BEGIN LOOP s := s+n*n; EXIT WHEN s>2000; n:=n+2; m:=m+1; END LOOP; dbms_output.put_line(m); END; 14.將僱員表中的全部工資小於3000增長400,統計出增長工資的人數及增長的工資數量。 DECLARE vemp emp%ROWTYPE; m NUMBER:=0; total NUMBER :=0; BEGIN FOR i IN (SELECT * INTO vemp FROM emp WHERE sal<3000) LOOP i.sal := i.sal+400; UPDATE emp SET sal = i.sal WHERE ename = i.ename; dbms_output.put_line(i.ename||','||i.sal); m:=m+1; total:=total+400; END LOOP; dbms_output.put_line('增長工資總人數爲:'||m); dbms_output.put_line('增長總工資爲:'||total); END; ------------------ DECLARE n NUMBER(10):=0; BEGIN FOR i IN (SELECT * FROM emp WHERE sal<3000) LOOP UPDATE emp SET sal = sal+400 WHERE empno = i.empno; n:=n+1; END LOOP; dbms_output.put_line('人數:'||n||',總工資'||n*400); END; 15.從僱員表中顯示工資最高的前五我的的姓名,部門和工資。 DECLARE vemp emp%ROWTYPE; BEGIN FOR i IN (SELECT * INTO vemp FROM (SELECT * FROM emp ORDER BY sal DESC) WHERE ROWNUM<=5) LOOP dbms_output.put_line(i.ename||','||i.deptno||','||i.sal); END LOOP; END; 1-鍵盤接入兩個值,打印比較大的值 DECLARE a NUMBER:=&a; b NUMBER :=&b; BEGIN IF a > b THEN dbms_output.put_line(a); ELSE dbms_output.put_line(b); END IF ; END ; 2-鍵盤介入三個值,並按照從大到小依次打印 DECLARE a NUMBER :=&a; b NUMBER :=&b; c NUMBER :=&c; BEGIN IF a>b AND b>c THEN dbms_output.put_line(a||'>'||b||'>'||c); ELSIF a>c AND c>b THEN dbms_output.put_line(a||'>'||c||'>'||b); ELSIF b>a AND a>c THEN dbms_output.put_line(b||'>'||a||'>'||c); ELSIF b>c AND c>a THEN dbms_output.put_line(b||'>'||c||'>'||a); ELSIF c>a AND a>b THEN dbms_output.put_line(c||'>'||a||'>'||b); ELSIF c>b AND b>a THEN dbms_output.put_line(c||'>'||b||'>'||a); END IF; END ; 4-判斷一個年份是否是閏年 DECLARE YEAR NUMBER(4):=&年份; BEGIN IF mod(YEAR,4)=0 THEN IF MOD(YEAR ,100) !=0 THEN dbms_output.put_line(YEAR||'是閏年'); ELSIF MOD(YEAR,400)=0 THEN dbms_output.put_line(YEAR||'是閏年'); ELSE dbms_output.put_line(YEAR||'是平年'); END IF; ELSE dbms_output.put_line(YEAR||'是平年'); END IF; END; ------------------------- DECLARE YEAR NUMBER(4) :=&年份; BEGIN IF MOD(YEAR,4)=0 AND MOD(YEAR,100)!=0 OR MOD(YEAR,100)=0 AND MOD(YEAR,400)=0 THEN dbms_output.put_line(YEAR||'是閏年'); ELSE dbms_output.put_line(YEAR||'是平年'); END IF; END; 5-體質指數(BMI)=體重(kg)÷身高^2(m) 偏瘦 <= 18.4 正常 18.5 ~ 23.9 太重 24.0 ~ 27.9 肥胖 >= 28.0 現要求輸入體重和身高,求出體質指數所在範圍 DECLARE hight NUMBER:=&身高米; weight NUMBER:=&體重千克; bmi NUMBER; BEGIN bmi:=weight/(hight*hight); dbms_output.put_line(bmi); IF bmi<=18.4 THEN dbms_output.put_line('偏瘦'); ELSIF bmi<=23.9 THEN dbms_output.put_line('正常'); ELSIF bmi<=27.9 THEN dbms_output.put_line('太重'); ELSE dbms_output.put_line('肥胖'); END IF; END; 6-輸入一個數,判斷是奇數仍是偶數 DECLARE a NUMBER:=&整數; BEGIN IF MOD(a,2) = 0 THEN dbms_output.put_line(a||'是偶數'); else dbms_output.put_line(a||'是奇數'); END IF; END; 7-只含有一個未知數(一元),而且未知數項的最高次數是2(二次)的整式 方程叫作一元二次方程。標準形式爲:ax2+bx+c=0(a≠0)。 現輸入a b c三個值,求一元二次方程的解 注:平方根函數爲 SQRT DECLARE a NUMBER(5,1):=&a; b NUMBER(5,1):=&b; c NUMBER(5,1):=&c; x1 NUMBER(10,3); x2 NUMBER(10,3); BEGIN x1:=(-b+SQRT(b*b-4*a*c))/(2*a); x2:=(-b-SQRT(b*b-4*a*c))/(2*a); IF x1=x2 THEN dbms_output.put_line('x1='||x1); ELSE dbms_output.put_line('x1='||x1||','||'x2='||x2); END IF; END; 8-99乘法表 ----1..9 DECLARE n NUMBER:=1; s NUMBER:=0; x NUMBER; BEGIN FOR i IN 1..9 LOOP n:=i; FOR j IN 1..i LOOP x:=n*j; s:=x; dbms_output.put(j||'*'||n||'='||s||CHR(9)); END LOOP; dbms_output.new_line(); END LOOP; END; ---9..1 DECLARE n NUMBER:=1; s NUMBER:=0; x NUMBER; BEGIN FOR i IN REVERSE 1..9 LOOP n:=i; FOR j IN i..9 LOOP x:=n*j; s:=x; dbms_output.put(j||'*'||n||'='||s||' '); END LOOP; dbms_output.new_line(); END LOOP; END; ------- DECLARE n NUMBER:=1; s NUMBER:=0; x NUMBER; BEGIN FOR i IN REVERSE 1..9 LOOP n:=i; FOR j IN 1..i LOOP x:=n*j; s:=x; dbms_output.put(j||'*'||n||'='||s||' '); END LOOP; dbms_output.new_line(); END LOOP; END; ------------ DECLARE n NUMBER:=1; s NUMBER:=0; x NUMBER; BEGIN FOR i IN REVERSE 1..9 LOOP n:=i; FOR j IN REVERSE 1..i LOOP x:=n*j; s:=x; dbms_output.put(j||'*'||n||'='||s||' '); END LOOP; dbms_output.new_line(); END LOOP; END;
7.遊標
遊標比較簡單,主要就是定義cursor 而後在begin中open 遊標,用fetch into 傳個值,再用控制語句作一些事,最後close一下就行了
declare
cursor 遊標名 is select 語句;
變量 --聲名接收遊標值
begin
open 遊標名;
循環語句
fetch 遊標 into 變量;--這個根據循環語句的不一樣變換位置
結束循環;
close 遊標
end;
1、定義遊標:列出每一個員工的姓名、部門名稱並編程顯示第10個到第20個記錄。 ---loop----------- DECLARE --定義cursor CURSOR cur IS SELECT ename,dname FROM (SELECT ename,dname,ROWNUM r FROM (SELECT * FROM emp,dept WHERE emp.deptno = dept.deptno AND ROWNUM<=20)) WHERE r>=10; --定義接收變量 v_ename emp.ename%TYPE; v_dname dept.dname%TYPE; BEGIN --open 遊標 OPEN cur; --循環控制 LOOP --導入變量 FETCH cur INTO v_ename,v_dname; --控制器 EXIT WHEN cur%NOTFOUND; --循環體 dbms_output.put_line(v_ename||'-'||v_dname); --結束循環 END LOOP; --close cursor CLOSE cur; END; ------------------while------------------------ DECLARE CURSOR cur IS SELECT ename,dname FROM (SELECT ename,dname,ROWNUM r FROM (SELECT * FROM emp,dept WHERE emp.deptno = dept.deptno AND ROWNUM<=20)) WHERE r>=10; v_ename emp.ename%TYPE; v_dname dept.dname%TYPE; BEGIN OPEN cur; FETCH cur INTO v_ename,v_dname; --讓cur%found識別第一條記錄 WHILE cur%FOUND LOOP dbms_output.put_line(v_ename||'-'||v_dname); FETCH cur INTO v_ename,v_dname;---須要放在下面 END LOOP; CLOSE cur; END; ------------------for ------------------------------- DECLARE CURSOR cur IS SELECT ename,dname FROM (SELECT ename,dname,ROWNUM r FROM (SELECT * FROM emp,dept WHERE emp.deptno = dept.deptno AND ROWNUM<=20)) WHERE r>=10; BEGIN----for循環不用開啓遊標,直接循環 FOR i IN cur LOOP dbms_output.put_line(i.ename||'-'||i.dname); END LOOP; END; 2、定義遊標:從僱員表中顯示工資大於3000的記錄,只要姓名、部門編號和工資。編程顯示其中的奇數記錄。 --------------loop--------------- DECLARE --定義遊標 CURSOR cur IS SELECT ename,deptno,sal FROM emp WHERE sal>3000; --定義變量 v_emp emp%ROWTYPE; BEGIN --打開遊標 OPEN cur; ---先傳cur%rowcount初始值 FETCH cur INTO v_emp.ename,v_emp.deptno,v_emp.sal; --循環 LOOP FETCH cur INTO v_emp.ename,v_emp.deptno,v_emp.sal;---給變量傳值 IF mod(cur%ROWCOUNT,2)=1 THEN --判斷爲奇數時打印 dbms_output.put_line(v_emp.ename||','||v_emp.deptno||','||v_emp.sal); END IF; EXIT WHEN cur%NOTFOUND;---找不到時結束 END LOOP; --關閉遊標 CLOSE cur; END; -------------while---------------- DECLARE CURSOR cur IS SELECT ename,deptno,sal FROM emp WHERE sal>3000; v_emp emp%ROWTYPE; BEGIN OPEN cur; FETCH cur INTO v_emp.ename,v_emp.deptno,v_emp.sal;---賦予cur%rowcount初始值 WHILE cur%FOUND LOOP FETCH cur INTO v_emp.ename,v_emp.deptno,v_emp.sal; IF mod(cur%ROWCOUNT,2)=1 THEN --------判斷奇數 dbms_output.put_line(v_emp.ename||','||v_emp.deptno||','||v_emp.sal); END IF; END LOOP; CLOSE cur; END; -------------for-------------- DECLARE CURSOR cur IS SELECT ename,deptno,sal FROM emp WHERE sal>3000; v NUMBER(2):=1; BEGIN FOR i IN cur LOOP IF MOD(v,2)=1 THEN -------判斷奇數 dbms_output.put_line(i.ename||','||i.deptno||','||i.sal); v:=v+1; END IF; END LOOP; END; 3、用遊標顯示全部部門編號與名稱,以及其所擁有的員工人數。 ---------------------loop----------------- DECLARE --定義cursor CURSOR cur IS SELECT d.deptno,dname,COUNT(*) FROM emp e,dept d WHERE e.deptno=d.deptno GROUP BY d.deptno,dname; --定義變量 v_deptno dept.deptno%TYPE; v_dname dept.dname%TYPE; v_count NUMBER(10); BEGIN --打開遊標 OPEN cur; FETCH cur INTO v_deptno,v_dname,v_count; LOOP dbms_output.put_line(v_deptno||','||v_dname||','||v_count); FETCH cur INTO v_deptno,v_dname,v_count; EXIT WHEN cur%NOTFOUND; END LOOP; --關閉遊標 CLOSE cur; END; --------------------------------while----------------------- DECLARE --定義cursor CURSOR cur IS SELECT d.deptno,dname,COUNT(*) FROM emp e,dept d WHERE e.deptno=d.deptno GROUP BY d.deptno,dname; --定義變量 v_deptno dept.deptno%TYPE; v_dname dept.dname%TYPE; v_count NUMBER(10); BEGIN --打開遊標 OPEN cur; FETCH cur INTO v_deptno,v_dname,v_count; WHILE cur%FOUND LOOP dbms_output.put_line(v_deptno||','||v_dname||','||v_count); FETCH cur INTO v_deptno,v_dname,v_count; END LOOP; --關閉遊標 CLOSE cur; END; 4、用遊標屬性%rowcount實現輸出前十個員工的信息 --------------loop----------------- DECLARE --定義遊標 CURSOR cur IS SELECT * FROM emp; vemp emp%ROWTYPE; BEGIN --打開遊標 OPEN cur; --循環 LOOP --傳值 FETCH cur INTO vemp; IF cur%ROWCOUNT<=10 THEN ---判斷前十個並輸出 dbms_output.put_line(vemp.ename||','||vemp.empno||','||vemp.deptno||','||vemp.sal||','||vemp.comm); END IF; EXIT WHEN cur%NOTFOUND; END LOOP; --關閉遊標 CLOSE cur; END; -------------------------------while-------------------------- DECLARE --定義遊標 CURSOR cur IS SELECT * FROM emp; vemp emp%ROWTYPE; BEGIN --打開遊標 OPEN cur; --第一次傳值保證while 後判斷條件有值 FETCH cur INTO vemp; --循環 WHILE cur%FOUND loop IF cur%ROWCOUNT<=10 THEN ---判斷前十個並輸出 dbms_output.put_line(vemp.ename||','||vemp.empno||','||vemp.deptno||','||vemp.sal||','||vemp.comm); END IF; FETCH cur INTO vemp; -----while循環下必需要將傳值放在後面,讓第一次的遊標輸出 END LOOP; --關閉遊標 CLOSE cur; END; --------------------------for-------------------------- DECLARE CURSOR cur IS SELECT ename,empno,sal FROM emp; BEGIN OPEN cur; fe FOR i IN cur LOOP dbms_output.put_line(i.ename||','||i.empno||','||i.sal); END LOOP; END; 5、經過使用遊標來顯示dept表中的部門名稱,及其相應的員工列表(提示:可使用雙重循環)。 DECLARE CURSOR cur IS SELECT dname,e.ename FROM dept d LEFT JOIN emp e ON d.deptno = e.deptno; BEGIN FOR i IN cur LOOP dbms_output.put_line(i.dname||','||i.ename); END LOOP; END; 6、接受一個部門號,使用For循環,從emp表中顯示該部門的全部僱員的姓名,工做和薪水。 ----------------------for--------------------------- DECLARE CURSOR cur IS SELECT ename,job,sal FROM emp WHERE deptno = &部門號; BEGIN FOR i IN cur LOOP dbms_output.put_line(i.ename||','||i.job||','||i.sal); END LOOP; END; -----------------------loop----------------------- DECLARE CURSOR cur IS SELECT ename,job,sal FROM emp WHERE deptno = &部門號; vemp emp%ROWTYPE; BEGIN OPEN cur; LOOP FETCH cur INTO vemp.ename,vemp.job,vemp.sal; EXIT WHEN cur%NOTFOUND; dbms_output.put_line(vemp.ename||','||vemp.job||','||vemp.sal); END LOOP; CLOSE cur; END; -----------------------while-------------------------- DECLARE CURSOR cur IS SELECT ename,job,sal FROM emp WHERE deptno = &部門號; vemp emp%ROWTYPE; BEGIN OPEN cur; FETCH cur INTO vemp.ename,vemp.job,vemp.sal; WHILE cur%FOUND LOOP dbms_output.put_line(vemp.ename||','||vemp.job||','||vemp.sal); FETCH cur INTO vemp.ename,vemp.job,vemp.sal; END LOOP; CLOSE cur; END; 7、編寫一個程序塊,將emp表中前5人的名字,及其出的工資等級(salgrade)顯示出來。 ----------------loop---------------- DECLARE CURSOR cur IS SELECT ename,grade FROM emp e ,salgrade s WHERE sal BETWEEN losal AND hisal AND ROWNUM <=5; vname emp.ename%TYPE; vgrade salgrade.grade%TYPE; BEGIN OPEN cur; LOOP FETCH cur INTO vname,vgrade; EXIT WHEN cur%NOTFOUND; dbms_output.put_line(vname||','||vgrade); END LOOP; CLOSE cur; END; ----------------while---------------- DECLARE CURSOR cur IS SELECT ename,grade FROM emp e ,salgrade s WHERE sal BETWEEN losal AND hisal AND ROWNUM <=5; vname emp.ename%TYPE; vgrade salgrade.grade%TYPE; BEGIN OPEN cur; FETCH cur INTO vname,vgrade; WHILE cur%FOUND LOOP dbms_output.put_line(vname||','||vgrade); FETCH cur INTO vname,vgrade; END LOOP; CLOSE cur; END; -----------------for———————————————— DECLARE CURSOR cur IS SELECT ename,grade FROM emp e ,salgrade s WHERE sal BETWEEN losal AND hisal AND ROWNUM <=5; BEGIN FOR i IN cur LOOP dbms_output.put_line(i.ename||','||i.grade); END LOOP; END; -------------loop2 ---------------其餘一樣能夠用此種方法,很少寫了 DECLARE CURSOR cur IS SELECT ename,grade FROM emp e ,salgrade s WHERE sal BETWEEN losal AND hisal; vname emp.ename%TYPE; vgrade salgrade.grade%TYPE; BEGIN OPEN cur; LOOP FETCH cur INTO vname,vgrade; EXIT WHEN cur%NOTFOUND; IF cur%ROWCOUNT<=5 THEN ----------------其餘一樣能夠用此種方法 dbms_output.put_line(vname||','||vgrade); END IF; END LOOP; CLOSE cur; END; 8.emp表中對全部僱員按他們基本薪水的10%給他們加薪,若是所增長後的薪水大於5000,則取消加薪。 ---------------------loop------------------- DECLARE CURSOR cur IS SELECT empno,ename,sal FROM emp; vemp emp%ROWTYPE; BEGIN OPEN cur; LOOP FETCH cur INTO vemp.empno,vemp.ename,vemp.sal; EXIT WHEN cur%NOTFOUND; --判斷加10%以後是否超過5000,若是超過5000,則把元值賦給sal,不然加上基礎薪資的10% IF (vemp.sal+vemp.sal*0.1)>5000 THEN UPDATE emp SET sal = vemp.sal WHERE empno = vemp.empno; ELSE UPDATE emp SET sal = vemp.sal+vemp.sal*0.1 WHERE empno = vemp.empno; END IF; END LOOP; CLOSE cur; END; ---------------------------------while------------------------ DECLARE CURSOR cur IS SELECT empno,ename,sal FROM emp; vemp emp%ROWTYPE; BEGIN OPEN cur; FETCH cur INTO vemp.empno,vemp.ename,vemp.sal; WHILE cur%FOUND LOOP --判斷加10%以後是否超過5000,若是超過5000,則把元值賦給sal,不然加上基礎薪資的10% IF (vemp.sal+vemp.sal*0.1)>5000 THEN UPDATE emp SET sal = vemp.sal WHERE empno = vemp.empno; ELSE UPDATE emp SET sal = vemp.sal+vemp.sal*0.1 WHERE empno = vemp.empno; END IF; FETCH cur INTO vemp.empno,vemp.ename,vemp.sal; END LOOP; CLOSE cur; END; -----------------------for -------------------------------- DECLARE CURSOR cur IS SELECT empno,ename,sal FROM emp; vemp emp%ROWTYPE; BEGIN FOR i IN cur LOOP --判斷加10%以後是否超過5000,若是超過5000,則把元值賦給sal,不然加上基礎薪資的10% IF (i.sal+i.sal*0.1)>5000 THEN UPDATE emp SET sal = i.sal WHERE empno = i.empno; ELSE UPDATE emp SET sal = i.sal+i.sal*0.1 WHERE empno = i.empno; END IF; END LOOP; END; 9.按照salgrade表中的標準,給員工加薪,1:5%,2:4%,3:3%,4:2%,5:1%,並打印輸出每一個人,加薪先後的工資。 -----------------------loop--------------------其餘都同樣 很少寫了 DECLARE CURSOR cur IS SELECT empno,grade,sal FROM emp e,salgrade s WHERE e.sal BETWEEN losal AND hisal; vemp emp%ROWTYPE; vsal salgrade%ROWTYPE; newsal emp.sal%TYPE; --聲明一個newsal能接收新的sal值 BEGIN OPEN cur; LOOP FETCH cur INTO vemp.empno,vsal.grade,vemp.sal; EXIT WHEN cur%NOTFOUND; IF vsal.grade = 1 THEN -----判讀每種等級改增長多少 newsal:=vemp.sal+vemp.sal*0.05;---------------經過newsal來提供輸出的新sal ELSIF vsal.grade = 2 THEN newsal:=vemp.sal+vemp.sal*0.04; ELSIF vsal.grade = 3 THEN newsal:=vemp.sal+vemp.sal*0.03; ELSIF vsal.grade = 4 THEN newsal:=vemp.sal+vemp.sal*0.02; ELSIF vsal.grade = 5 THEN newsal:=vemp.sal+vemp.sal*0.01; END IF; UPDATE emp SET sal = newsal WHERE empno = vemp.empno; dbms_output.put_line(vemp.sal||','||newsal); END LOOP; CLOSE cur; END; 10、用遊標獲取全部收入超過2000的 salesman. -------------------------loop---------------1 DECLARE CURSOR cur IS SELECT ename,job,sal FROM emp WHERE job = 'SALESMAN' AND sal+NVL(comm,0)>2000; vemp emp%ROWTYPE; BEGIN OPEN cur; LOOP FETCH cur INTO vemp.ename,vemp.job,vemp.sal; EXIT WHEN cur%NOTFOUND; dbms_output.put_line(vemp.ename||','||vemp.job||','||vemp.sal); END LOOP; CLOSE cur; END; -----------------------------while -----------------2 DECLARE CURSOR cur IS SELECT ename,job,sal,comm FROM emp WHERE job = 'SALESMAN'; vemp emp%ROWTYPE; BEGIN OPEN cur; FETCH cur INTO vemp.ename,vemp.job,vemp.sal,vemp.comm; WHILE cur%FOUND LOOP IF vemp.sal+NVL(vemp.comm,0)>2000 THEN dbms_output.put_line(vemp.ename||','||vemp.job||','||vemp.sal); END IF; FETCH cur INTO vemp.ename,vemp.job,vemp.sal; END LOOP; CLOSE cur; END;