PL/SQL程序基礎1

一.實驗目標

掌握PL/SQL程序的基本結構編程,具備如下能力:

1、針對數據庫應用領域的數據需求,設計出基於Oracle數據庫的解決方案的能力;

2、承擔Oracle數據庫系統的實施、運行與維護等基本工作的能力。

二.實驗項目

編寫存儲過程或存儲函數完成以下各題,存儲過程或函數依次命名爲obj2_1、obj2_2、…
以下1-7題與EMP、DEPT表有關。
如果沒有上述基本表,可以用下述SQL語句創建:

create table COUNTRIES as select * from univ.COUNTRIES;
create table DEPT as select * from univ.DEPT;
create table EMP as select * from univ.EMP;

1、輸出名爲SMITH的僱員的工資和職位。(存儲過程)

create or replace procedure obj2_1 as 
  vsal emp.sal%type; vjob emp.job%type;
begin
   select sal,job into vsal, vjob from emp 
   where ename='SMITH';
   dbms_output.put_line(vsal ||','|| vjob);
end;
.
/
set serveroutput on;
exec obj2_1;

2、傳送參數部門編號,輸出該部門名和地理位置。(存儲過程)

create or replace procedure obj2_2(z_deptno dept.deptno%type)
as  z_dname dept.dname%type;
    z_loc dept.loc%type;
begin
   select dname,loc
      into z_dname,z_loc
      from dept
      where deptno=z_deptno;
   dbms_output.put_line(z_dname||' '||z_loc);
end;
.
/
exec obj2_2(30)

3、傳送參數僱員號,輸出該僱員的工資和提成,沒有提成的用0替代。(用%type實現)。(存儲過程)

create or replace procedure obj2_3(v_empno emp.empno%type)
as  v_sal emp.empno%type;
    v_comm emp.comm%type;
begin
   select sal,nvl(comm,0)
      into v_sal,v_comm
      from emp
      where empno=v_empno;
   dbms_output.put_line(v_sal||' '||v_comm);
end;
.
/
set serveroutput on;
exec obj2_3(7369)

4、傳送參數僱員號,輸出該僱員的所有信息,沒有提成的用0替代。(用%rowtype實現)。(存儲過程)

create or replace procedure obj2_4(vempno emp.empno%type) as
      row_emp emp%rowtype;
    begin
     select empno, ename,job,mgr, hiredate,nvl(sal,0),nvl(comm,0),deptno
     into row_emp
 from emp
     where empno= vempno;
     dbms_output.put(row_emp.empno||','||row_emp.ename||',');
     dbms_output.put(row_emp.job||','||row_emp.mgr||',');
     dbms_output.put(row_emp.hiredate||','||row_emp.sal||',');
     dbms_output.put_line(row_emp.comm||','||row_emp.deptno);
   end;
.
/
set serveroutput on;
exec obj2_4(7369)

5、傳送參數僱員號,返回該僱員的工資。(存儲函數)

create or replace function obj2_5(v_empno emp.empno%type) 
  return integer as  v_sal emp.sal%type;
begin 
   select sal into v_sal from emp where empno=v_empno;
   return v_sal;
end;
.
/
select obj2_5(7369)from dual;

6、傳送參數僱員名或僱員編號,判斷他的job,根據job不同,爲他增加相應的sal(用if-elsif實現,不要改動到基本表emp,創建一個與emp表一模一樣的表emp1)。(存儲過程)
 Job     raise
 clerk    +500
 salesman +1000
 analyst  +1500
 otherwise +3000

create table emp1 as select * from emp;
create or replace
procedure obj2_6(vempno emp1.empno%type,vname emp1.ename%type) as
     vsal  emp1.sal%type; vjob emp1.job%type;
  begin
select sal,job into vsal,vjob from emp1 where empno=vempno or ename=vname;
  if vjob='CLERK' then vsal:=vsal+500;
  elsif vjob='SALESMAN' then vsal:=vsal+1000;
  elsif vjob='ANALYST' then vsal:=vsal+1500;
  else vsal:=vsal+3000;
  end if;
  update emp1 set sal=vsal where (vempno=empno) or (ename=vname);
  dbms_output.put_line(vname||'的工資已經更改爲:'||vsal);
end;
.
/
exec obj2_6(7369,'');
exec obj2_6('','SMITH');

7、傳送參數部門編號,按照下列加工資比例執行給該部門的僱員加工資(用CASE實現,修改emp1表的數據) (存儲過程)
 deptno raise(%)
 10   8%
 20   10%
 30   20%
 40   20%
加薪比例以現有的sal爲標準。

create or replace 
procedure obj2_7(vdeptno emp1.deptno%type) as
    begin
 case(vdeptno)
        when 10 then update emp1 set sal=sal*1.08 where deptno=vdeptno; 
        when 20 then update emp1 set sal=sal*1.18 where deptno=vdeptno;
        when 30 then update emp1 set sal=sal*1.20 where deptno=vdeptno;
        when 40 then update emp1 set sal=sal*1.20 where deptno=vdeptno;
      end case;
        dbms_output.put_line(vdeptno||'部門的加薪已完成');
end;
.
/
set serveroutput on;
exec obj2_7(20);

以下8-12題與以下表有關:學生、學費標準表、收費表、收費明細表。先從a_db模式中將這些表等複製到自己的模式中。

學生每學年開學前必須註冊。開始註冊前要初始化學生表,所有狀態爲“註冊”的學生的狀態設置爲空值,註冊後設置爲"註冊",還有“畢業”、“開除”、“休學”等狀態。註冊時在收費表生成相應記錄。學生每學年按學生所屬專業收取學費,交學費時產生收費明細記錄,並修改收費表中相應記錄。

create table 學生 as select * from a_db.學生;
create table 學費標準表 as select * from a_db.學費標準表;
create table 收費表 as select * from a_db.收費表;
create table 收費明細表 as select * from a_db.收費明細表;

8、在學生表中增加一列,用來記錄學生的密碼,寫一個PL/SQL程序,模擬登錄的過程。輸入學號和密碼,判斷是否正確,對於登錄成功和失敗分別給出提示信息。(存儲過程)
增加密碼列
alter table 學生 add 密碼 varchar2(12);
創建了學生表的密碼列,設置密碼爲666
update 學生 set 密碼 = ‘666’,

create or replace
procedure obj2_8(v_學號  學生.學號%type,v_密碼 學生.密碼%type) as
    vv_學號  學生.學號%type;
    vv_密碼 學生.密碼%type;
  begin
     select 學號,密碼 
     into vv_學號,vv_密碼
     from 學生
     where v_學號=學號 and v_密碼=密碼;
     dbms_output.put_line('登錄成功!');      
   exception
     when no_data_found then
      dbms_output.put_line('登陸失敗');     
end;

9、編寫一個向學費標準表添加記錄的過程。

create or replace
procedure obj2_9 (
   v_專業 學費標準表.專業%type,
   v_學年     學費標準表.學年%type,
   v_學費    學費標準表.學費%type) as
  begin
  insert into 學費標準表(專業, 學年, 學費)
         values (v_專業, v_學年, v_學費);
  dbms_output.put_line(v_專業||','||v_學年||','||v_學費||'添加完成');
  end;
.
/
exec obj2_9('計算機科學與技術','2017','13000');

10、編寫一個學生註冊的過程,註冊日期默認爲當天,以學號爲參數。

create or replace
procedure obj2_10(v學號  學生.學號%type) as
     begin
      insert into 學生(學號,註冊日期) values  (v學號,sysdate);
      update 學生 set 狀態='註冊' where 學號=v學號 and 狀態='null';
     dbms_output.put_line(v學號||'學生已在'|| to_char (sysdate,'yyyy-mm-dd')||'註冊成功');
     end;
.
/

11、編寫一個收學費的過程,收費日期默認爲當天,以學年、 學號、學費爲參數。

create or replace
procedure obj2_11(
  v_學年 收費明細表.學年%type,
  v_學號 收費明細表.學號%type,
  v_學費 收費明細表.學費%type) as
    begin
  insert into 收費明細表(學年,學號,學費)  values (v_學年, v_學號, v_學費);
  dbms_output.put_line('成功添加學生'||v_學號||'在'|| v_學年||'學年的付費記錄,共付款:'|| v_學費||'元');
  end;
.
/
exec obj2_11('2019','S101',1300);

12、編寫一個過程,輸出指定學年的欠費情況(含欠費人數、欠費總金額)。

create or replace
procedure obj2_12(
    v_學年     收費表.學年%type) as
    total  number(5);
    money  number(10);
  begin
    select count(學號),sum(應交學費-已交學費) a
    into total,money
    from 收費表
    where 學年=v_學年 and 應交學費>已交學費;
  dbms_output.put_line('欠費人數爲:'||total||'    欠費金額爲:'||money);  
  end;
.
/
exec obj2_12('2016');
select 學號,應交學費-已交學費 from 收費表 where 學年=2016 and 已交學費< 應交學費;

13、輸出如下九九乘法表。(存儲過程)

 create or replace procedure obj2_13
as
   i int;
   j int;
begin
   for i in 1..9 loop
      for j in 1..i loop
      dbms_output.put(i||'*'||j||'='||(i*j)||' ');
   end loop;
   dbms_output.put_line(' ');
   end loop;
end;
.
/
exec obj2_13        

三.實驗錯誤解決方案

問題一:創建的過程帶有編譯錯誤問題

1、問題的出現
在實驗項目2中創建“傳送參數部門編號,輸出該部門名和地理位置。(存儲過程)”,SQL語句如下:

create or replace
  procedure obj2_2 
  (vdeptno in DEPT.dept%type)
  as   
    vdname dept.dname%type;
    vloc dept.loc%type;
begin
   select dname,loc
   into vdname,vloc
   from dept
   where deptno= vdeptno;
   dbms_output.put_line(dname ||','|| loc);
end;

出現錯誤:
警告:創建的過程帶有編譯錯誤

2、問題分析

錯誤出現在第3行,表明“%type”定義數據類型有問題。使用由%TYPE定義的變量時要用“.”運算符指定表名限定詞,而且不用加“in”。但在第3行中由於C語言的語法干擾加了“in”,所以出錯。

3、解決方案
解決方案如下:

create or replace procedure obj2_2(z_deptno dept.deptno%type)
as  z_dname dept.dname%type;
    z_loc dept.loc%type;
begin
   select dname,loc
      into z_dname,z_loc
      from dept
      where deptno=z_deptno;
   dbms_output.put_line(z_dname||' '||z_loc);
end;
.
/
exec obj2_2(30)

執行該語句後,表已創建,問題解決。

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