--流程控制语句
--条件表达式符号
>、<、>、<=、>=、<>、!=
IS NULL / IS NOT NULL
BETWEEN ... AND ...
--条件连接符
AND/OR
-------------------------------------------------------------------------------
--判断语句
--IF语句
--语法
IF 条件表达式 THEN
PLSQL语句块;
END IF;
--IF ELSE语句
--语法
IF 条件表达式 THEN
PLSQL语句块;
ELSE
PLSQL语句块;
END IF;
--IF ELSIF ELSE语句
--语法
IF 条件表达式1 THEN
PLSQL语句块1;
ELSIF 条件表达式2 THEN
PLSQL语句块2;
ELSIF 条件表达式3 THEN
PLSQL语句块3;
...
ELSE
PLSQL语句块;
END IF;
--示例1,IF练习题。如果员工的工资小于3000,则给该员工薪资加500
DECLARE
V_EMPNO SCOTT.EMP2.EMPNO%TYPE:=7499;
V_SAL SCOTT.EMP2.SAL%TYPE;
BEGIN
SELECT SAL INTO V_SAL FROM EMP2 WHERE EMPNO=V_EMPNO;
IF V_SAL<3000 THEN
UPDATE EMP2 SET SAL=SAL+500 WHERE EMPNO=V_EMPNO;
END IF;
END;
--示例2,IF ELSE练习题。比较M和N的大小,打印出更大的那个值
DECLARE
V_N NUMBER(10):=333;
V_M NUMBER(10):=100;
BEGIN
IF V_N>=V_M THEN
DBMS_OUTPUT.PUT_LINE(V_N);
ELSE
DBMS_OUTPUT.PUT_LINE(V_M);
END IF;
END;
--示例3,IF ELSIF ELSE练习题。当成绩小于60时打印不及格,当成绩60-70时,打印及格,当成绩70-80,打印良好。当成绩80以上,打印优秀。
DECLARE
V_SC NUMBER(4,1):=80;
BEGIN
IF V_SC<60 THEN
DBMS_OUTPUT.PUT_LINE('不及格');
ELSIF V_SC<70 THEN
DBMS_OUTPUT.PUT_LINE('及格');
ELSIF V_SC<80 THEN
DBMS_OUTPUT.PUT_LINE('良好');
ELSE
DBMS_OUTPUT.PUT_LINE('优秀');
END IF;
END;
-------------------------------------------------------------------------------
--CASE语句
--语法1
CASE
WHEN 条件表达式1 THEN
PLSQL语句块1;
WHEN 条件表达式2 THEN
PLSQL语句块2;
...
ELSE
PLSQL语句块;
END CASE;
--语法2
CASE 表达式
WHEN 值 THEN
PLSQL语句块1;
WHEN 值 THEN
PLSQL语句块2;
...
ELSE
PLSQL语句块;
END CASE;
--示例4,CASE WHEN练习题。当成绩小于60时打印不及格,当成绩60-70时,打印及格,当成绩70-80,打印良好。当成绩80以上,打印优秀。
DECLARE
V_SC NUMBER(4,1):=70;
BEGIN
CASE
WHEN V_SC<60 THEN
DBMS_OUTPUT.PUT_LINE('不及格');
WHEN V_SC<70 THEN
DBMS_OUTPUT.PUT_LINE('及格');
WHEN V_SC<80 THEN
DBMS_OUTPUT.PUT_LINE('良好');
ELSE
DBMS_OUTPUT.PUT_LINE('优秀');
END CASE;
END;
-------------------------------------------------------------------------------
--循环语句
--LOOP循环
--语法
LOOP
循环体语句;
退出循环体语句; --EXIT WHEN
循环控制语句; --修改循环变量的值
END LOOP;
--注意:需要声明循环变量,有退出循环语句和循环控制语句,条件是退出循环条件
--WHILE循环
--语法
WHILE 循环条件 LOOP
循环体语句;
循环控制语句;
END LOOP;
--FOR循环
--语法
FOR 循环变量 IN [REVERSE] 集合|游标|SELECT语句 LOOP
循环体语句;
END LOOP;
--注意:
FOR循环不需要声明循环变量,也不需要循环控制语句
FOR循环后面是一个非数字集合时,循环变量默认是一个记录类型
数字集合的表示:最小值..最大值
--循环涉及的关键字
EXIT:退出循环
CONTINUE:退出本次循环
RETURN:结束程序
--示例4,LOOP循环练习。循环打印1-10
DECLARE
V_N NUMBER(10):=1;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE(V_N); --循环体语句
EXIT WHEN V_N=10; --退出循环语句
V_N:=V_N+1; --循环控制语句
END LOOP;
END;
--示例5,WHILE循环练习。循环打印1-10
DECLARE
V_N NUMBER(10):=1;
BEGIN
WHILE V_N<=10 LOOP
DBMS_OUTPUT.PUT_LINE(V_N); --循环体语句
V_N:=V_N+1; --循环控制语句
END LOOP;
END;
--示例6,FOR循环练习。循环打印1-10
BEGIN
FOR V_N IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(V_N);
END LOOP;
END;
--示例7,FOR循环练习。查询10号部门的所有员工信息
BEGIN
FOR V_EMP IN (SELECT * FROM EMP2 WHERE DEPTNO=10) LOOP
DBMS_OUTPUT.PUT_LINE(V_EMP.EMPNO||','||V_EMP.ENAME);
END LOOP;
END;
-------------------------------------------------------------------------------
--流程控制语句练习题
--判断语句练习题
--练习题1,打印如下图形,分析如下
--******* 1ROW 7'*' 0' ' (N-1) 7-2(N-1)
-- ***** 2ROW 5'*' 1' '
-- *** 3ROW 3'*' 2' '
-- * 4ROW 1'*' 3' '
DECLARE
V_R NUMBER(10):=11;
BEGIN
FOR V_N IN 1..(1+V_R)/2 LOOP
FOR V_M IN 1..(V_N-1) LOOP
DBMS_OUTPUT.PUT(' ');
END LOOP;
FOR V_M IN 1..V_R-2*(V_N-1) LOOP
DBMS_OUTPUT.PUT('*');
END LOOP;
DBMS_OUTPUT.NEW_LINE();
END LOOP;
END;
--练习题2,打印九九乘法表
DECLARE
V_RES NUMBER(10);
BEGIN
FOR V_N IN 1..9 LOOP
FOR V_M IN 1..V_N LOOP
V_RES:=V_M*V_N;
DBMS_OUTPUT.PUT(V_M||'*'||V_N||'='||V_RES);
IF V_RES<10 THEN
DBMS_OUTPUT.PUT(' ');
ELSE
DBMS_OUTPUT.PUT(' ');
END IF;
END LOOP;
DBMS_OUTPUT.NEW_LINE();
END LOOP;
END;
--练习题3,给出三个数,并按从大到小依次打印
DECLARE
V_N NUMBER(10):=66; --77 100 100
V_M NUMBER(10):=300; --66 66 77
V_K NUMBER(10):=100; --100 77 66
V_TMP NUMBER(10);
BEGIN
IF V_N<V_M THEN
V_TMP:=V_N;
V_N:=V_M;
V_M:=V_TMP;
END IF;
IF V_N<V_K THEN
V_TMP:=V_K;
V_K:=V_N;
V_N:=V_TMP;
END IF;
IF V_M<V_K THEN
V_TMP:=V_M;
V_M:=V_K;
V_K:=V_TMP;
END IF;
DBMS_OUTPUT.PUT_LINE(V_N||','||V_M||','||V_K);
END;
--练习题4,判断一个年份是不是闰年,优先级:AND > OR
DECLARE
V_YEAR NUMBER(4):=2021;
BEGIN
IF MOD(V_YEAR,400)=0 OR MOD(V_YEAR,4)=0 AND MOD(V_YEAR,100)<>0 THEN
DBMS_OUTPUT.PUT_LINE(V_YEAR||'是闰年');
ELSE
DBMS_OUTPUT.PUT_LINE(V_YEAR||'是平年');
END IF;
END;
--练习题5,判断一个数是奇数还是偶数
DECLARE
V_N NUMBER(10):=16;
BEGIN
IF MOD(V_N,2)=0 THEN
DBMS_OUTPUT.PUT_LINE(V_N||'是偶数');
ELSE
DBMS_OUTPUT.PUT_LINE(V_N||'是奇数');
END IF;
END;
--练习题6,现要求输入体重和身高,求出体制指数所在范围
--体质指数(BMI)=体重(KG)/身高^2(M)
--偏瘦 <=18.4;
--正常 18.5-23.9
--过重 24.0-27.9
--肥胖 >=28
DECLARE
V_H NUMBER(10,2):=1.72;
V_W NUMBER(10,2):=90;
V_BMI NUMBER(10,2);
BEGIN
V_BMI:=V_W/POWER(V_H,2);
CASE
WHEN V_BMI<=18.4 THEN
DBMS_OUTPUT.PUT_LINE('V_BMI:'||V_BMI||',偏瘦');
WHEN V_BMI<=23.9 THEN
DBMS_OUTPUT.PUT_LINE('V_BMI:'||V_BMI||',正常');
WHEN V_BMI<=27.9 THEN
DBMS_OUTPUT.PUT_LINE('V_BMI:'||V_BMI||',过重');
ELSE
DBMS_OUTPUT.PUT_LINE('V_BMI:'||V_BMI||',肥胖');
END CASE;
END;
--练习题7,两个数相除并显示结果,如果第二个数为0,显示除数不能为0
DECLARE
V_N NUMBER(10):=38;
V_M NUMBER(10):=10;
BEGIN
IF V_M<>0 THEN
DBMS_OUTPUT.PUT_LINE('V_N/V_M='||V_N/V_M);
ELSE
DBMS_OUTPUT.PUT_LINE('除数不能为0');
END IF;
END;
-------------------------------------------------------------------------------
--循环语句练习题
--练习题1,从EMP2表中显示名为SMITH的雇员的薪水和职位
DECLARE
BEGIN
FOR V_EMP IN (SELECT ENAME,SAL,JOB FROM EMP2 WHERE ENAME='SMITH') LOOP
DBMS_OUTPUT.PUT_LINE(V_EMP.ENAME||','||V_EMP.SAL||','||V_EMP.JOB);
END LOOP;
END;
--练习题2,根据雇员的职位,公司决定按下列结构给员工加薪
--CLERK 500
--SALESMAN 1000
--ANALYST 1500
--OTHERWISE 2000
DECLARE
V_SAL SCOTT.EMP2.SAL%TYPE;
BEGIN
FOR V_EMP IN(SELECT EMPNO,JOB FROM EMP2) LOOP
CASE V_EMP.JOB
WHEN 'CLERK' THEN
V_SAL:=500;
WHEN 'SALESMAN' THEN
V_SAL:=1000;
WHEN 'ANALYST' THEN
V_SAL:=1500;
ELSE
V_SAL:=2000;
END CASE;
UPDATE EMP2 SET SAL=SAL+V_SAL WHERE EMPNO=V_EMP.EMPNO;
END LOOP;
END;
--练习题3,计算S=1*2+2*3+...+N*(N+1),当N=50的值
DECLARE
V_N NUMBER(10):=50;
V_SUM NUMBER(10):=0;
BEGIN
FOR V_M IN 1..V_N LOOP
V_SUM:=V_SUM+V_M*(V_M+1);
END LOOP;
DBMS_OUTPUT.PUT_LINE('V_SUM='||V_SUM);
END;
--练习题4,计算下面级数当末项小于0.001时的部分和
--1/(1*2)+1/(2*3)+1/(3*4)+...+1/(N*(N+1))
DECLARE
V_N NUMBER(10):=100; --声明循环变量N
V_I NUMBER(10,9); --声明一个变量保存每一项的值
V_SUM NUMBER(10,9):=0; --声明一个变量保存表达式的和
BEGIN
FOR V_M IN 1..V_N LOOP
V_I:=1/(V_M*(V_M+1));
V_SUM:=V_SUM+V_I;
IF V_I<0.001 THEN
DBMS_OUTPUT.PUT_LINE('V_M='||V_M);
EXIT;
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE('V_SUM='||TO_CHAR(V_SUM));
END;
--练习题5,计算SUM=1!+2!+3!+...+N!
DECLARE
V_N NUMBER(10):=5;
V_TMP NUMBER(10):=1;
V_SUM NUMBER(10):=0;
BEGIN
FOR V_M IN 1..V_N LOOP
V_TMP:=V_TMP*V_M;
V_SUM:=V_SUM+V_TMP;
END LOOP;
DBMS_OUTPUT.PUT_LINE('V_SUM='||V_SUM);
END;
--练习题6,编程满足不等式 1^2+3^2+5^2+...+N^2>2000的最小N值
DECLARE
V_SUM NUMBER(20):=0;
V_N NUMBER(20):=1;
BEGIN
WHILE 1=1 LOOP
V_SUM:=V_SUM+POWER(V_N,2);
IF V_SUM>2000 THEN
EXIT;
END IF;
V_N:=2*V_N+1;
END LOOP;
DBMS_OUTPUT.PUT_LINE(V_N);
END;
DECLARE
V_SUM NUMBER(20):=0;
V_N NUMBER(20):=1;
BEGIN
LOOP
V_SUM:=V_SUM+POWER(V_N,2);
EXIT WHEN V_SUM>2000;
V_N:=2*V_N+1;
END LOOP;
DBMS_OUTPUT.PUT_LINE(V_N);
END;
--练习题7,将员工表中所有工资小于3000增加400,统计出增加工资的人数和增加工资的数量
--方法一
DECLARE
V_COUNT NUMBER(10);
BEGIN
SELECT COUNT(*) INTO V_COUNT FROM EMP2 WHERE SAL<3000;
UPDATE EMP2 SET SAL=SAL+400 WHERE SAL<3000;
DBMS_OUTPUT.PUT_LINE('人数='||V_COUNT||',总工资='||(V_COUNT*400));
END;
--方法二
DECLARE
V_COUNT NUMBER(10);
BEGIN
UPDATE EMP2 SET SAL=SAL+400 WHERE SAL<3000;
V_COUNT:=SQL%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE('人数='||V_COUNT||',总工资='||(V_COUNT*400));
END;
--练习题8,从员工表中显示工资最高的前五个人的姓名、部门编号和工资
BEGIN
FOR V_EMP IN (SELECT * FROM (SELECT ENAME,DEPTNO,SAL FROM EMP2 ORDER BY SAL DESC) WHERE ROWNUM<=5) LOOP
DBMS_OUTPUT.PUT_LINE(V_EMP.ENAME||','||V_EMP.SAL||','||V_EMP.DEPTNO);
END LOOP;
END;