一、涉及內容
游標的創建與應用
二、具體操作
(一)填空題
1.PL/SQL 程序塊主要包含3個部分:聲明部分、(執行部分 )、異常處理部分。
2.自定義異常必須使用(RAISE )語句引發。
(二)選擇題
1.下列哪一個不是BOOLEAN變量可能的取值?(D )
A.TRUE B.FALSE C.NULL D.BLANK
2.請查看以下IF語句:
Declare sal number:=500; comm number; Begin If sal <100 then Comm :=0; Elsif sal <600 then Comm: =sal*0.1; Else sal <1000 then Comm: =sal*0.15; Else Comm: =sal*0.2; End if; End;
在執行了以上語句之后,變量comm 的結果應是:(B )
A.0 B.50 C.75 D.100
3.在以下哪些語句中可以包含WHERE CURRENT OF 子句?(CE)
A.OPEN B.FETCH C.DELETE D.SELECT E.UPDATE F.CURSOR
4.在異常和oracle錯誤之間建立關聯時,應該在哪個部分完成?(A)
A.定義部分 B.執行部分 C.異常處理部分
5.只能存在一個值的變量是哪種變量?(B )
A.游標 B.標量變量 C.游標變量 D.記錄變量
(三)編程題
1.編寫程序計算並輸出1~100的和。
方案一:
語句:
Declare v_sum integer:=0; begin for i in 1..100 loop v_sum := v_sum+i; end loop; dbms_output.put_line(‘1~100的和為:’|| v_sum); end; /
截圖:
方案二:
語句:
Declare v_sum integer; begin v_sum := 100*101/2; dbms_output.put_line(‘1~100的和為:’|| v_sum); end; /
截圖:
2.分別使用顯式游標和隱式游標逐行輸出scott.emp表中的員工姓名和工資。
(一)使用顯式游標
語句:
DECLARE CURSOR emp_cursor01 IS SELECT ename,sal FROM scott.emp; emp_record emp_cursor01%ROWTYPE; BEGIN OPEN emp_cursor01 ; LOOP FETCH emp_cursor01 INTO emp_record; EXIT WHEN emp_cursor01%NOTFOUND; dbms_output.put_line('ename:'||emp_record.ename||',sal:'||emp_record.sal); END LOOP; dbms_output.put_line('row count:'||emp_cursor01%rowcount); CLOSE emp_cursor01; END;
截圖:
(二)使用隱式游標
語句:
BEGIN FOR emp_record IN (SELECT ename,sal FROM scott.emp) LOOP dbms_output.put_line('ename:'||emp_record.ename||',sal:'||emp_record.sal); END LOOP; END;
截圖:
(補充練習)
1、 創建一個表top_dogs,包含兩列:name varchar2(25) 和 salary NUMBER(11,2),用來存放員工姓名和工資。
語句:
create table top_dogs (name varchar2(25), salary NUMBER(11,2));
截圖:
2、創建一個PL/SQL塊,查詢出工資水平前n名的員工。具體要求如下:
(1)通過替代變量讀取n的值。
(2)通過循環從emp表中獲取工資在前n名的員工的姓名和工資
(3)將得到的員工姓名和工資寫入top_dogs表。
(4)如果有多名員工的工資相同,則每人都占n名中的一個名額。
(5)測試特殊情況,例如n=0或者n大於員工總數。
(6)每次向top_dogs 表中寫入數據前,先清空該表中的數據。
方案一:
語句:
DECLARE CURSOR emp_cursor(n number) IS SELECT ename,sal FROM scott.emp ORDER BY sal DESC; v_n integer := &n; BEGIN delete from top_dogs; FOR rec IN emp_cursor(v_n) LOOP IF emp_cursor%ROWCOUNT <=v_n THEN insert into top_dogs values(rec.ename,rec.sal); dbms_output.put_line('ename: '||rec.ename||' sal:'||rec.sal); ELSIF v_n<=0 or v_n>emp_cursor%ROWCOUNT then dbms_output.put_line('error!'); ELSE EXIT; --退出循環 END IF; END LOOP; END; /
截圖:
n=3以及n=4:
測試n=0以及n=100的情況:
方案二:
語句:
DECLARE CURSOR emp_cursor IS SELECT ename,sal FROM scott.emp ORDER BY sal DESC; v_n integer := &n; BEGIN delete from top_dogs; FOR rec IN emp_cursor LOOP Exit when emp_cursor%notfound; Exit when emp_cursor%ROWCOUNT>v_n; insert into top_dogs values(rec.ename,rec.sal); -- dbms_output.put_line('ename: '||rec.ename||' sal:'||rec.sal); END LOOP; END; /
截圖:
輸入n:2
輸入n:3
Select * from top_dogs
輸入n:0
Select * from top_dogs
輸入n:100
Select * from top_dogs
3、在上題的基礎上,如果員工工資相同(並列第幾名),需要將前n名的員工全部輸出。
語句:
DECLARE CURSOR emp_cursor IS SELECT ename,sal FROM scott.emp ORDER BY sal DESC; v_n integer := &n; v_sal scott.emp.sal%type; BEGIN delete from top_dogs; FOR rec IN emp_cursor LOOP Exit when emp_cursor%notfound; Exit when emp_cursor%ROWCOUNT>v_n and v_sal<>rec.sal; V_sal:= rec.sal; insert into top_dogs values(rec.ename,rec.sal); -- dbms_output.put_line('ename: '||rec.ename||' sal:'||rec.sal); END LOOP; END;
輸入n 的值:2
Select * from top_dogs
有三條記錄
截圖:
4、使用游標查詢dept表的部門編號和名稱,將其部門編號傳遞給另一個用於查詢emp表的游標(查詢emp表的員工姓名,工作,雇佣日期,工資)。
語句:
Declare Cursor dept_cur is select deptno,dname from scott.dept; Cursor emp_cur (c_deptno scott.emp.deptno%type) is select ename,job,hiredate,sal from scott.emp where deptno=c_deptno; Emp_rec emp_cur%rowtype; Begin For dept_rec in dept_cur Loop Open emp_cur(dept_rec.deptno); Loop Fetch emp_cur into Emp_rec; Exit when emp_cur%notfound; Dbms_output.put_line('ename:'|| Emp_rec.ename||' job:'|| Emp_rec.job||' hiredate:'|| Emp_rec.hiredate||' sal:'|| Emp_rec.sal); End loop; Close emp_cur; End loop; End; /
截圖:
5、為emp表增加一個列stars,類型為VARCHAR2(100)。使用游標更新stars列:創建一個PL/SQL塊,根據員工的工資計算他能獲得的星號“*”數量,每100美元獎勵一個星號,按四舍五入處理。並根據員工所獲得的星號數量n,形成由n個星號組成的字符串,寫入emp表的stars列。
(1)為emp表增加一個列stars,類型為VARCHAR2(100)。
(2)使用游標更新stars列:
語句:
Declare v_stars scott.emp.stars%type; v_num number:=0; Cursor c1 is select empno,sal,stars from scott.emp; Begin For emp_rec in c1 Loop v_stars:=''; exit when c1%notfound; v_num:=round(emp_rec.sal/100); for i in 1..v_num loop v_stars:= v_stars||'*'; end loop; update scott.emp set stars= v_stars where empno=emp_rec.empno; end loop; end;
截圖: