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);