PL/SQL程序基礎2

一.實驗目標

掌握較複雜的PL/SQL編程方法。具備如下能力:

  1. 針對數據庫應用領域的數據需求,設計出基於Oracle數據庫的解決方案的能力;
  2. 承擔Oracle數據庫系統的實施、運行與維護等基本工作的能力。

二.實驗項目

  1. 在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;
  1. 在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;

  2. 在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;

  3. 對稱字符串。
    在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;

  4. 編寫一個名爲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;
    .
    /

  5. 編寫一個名爲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;

  6. 在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;
  1. 編寫一個名爲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;
.
/
  1. 在示例“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;

執行該語句後,函數已創建,輸出結果與預期相符合,問題解決。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章