存储过程练习题

1.创建一个过程,能向DEPT表中添加一个新记录。(IN参数)
创建过程
CREATE OR REPLACE PROCEDURE SP_INSERT_DEPT(P_DEPTNO IN NUMBER, 
                                           P_DNAME IN VARCHAR2, 
                                           P_LOC IN VARCHAR2 )
IS
BEGIN
    INSERT INTO DEPT
    VALUES(P_DEPTNO,P_DNAME,P_LOC);
    COMMIT;
END;

/*
调用
BEGIN
    SP_INSERT_DEPT(79,'技术部','武汉');
END;
*/


CREATE OR REPLACE PROCEDURE SP_DEPT_HZH(P_DEPT_DEPTNO IN DEPT.DEPTNO%TYPE,
                                        P_DEPT_DNAME IN DEPT.DNAME%TYPE,
                                        P_DEPT_LOC  IN DEPT.LOC%TYPE)
IS
BEGIN
  INSERT INTO DEPT_H1 VALUES(P_DEPT_DEPTNO , P_DEPT_DNAME ,  P_DEPT_LOC ) ;
  COMMIT;
END;


DECLARE 
 V_DEPT_DEPTNO DEPT.DEPTNO%TYPE:=&部门编号;
 V_DEPT_DNAME  DEPT.DNAME%TYPE:=&部门名称;
 V_DEPT_LOC    DEPT.LOC%TYPE:=&部门所在地;
BEGIN
  SP_DEPT_HZH(V_DEPT_DEPTNO,V_DEPT_DNAME,V_DEPT_LOC);
END;


2.从EMP表中查询给定职工的职工姓名和工资。
 (提示:使用&来输入员工编号
   要求:利用OUT模式的参数将值传给调用者)
  创建过程
CREATE OR REPLACE PROCEDURE SP_SELECT_EMP( P_EMPNO IN EMP.EMPNO%TYPE,
                                        P_ENAME OUT EMP.ENAME%TYPE,
                                        P_SALARY OUT EMP.SAL%TYPE) 
IS
BEGIN
  SELECT ENAME,SAL INTO P_ENAME,P_SALARY FROM EMP WHERE EMPNO = P_EMPNO;
  DBMS_OUTPUT.PUT_LINE('员工姓名:'||P_ENAME||' 员工工资:'||P_SALARY);
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      DBMS_OUTPUT.PUT_LINE('该部门不存在!');
END;
/
调用
DECLARE
  V_NAME EMP.ENAME%TYPE;
  V_SALARY EMP.SAL%TYPE;
BEGIN
  SP_SELECT_EMP(&员工编号,V_NAME,V_SALARY);
END;
/
 

3.创建一个过程,在执行调用过程时,可随机输入EMP表中某个雇员的姓名,
  根据雇员的姓名,返回该雇员的薪水值,并输出(OUT参数)。
  创建过程
CREATE OR REPLACE PROCEDURE SP_SELECT_EMP2( P_ENAME IN EMP.ENAME%TYPE,
                                            P_SALARY OUT EMP.SAL%TYPE) 
IS
BEGIN
  SELECT SAL INTO P_SALARY FROM EMP WHERE ENAME = P_ENAME;
  EXCEPTION 
    WHEN NO_DATA_FOUND THEN
    P_SALARY:=0;
END;
/
调用
DECLARE
  V_SAL NUMBER(5);
BEGIN
  SP_SELECT_EMP2('&员工姓名',V_SAL);
  DBMS_OUTPUT.PUT_LINE(V_SAL);
END;
/

4.编写过程,实现交换两个变量的值的功能。并输出交换前和交换后的两个值(IN OUT参数)
  创建过程
CREATE OR REPLACE PROCEDURE SP_SWAP(P_NUM1 IN OUT NUMBER,
                                    P_NUM2 IN OUT NUMBER)
IS 
 V_Z NUMBER(5);
BEGIN
  V_Z:=P_NUM1;
  P_NUM1:=P_NUM2;
  P_NUM2:=V_Z;
END;
/
调用
DECLARE
  V_X NUMBER:=10;
  V_Y NUMBER:=20;
BEGIN
  DBMS_OUTPUT.PUT_LINE('交换前V_X和V_Y的值是:'||V_X||'  '||V_Y);
  SP_SWAP(V_X,V_Y);
  DBMS_OUTPUT.PUT_LINE('交换后V_X和V_Y的值是:'||V_X||'  '||V_Y);
END;
/
 

5.创建存储过程,根据员工编号删除EMP表中的相关记录
(提示:由调用语句提供的员工编号来删除记录,要求员工编号可随机输入)
 创建过程
CREATE OR REPLACE PROCEDURE SP_DELETE_EMP(P_EMPNO EMP.EMPNO%TYPE) 
IS
BEGIN
  DELETE FROM EMP WHERE EMPNO = P_EMPNO;
  COMMIT;
END;
/
调用
EXECUTE SP_DELETE_EMP('&员工编号');  -- COMMAND WINDOW
/

6. 创建存储过程:输入部门编号,
   输出EMP表中该部门所有职工的员工编号、姓名、工作岗位。
   创建过程
CREATE OR REPLACE PROCEDURE SELCET_CUREMP(P_DEPTNO IN EMP.DEPTNO%TYPE)
IS
  CURSOR C1 IS 
  SELECT EMPNO,ENAME,JOB 
    FROM EMP 
   WHERE DEPTNO = P_DEPTNO;
BEGIN
  FOR REC IN C1 LOOP
    DBMS_OUTPUT.PUT_LINE(REC.EMPNO||' '||REC.EMPNO||' '||REC.JOB);
  END LOOP;
END;
/
执行存储过程
EXECUTE SELCET_CUREMP(10);  -- COMMAND WINDOW
/

7.编写一个过程,指定一个员工编号与一个工资增加的百分比,
  使EMP表中将该员工的工资(SAL)增加输入的百分比。
  创建过程
CREATE OR REPLACE PROCEDURE SP_UP_SAL( P_EMPNO IN NUMBER, P_PARSENT IN FLOAT) 
IS
BEGIN
  UPDATE EMP SET SAL = SAL*(1+P_PARSENT) WHERE EMPNO = P_EMPNO;
END;
/
调用
BEGIN
  SP_UP_SAL(1234,0.5);
END;
/
  

8.创建函数,从EMP表中查询指定员工编号的职工的工资
CREATE OR REPLACE FUNCTION F_SELECT_SAL(P_EMPNO EMP.EMPNO%TYPE)
RETURN VARCHAR2
IS 
V_SALARY EMP.SAL%TYPE;
BEGIN
  SELECT SAL INTO V_SALARY FROM EMP WHERE EMPNO = P_EMPNO;   -- 注意在函数中,查询结果不为单行此处没有报错但是是有异常的!!!
  RETURN TO_CHAR(V_SALARY);
  EXCEPTION   -- 异常处理开始
       WHEN NO_DATA_FOUND THEN
         RETURN '没有该员工的信息或其工资为空!';

END;
/
调用函数有以下四种方式:
方式一:使用变量接收返回值
VAR V_SALARY NUMBER;
EXEC :V_SALARY:=F_SELECT_SAL(7369);
PRINT V_SALARY;
方式二:在SQL语句中直接调用函数
SELECT F_SELECT_SAL(7369) FROM DUAL;
方式三:使用DBMS_OUTPUT调用函数
EXEC DBMS_OUTPUT.PUT_LINE('工资是:'|| F_SELECT_SAL(7369));
方式四:在匿名PL/SQL块中调用函数(推荐使用该种方式-方便好记)
BEGIN
DBMS_OUTPUT.PUT_LINE('工资是:'|| F_SELECT_SAL(7369));
END;
/
 

9.创建函数,返回EMP表中指定职工的工资和姓名
(提示:返回值是两个,可用RETURN返回一个,另一个用OUT参数带回)
CREATE OR REPLACE FUNCTION F_SELECT_SAL_NAME(P_EMPNO IN EMP.EMPNO%TYPE,
                                             P_NAME OUT EMP.ENAME%TYPE) 
RETURN EMP.SAL%TYPE 
IS 
  V_SALARY EMP.SAL%TYPE;
BEGIN
  SELECT SAL, ENAME INTO V_SALARY,P_NAME FROM EMP WHERE EMPNO = P_EMPNO;
  RETURN V_SALARY;
END;
/
调用
DECLARE
  V_NAME EMP.ENAME%TYPE;
  V_SAL EMP.SAL%TYPE;
BEGIN
  V_SAL:=F_SELECT_SAL_NAME(7369,V_NAME);
  DBMS_OUTPUT.PUT_LINE(V_NAME||'的工资为'||V_SAL);
END;
/
 

10. 创建函数,根据给定的部门编号(提示: 利用&)计算该部门所有职工的平均工资。
CREATE OR REPLACE FUNCTION F_AVG_SAL(P_DEPTNO EMP.DEPTNO%TYPE) 
RETURN NUMBER 
IS
  V_AVGSAL NUMBER(7,2);
BEGIN
  SELECT AVG(SAL) INTO V_AVGSAL FROM EMP WHERE DEPTNO = P_DEPTNO;
  RETURN V_AVGSAL;
END;
/
调用
BEGIN
  DBMS_OUTPUT.PUT_LINE(F_AVG_SAL(&DEPTNO));
END;
/
 

11.创建函数,将EMP表中工资低于平均工资的职工工资加上200,并返回修改了工资的总人数.
CREATE OR REPLACE FUNCTION F_MODIFY 
RETURN NUMBER 
IS
BEGIN
 UPDATE EMP SET SAL=SAL+200 WHERE SAL<(SELECT AVG(SAL) FROM EMP);
 RETURN SQL%ROWCOUNT; 
/* sql%rowcount用于记录修改的条数,必须放在一个更新或者删除等修改类语句后面执行,
   select语句用于查询的话无法使用,
   当你执行多条修改语句时,按照sql%rowcount 之前执行的最后一条语句修改数为准。*/
END;
/
调用
BEGIN
  DBMS_OUTPUT.PUT_LINE(F_MODIFY);
END; 
/

CREATE OR REPLACE FUNCTION FT_EMP RETURN NUMBER IS
  V_CNT NUMBER;
  V_AVG NUMBER;
  PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  SELECT AVG(SAL) INTO V_AVG FROM TEMP_KIKI_EMP;
  SELECT COUNT(SAL) INTO V_CNT FROM TEMP_KIKI_EMP WHERE SAL < V_AVG;
  UPDATE TEMP_KIKI_EMP SET SAL = SAL + 200 WHERE SAL < V_AVG;
  COMMIT;
  RETURN V_CNT;
END;

12.创建一个函数,仅有一个形参,它接收调用函数中传递过来的实参--部门号,
   函数的返回值为该部门的一整条记录信息(注意:此处能够接收一整条记录的变量该怎么定义?)。
   要求在调用函数中输出该部门的部门名称与位置。
CREATE OR REPLACE FUNCTION F_FIND_DEPT(P_DEPTNO DEPT.DEPTNO%TYPE) 
RETURN DEPT%ROWTYPE
IS
  V_DEPT DEPT%ROWTYPE;
BEGIN
  SELECT * INTO V_DEPT FROM DEPT WHERE DEPTNO = P_DEPTNO;
  RETURN V_DEPT;
END;
/
调用
DECLARE
  V_DEPT DEPT%ROWTYPE;
BEGIN
  V_DEPT:=F_FIND_DEPT(30);
  DBMS_OUTPUT.PUT_LINE(V_DEPT.DNAME||'---'||V_DEPT.LOC);
END;
/


CREATE OR REPLACE FUNCTION JADE_12(P_DEPTNO JADE_EMP.DEPTNO%TYPE)
  RETURN SYS_REFCURSOR 
IS
  C_EMP SYS_REFCURSOR;
BEGIN
  OPEN C_EMP FOR
    SELECT * FROM JADE_DEPT WHERE DEPTNO = P_DEPTNO;
  RETURN C_EMP;
END JADE_12;
--直接调用,点击查看
SELECT jade_12(10) FROM dual;

18.基于表emp和dept 构造存储过程
--参数:P_ENAME   IN  VARCHAR2
        P_SALARY  IN  NUMBER
        P_JOB     OUT VARCHAR2
        P_DNAME   OUT VARCHAR2 
--先查找指定员工,如果查出多条记录,提示并异常退出;如果没有该名员工,提示并异常退出。 
--如果非上述情况,先判断该名员工的职位,如果职位不是'MANAGER',且要修改的薪水大于8000,拒绝修改并提示:“普通员工不能赚这么多薪水!”。 
--否则修改该名员工的薪水,提示:'修改薪水成功!'
--输出参数:该职员的职位,和所在部门的名字,并打印输出。
CREATE OR REPLACE PROCEDURE SP_EMP_DEPT(P_ENAME   IN VARCHAR2,
                                        P_SALARY  IN NUMBER,
                                        P_JOB   OUT VARCHAR2,
                                        P_DNAME OUT VARCHAR2)
IS
BEGIN
  SELECT E.JOB,D.DNAME
    INTO P_JOB,P_DNAME
    FROM EMP E
    JOIN DEPT D
      ON E.DEPTNO=D.DEPTNO
   WHERE E.ENAME=P_ENAME;
   IF P_JOB != 'MANAGER' AND P_SALARY>8000 THEN
      DBMS_OUTPUT.PUT_LINE('普通员工不能赚这么多薪水!');
   ELSE
      UPDATE EMP SET SAL=P_SALARY WHERE ENAME=P_ENAME;
      DBMS_OUTPUT.PUT_LINE('修改薪水成功!');
   END IF;
   DBMS_OUTPUT.PUT_LINE('职位: '|| P_JOB || ' 部门名称: '|| P_DNAME);

  -- 异常
  EXCEPTION
    WHEN TOO_MANY_ROWS THEN
      DBMS_OUTPUT.PUT_LINE('查出的值为多行,异常!');
    WHEN NO_DATA_FOUND THEN
      DBMS_OUTPUT.PUT_LINE('没有查出任何结果,异常!');
END;


DECLARE
  V_ENAME  VARCHAR2(100) :=&输入员工名称;
  V_SALARY NUMBER :=&输入修改后的薪水;
  V_JOB    VARCHAR2(100);
  V_DNAME  VARCHAR2(100);
BEGIN
  SP_EMP_DEPT(V_ENAME,V_SALARY,V_JOB,V_DNAME);
END;

--存储过程、函数练习题
 
--(1)创建一个存储过程,以员工号为参数,输出该员工的工资
create or replace procedure p_sxt1(v_empno in emp.empno%type, v_sal out emp.sal%type) is
begin
  select sal into v_sal from emp where empno = v_empno;
end;
--(1)执行
declare
  v_empno emp.empno%type := 7369;
  v_sal emp.sal%type;
begin
  p_sxt1(v_empno,v_sal);
  dbms_output.put_line(v_empno || ' 员工的工资为:' || v_sal);
end;
 
 
--(2)创建一个存储过程,以员工号为参数,修改该员工的工资。若该员工属于10号部门,
--则工资增加150;若属于20号部门,则工资增加200;若属于30号部门,则工资增加250;
--若属于其他部门,则增加300。
CREATE OR REPLACE PROCEDURE SP_STORE22(P_EMPNO IN MYTABLES.EMPNO%TYPE) IS
  P_DEPTNO MYTABLES.DEPTNO%TYPE;
BEGIN
  SELECT DEPTNO INTO P_DEPTNO FROM MYTABLES WHERE EMPNO = P_EMPNO;
  UPDATE EMP SET SAL = (CASE WHEN P_DEPTNO=10 THEN SAL+100 
                             WHEN P_DEPTNO=20 THEN SAL+150
                             WHEN P_DEPTNO=30 THEN SAL+250
                             ELSE SAL+300
                          END);     
END;

BEGIN
  SP_STORE22(7369);
END;

-- 或者
create or replace procedure p_sxt2(v_empno in emp.empno%type) is
  v_deptno emp.deptno%type;
  v_sal emp.sal%type;
begin
  select deptno into v_deptno from emp where empno = v_empno;
  select sal into v_sal from emp where empno = v_empno;
  dbms_output.put_line(v_empno || ' 的部门是 ' || v_deptno || ' 修改前的工资是 ' || v_sal);
  
  case v_deptno
  when 10 then
    update emp set sal = sal + 150 where empno = v_empno;
  when 20 then
    update emp set sal = sal + 200 where empno = v_empno;
  when 30 then
    update emp set sal = sal + 250 where empno = v_empno;
  else
    update emp set sal = sal + 300 where empno = v_empno;
  end case;
  
  select sal into v_sal from emp where empno = v_empno;
  dbms_output.put_line(v_empno || ' 的部门是 ' || v_deptno || ' 修改后的工资是 ' || v_sal);
  commit;
end;
--(2)执行
begin
  p_sxt2(7369);
end;
 
 
--(3)创建一个存储过程,以员工号为参数,返回该员工的工作年限(以参数形式返回)。
create or replace procedure p_sxt3(v_empno in emp.empno%type, v_year out number) is
begin
  select round((sysdate - hiredate)/365,1) into v_year from emp where empno = v_empno;
end;
--(3)执行
declare
  v_empno emp.empno%type := 7369;
  v_year number;
begin
  p_sxt3(v_empno,v_year);
  dbms_output.put_line(v_empno || ' 工作年限为 ' || v_year || '年');
end;
 
 
--(4)创建一个存储过程,以部门号为参数,输出入职日期最早的10个员工信息。
create or replace procedure p_sxt4(v_deptno emp.deptno%type) is
  cursor c_emp is select * from emp where deptno = v_deptno order by hiredate;
  v_times number := 0;
begin
  for v_emp in c_emp loop
    v_times := v_times + 1;
    dbms_output.put_line(v_emp.empno || '**' || v_emp.ename || '**' || to_char(v_emp.hiredate,'yyyy-mm-dd'));
    if v_times = 10 then
      exit;
    end if;
  end loop;
end;
--(4)执行
begin
  p_sxt4(20);
end;
 
 
--(5)创建一个函数,以员工号为参数,返回该员工的工资。
create or replace function f_sxt5(v_empno emp.empno%type) return emp.sal%type is
  vr_sal emp.sal%type;
begin
  select sal into vr_sal from emp where empno = v_empno;
  return vr_sal;
end;
--(5)执行
select f_sxt5(7369)||'元' 工资 from dual;
 
 
--(6)创建一个函数,以部门号为参数,返回该部门的平均工资。
create or replace function f_sxt6(v_deptno emp.deptno%type) return emp.sal%type is
  vr_sal emp.sal%type;
begin
  select avg(sal) into vr_sal from emp where deptno = v_deptno;
  return vr_sal;
end;
--(6)执行
select f_sxt6(20) 部门平均工资 from dual;
 
 
--(7)创建一个函数,以员工号为参数,返回该员工所在的部门的平均工资。
create or replace function f_sxt7(v_empno emp.empno%type) return emp.sal%type is
  vr_sal emp.sal%type;
begin
  select avg(sal) into vr_sal from emp where deptno = (select deptno from emp where empno = v_empno);
  return vr_sal;
end;
--(7)执行
select  f_sxt7(7369) from dual;
 
 
--(8)创建一个存储过程,以员工号和部门号作为参数,修改员工所在的部门为所输入的部门号。
--如果修改成功,则显示“员工由……号部门调入调入……号部门”;如果不存在该员工,则显示
--“员工号不存在,请输入正确的员工号。”;如果不存在该部门,则显示
--“该部门不存在,请输入正确的部门号。”。
CREATE OR REPLACE PROCEDURE SP_5(P_EMPNO  EMP.EMPNO%TYPE ,
                                 P_DEPTNO   DEPT.DEPTNO%TYPE)     
 IS
 CURSOR C_X IS (SELECT F.DEPTNO , E.EMPNO
  FROM DEPT F
  LEFT JOIN EMP E   
  ON  F.DEPTNO =  E.DEPTNO ) ;
 V_OLD  DEPT.DEPTNO%TYPE;
 V_1 NUMBER  :=0;
 V_2 NUMBER   :=0;

BEGIN
  FOR V_X IN C_X LOOP
    IF P_EMPNO = V_X.EMPNO THEN
      V_1 := V_1 + 1;
    ELSIF P_DEPTNO = V_X.DEPTNO THEN
      V_2 := V_2 + 1;
    END IF;
  END LOOP;
  IF V_1 > 0 AND V_2 = 0 THEN
    DBMS_OUTPUT.PUT_LINE('该部门不存在,请输入正确的部门号。');
  ELSIF V_1 = 0 AND V_2 > 0 THEN
    DBMS_OUTPUT.PUT_LINE('员工号不存在,请输入正确的员工号。');
  ELSIF V_1 > 0 AND V_2 > 0 THEN
    SELECT DEPTNO INTO V_OLD FROM EMP WHERE EMPNO = P_EMPNO;
    UPDATE EMP SET DEPTNO = P_DEPTNO WHERE EMPNO = P_EMPNO;
    IF V_OLD=P_DEPTNO THEN
      DBMS_OUTPUT.PUT_LINE('员工' || P_EMPNO || '调入的部门和原部门相同都为:'||V_OLD||'号部门');
    ELSE  
      DBMS_OUTPUT.PUT_LINE('员工' || P_EMPNO || '由' || V_OLD || '号部门调入调入' ||
                         P_DEPTNO || '号部门');
    END IF;
  ELSE 
    DBMS_OUTPUT.PUT_LINE('员工号不存在,部门号也不存在。');
  END IF;
END;


BEGIN
  SP_5(7344,40);
END;
 
 
--(9)创建一个存储过程,以一个整数为参数,输入工资最高的前几个(参数值)员工的信息。
create or replace procedure p_sxt15(v_number in number) is
  cursor c_emp is select * from emp order by sal desc;
  v_n number := 0;
begin
  for v_emp in c_emp loop
    v_n := v_n + 1;
    dbms_output.put_line(v_n || ' - ' || v_emp.ename || ' - ' || v_emp.sal);
    if v_n = v_number then
      exit;
    end if;
  end loop;
end;
--(9)执行
begin
  p_sxt15(5);
end;
 
 
--(10)创建一个存储过程,以两个整数为参数,输出工资排序在两个参数之间的员工信息。
create or replace procedure p_sxt16(v_up in number,v_down in number) is
  cursor c_emp is select * from emp order by sal desc;
  v_n number := 0;
begin
  for v_emp in c_emp loop
    v_n := v_n + 1;
    if v_n >= v_up and v_n <= v_down then
      dbms_output.put_line(v_n || ' - ' || v_emp.ename || ' - ' || v_emp.sal);
    end if;
  end loop;
end;
--(10)执行
begin
  p_sxt16(2,3);

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值