PL/SQL程序基礎2
一.實驗目標
掌握較複雜的PL/SQL編程方法。具備如下能力:
- 針對數據庫應用領域的數據需求,設計出基於Oracle數據庫的解決方案的能力;
- 承擔Oracle數據庫系統的實施、運行與維護等基本工作的能力。
二.實驗項目
- 在A_DB模式中有一個表tan1(a),表中有若干個整數(不要管是否有重複)。
請編寫一個名爲obj4_1 的存儲函數(無參數),統計該表中有多少個數是素數,並作爲函數返回值返回。
create or replace
function obj4_1 return integer
as
m integer:=0;
is_prim boolean;
begin
for e in (select * from A_DB.tan1) loop
begin
is_prim:=true;
for j in 2..trunc(sqrt(e.a)) loop
if mod(e.a,j)=0 then
begin
is_prim:=false;
exit;
end;
end if;
end loop;
if is_prim then
m:=m+1;
end if;
end;
end loop;
return m;
end;
.
/
select obj4_1() 素數個數 from DUAL;
-
在A_DB模式中有一個表tan3(a),表中有若干個整數(不要管是否有重複),假設這些數表示年份。請編寫一個名爲obj4_2的存儲函數(無參數),統計該表中有多少個年份是閏年,並作爲函數返回值返回。說明:閏年的計算方法:被400整除,或被4整除而不能被100整除的年份爲閏年。說明:閏年的計算方法:被400整數,或被4整除而不能被100整除的年份爲閏年。
create or replace
function obj4_2 return integer
as
total INTEGER:=0;
BEGIN
For y in (select distinct(A_DB.TAN3.A) from A_DB.TAN3)loop
if mod(y.A,400)=0 or (mod(y.A,4)=0 and mod(y.A,100)!=0) then
total:=total+1;
DBMS_OUTPUT.put_line(y.A);
End if;
End loop;
Return total;
End;
.
/
select obj4_2 from dual; -
在A_DB模式中有一個表tanbn1(a,b)。
請編寫一個名爲obj4_3的存儲函數(無參數),對於表中所有三位數abc,將個位與百位數字交換,得到cba,求這些cba的和,並作爲函數返回值返回。
create or replace
function obj4_3 return integer
as
m integer:=0;
begin
for e in(select * from a_db.tanbn1) loop
if e.a>=100 and e.a<1000 then
m:=m+trunc(e.a/100)+mod(trunc(e.a/10),10)*10+mod(e.a,10)*100;
end if;
if e.b>=100 and e.b<1000 then
m:=m+trunc(e.b/100)+mod(trunc(e.b/10),10)*10+mod(e.b,10)*100;
end if;
end loop;
return m;
end;
.
/
select obj4_3 result from dual; -
對稱字符串。
在A_DB模式中有一個表tac1(a),表中有若干個字符串(不要管是否有重複)。
請編寫一個名爲obj4_4的存儲函數(無參數),統計該表中有多少對稱字符串,並作爲函數返回值返回。
說明:對稱字符串是正讀倒讀一樣的字符串。如:“abcdcba”、“6”和"123321"等前後對稱,是對稱字符串;而“12332”不是。
create or replace
function obj4_4 return integer as
m INTEGER:=0;
b number;
o number;
c varchar(2);
d varchar(2);
begin
for e in (select a from A_DB.tac1) loop
begin
b:=length(e.a);
o:=b;
for j in 1…b/2 loop
c:= substr(e.a, j, 1);
d:= substr(e.a, o, 1);
if c!=d then
exit;
end if;
o:=o-1;
end loop;
if o=b/2+1 or o=b/2 then
m:=m+1;
end if;
end;
end loop;
return m;
end;
.
/
select obj4_4() from dual; -
編寫一個名爲obj4_5的存儲過程,判斷正整數n是否是若干個連續的正整數之和。如是,則輸出這些連續的正整數;如果有多串連續的正整數,則輸出最長的那串連續的正整數。n是過程的參數。如:15=1+2+3+4+5,15=7+8,則輸出1,2,3,4,5。
create or replace
procedure obj4_5(n integer )
as
a integer;
b integer;
c integer;
d integer;
k integer;
begin
for c in 1…n-1 loop
for d in c+1…n loop
a:=c+d;
b:=d-c+1;
if n=a*b/2 then
for k in c…d loop
dbms_output.put(k||’ ');
end loop;
end if;
end loop;
end loop;
end;
.
/ -
編寫一個名爲obj4_6的存儲函數,判斷正整數n是否是若干個連續的正整數之和。如是,則返回1,否則返回0。n是函數的參數。
create or replace
function obj4_6 (n integer) return integer
as
a integer;
b integer;
c integer;
d integer;
k integer:=0;
begin
for c in 1…n-1 loop
for d in c+1…n loop
a:=c+d;
b:=d-c+1;
if n=a*b/2 then
k:=k+1;
end if;
end loop;
end loop;
if k!=0 then
return 1;
else
return k;
end if;
end;
.
/
select obj4_6(12) result from dual; -
在A_DB模式中有一個表tan2(a),表中有若干個整數(不要管是否有重複)。
請編寫一個名爲obj4_7的存儲函數(無參數),統計該表中有多少個數是若干個連續的正整數之和,並作爲函數返回值返回。要求調用第6題編寫的存儲函數f6(n)。
create or replace
function obj4_7 return integer
as
total integer:=0;
small integer;
begin
for e in(select * from a_db.tan2) loop
small:= obj4_6(e.a);
total:=total+small;
end loop;
return total;
end;
.
/
select obj4_7() from dual;
- 編寫一個名爲obj4_8的程序包,包中重載兩個過程,一個以員工號爲參數,輸出該員工信息;另一個以員工名爲參數,輸出員工信息。包中另一個過程利用兩個重載過程分別查詢員工號爲7902、7934、以及員工名爲SMITH、FORD的員工信息。
create or replace package obj4_8 as
procedure p1(vno emp.empno%type);
procedure p1(vname emp.ename%type);
procedure p2;
end;
create or replace
package body obj4_8 as
procedure p1(vno emp.empno%type)
as
vemp emp%rowtype;
begin
select * into vemp
from emp
where empno=vno;
dbms_output.put_line('姓名:'||vemp.ename||',職位:'||vemp.job||',管理者編號:'
||vemp.mgr||',僱傭日期:'||vemp.hiredate||',工資:'||vemp.sal||
',提成:'||nvl(vemp.comm,0)||',部門編號:'||vemp.deptno);
end p1;
procedure p1(vname emp.ename%type)
as
vemp emp%rowtype;
begin
select * into vemp from emp where ename=vname;
dbms_output.put_line('姓名:'||vemp.ename||',職位:'||vemp.job||
',管理者編號:'||vemp.mgr||',僱傭日期:'||vemp.hiredate||
',工資:'||vemp.sal||',提成:'||nvl(vemp.comm,0)||',部門編號:'||vemp.deptno);
end p1;
procedure p2
as
begin
obj4_8.p1('7902');
obj4_8.p1('7934');
obj4_8.p1('smith');
obj4_8.p1('ford');
end p2;
end;
.
/
- 在示例“5.二進制轉換爲十進制”的bit_to_number函數中特意用到了動態SQL與BIN_TO_NUM函數。請換一種方式實現相同的功能,該存儲函數命名爲obj4_9。
create or replace
function obj4_9 (v varchar2) return number
as
m integer;
total integer:=0;
i integer;
begin
i:=length(v);
for e in 0..i-1 loop
m:=to_number(substr(v,i-e,1))*2**e;
total:=total+m;
end loop;
return total;
end;
.
/
select obj4_9('11010000') from dual;
三.實驗錯誤解決方案
問題一: 函數創建成功,沒有輸出結果問題
1、問題的出現
在實驗項目9中創建“二進制轉換爲十進制”函數,SQL語句如下:
create or replace function obj4_9 (v varchar2)
return number
as
m integer;
t integer;
i integer;
begin
i:=length(v);
for e in 0..i-1 loop
m:=(substr(v,i-e,1))*2**e;
t:=t+m;
end loop;
return t;
end;
.
/
出現錯誤:
輸出結果與實際不相符
2、問題分析
通過分析與同學進行討論發現第5行定義變量t時沒有給變量賦初始值,所以出錯。
3、解決方案
解決方案如下:
create or replace
function obj4_9 (v varchar2) return number
as
m integer;
total integer:=0;
i integer;
begin
i:=length(v);
for e in 0..i-1 loop
m:=to_number(substr(v,i-e,1))*2**e;
total:=total+m;
end loop;
return total;
end;
.
/
select obj4_9('11010000') from dual;
執行該語句後,函數已創建,輸出結果與預期相符合,問題解決。