看完这章后你会学习到以下内容:
1.练习场景
2.面试场景
3.工作应用场景
总览思维导图:
面试部分:
1.创建函数,从emp表中查询指定员工编号的职工的工资
CREATE OR REPLACE FUNCTION CHECK_SAL(F_EMPNO IN EMP.EMPNO%TYPE) RETURN NUMBER IS
V_SAL VARCHAR(50);
BEGIN
SELECT SAL INTO V_SAL FROM EMP WHERE EMPNO = F_EMPNO; --- 直接调用隐式游标
RETURN V_SAL;
EXCEPTION WHEN NO_DATA_FOUND THEN --- 异常值处理
V_SAL:='没找到任何结果';
RETURN V_SAL;
END;
--- 调用函数
SELECT CHECK_SAL(7499) AS 工资 FROM DUAL;
2.*创建函数,返回emp表中指定职工的工资和姓名。
返回值是两个,可用return返回一个,另一个用out参数带回
CREATE OR REPLACE FUNCTION F_EMP_SALENAME(FEMPNO IN EMP.EMPNO%TYPE
,V_ENAME OUT EMP.ENAME%TYPE
)RETURN NUMBER IS
V_SAL EMP.SAL%TYPE;
BEGIN
SELECT SAL,ENAME INTO V_SAL,V_ENAME
FROM EMP
WHERE EMPNO = FEMPNO;
RETURN V_SAL;
END;
--- 第一部分借用IN参数,返回其中一个SAL
--- 第二部分再重新定义一个OUT参数,不然程序不清楚要调用那个类型的参数
DECLARE
P_ENAME EMP.ENAME%TYPE;
p_SAL EMP.SAL%TYPE;
BEGIN
P_SAL:=F_EMP_SALENAME(7369,P_ENAME); --- 定义一个Out参数返回function的返回值Sal
DBMS_OUTPUT.put_line('员工'||P_ENAME||'薪酬'||P_SAL);
END;
3.创建函数,根据给定的部门编号(提示: 利用&)计算该部门所有职工的平均工资。
CREATE OR REPLACE FUNCTION F_INPUTEMPNO(F_DEPTNO IN DEPT.DEPTNO%TYPE)
RETURN NUMBER IS
V_SAL NUMBER;
BEGIN
SELECT AVG(SAL) INTO V_SAL FROM EMP WHERE DEPTNO = F_DEPTNO;
RETURN V_SAL;
END;
--- 调用时候,在输入名称前加入&,类似于VBA里的Input函数
SELECT F_INPUTEMPNO(&部门编号) AS 平均工资 FROM DUAL;
4.创建一个函数,仅有一个形参,它接收调用函数中传递过来的实参--部门号,函数的返回值为该部门的一整条记录信息.
CREATE OR REPLACE FUNCTION F_EMPINFO(F_DEPTNO IN DEPT.DEPTNO%TYPE)
RETURN DEPT%ROWTYPE IS
V_DEPT DEPT%ROWTYPE;
BEGIN
SELECT * INTO V_DEPT FROM DEPT WHERE DEPTNO = F_DEPTNO;
RETURN V_DEPT;
END;
DECLARE
V_DEPT DEPT%ROWTYPE;
BEGIN
V_DEPT := F_EMPINFO(20); --- 传递参数给到调用函数时新定义得变量V_Dept;
DBMS_OUTPUT.PUT_LINE('部门名: '||V_DEPT.DNAME || ' 部门位置: ' || V_DEPT.LOC);
END;
5*.创建函数,将emp表中工资低于平均工资的职工工资加上200,并返回修改了工资的总人数。注意:Update后面要加上Where语句否则全部都更新,其次我们善用%ROWCOUNT.
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;
/
面试过程
1.输入2个整数,返回最小到最大数之间的连乘的结果(两个整数在1到20之间);
思路: 先对两个数进行范围的设置,用IF加AND判断。
然后两个数字一共三种可能:
A大于B,A小于B,A等于B 用IF Elsif 方式做条件判断。
CREATE OR REPLACE FUNCTION FUNB(P1 IN INT, P2 IN INT) RETURN INTEGER IS --- 这两个的数据类型一定要一致
V_RESULT INTEGER := 1;
BEGIN
IF (P1 < 1 AND P1 > 20) AND (P2< 1 AND P2 > 20) THEN
IF P2 > P1 THEN
FOR I IN P1 .. P2 LOOP
V_RESULT := V_RESULT * I;
END LOOP;
ELSIF P2 < P1 THEN
FOR I IN P2 .. P1 LOOP
V_RESULT := V_RESULT * I;
END LOOP;
ELSE
V_RESULT := P1 * P2;
END IF;
ELSE
DBMS_OUTPUT.put_line('请输入正确的范围值');
END IF;
RETURN V_RESULT;
END;
2.输入3个整数,取中位数。
--- 方法一
CREATE OR REPLACE FUNCTION FUNA(P1 IN INT,P2 IN INT,P3 IN INT)
RETURN INTEGER IS
V_RESULT INTEGER;
BEGIN
SELECT CASE WHEN P1 >= P2 AND P1 <= P3 THEN P1
WHEN P2 >= P1 AND P2 <= P3 THEN P2
WHEN P3 >= P1 AND P3 <= P2 THEN P3 END
INTO V_RESULT FROM DUAL;
RETURN V_RESULT;
END;
----- 方法二
CREATE OR REPLACE FUNCTION FUN_middle(X1 IN NUMBER,X2 IN NUMBER,X3 IN NUMBER)
RETURN number
IS
BEGIN
IF (X1-X2)*(X1-X3)<=0 then return x1;
elsif (x2-x1)*(x2-x3)<=0 then return x2;
elsif(x3-x1)*(x3-x2)<=0 then return x3;
end if;
end;
3. 对比两个数,返回一个最大值。可以在设置参数时,顺带设置默认值
-- 传入两个参数,返回最大值
CREATE OR REPLACE FUNCTION FUN_MAX (P_NUM1 IN NUMBER, P_NUM2 IN NUMBER DEFAULT 99)
RETURN NUMBER -- 函数的返回类型
IS
BEGIN
IF P_NUM1>P_NUM2 THEN
RETURN P_NUM1;
ELSE
RETURN P_NUM2;
END IF;
END;
3. 工作场景(一)
-- 函数返回类型为游标(对应报表接口)
-- 传入部门编号,返回整个部门的员工信息(函数)
CREATE OR REPLACE FUNCTION FUN_REF(P_DEPTNO EMP.DEPTNO%TYPE)
RETURN SYS_REFCURSOR IS
C_EMP SYS_REFCURSOR; -- C_EMP 游标类型
BEGIN
OPEN C_EMP FOR -- 不要忘记添加FOR
SELECT * FROM EMP WHERE DEPTNO = P_DEPTNO;
RETURN C_EMP;
END FUN_REF;
-- 直接在Dual 表里直接调用
SELECT FUN_REF(30) FROM DUAL;