二、流程控制

介绍 PL/SQL 的流程控制语句, 包括如下三类:

  • 控制语句: IF 语句

    IF … THEN … ELSIF … THEN …ELSE … END IF;

    CASE … WHEN … THEN …ELSE … END;

  • 循环语句: LOOP 语句, EXIT 语句

    LOOP … EXIT WHEN … END LOOP

  • 顺序语句: GOTO 语句, NULL 语句

条件语句
IF <布尔表达式> THEN
	PL/SQL 和 SQL 语句;
END IF;
IF <布尔表达式> THEN 
	PL/SQL 和 SQL 语句;
ELSE
	其它语句;
END IF;
IF <布尔表达式> THEN 
	PL/SQL 和 SQL 语句;
ELSIF < 其它布尔表达式> THEN
	其它语句;
ELSIF < 其它布尔表达式> THEN
	其它语句;
ELSE
	其它语句;
END IF;

提示: ELSIF不能写成 ELSEIF

要求: 查询出 150号 员工的工资, 若其工资大于或等于 10000 则打印 'salary >= 10000'; 
若在 5000 到 10000 之间, 则打印 '5000<= salary < 10000'; 否则打印 'salary < 5000'
(方法一)
declare
  v_salary employees.salary%type;
begin
  --通过 select ... into ... 语句为变量赋值
 select salary into v_salary
 from employees
 where employee_id = 150;
 
 dbms_output.put_line('salary: ' || v_salary);
 
 -- 打印变量的值
 if v_salary >= 10000 then
    dbms_output.put_line('salary >= 10000');
 elsif v_salary >= 5000 then
    dbms_output.put_line('5000 <= salary < 10000');
 else
    dbms_output.put_line('salary < 5000');
 end if;
(方法二)
declare
     v_emp_name employees.last_name%type;
     v_emp_sal employees.salary%type;
     v_emp_sal_level varchar2(20);
begin
     select last_name,salary into v_emp_name,v_emp_sal from employees where employee_id = 150;
     
     if(v_emp_sal >= 10000) then v_emp_sal_level := 'salary >= 10000';
     elsif(v_emp_sal >= 5000) then v_emp_sal_level := '5000<= salary < 10000';
     else v_emp_sal_level := 'salary < 5000';
     end if;
     
     dbms_output.put_line(v_emp_name||','||v_emp_sal||','||v_emp_sal);
end;
CASE 表达式
CASE selector
	WHEN expression1 THEN result1 WHEN expression2 THEN result2
	...
	WHEN expressionN THEN resultN [ ELSE resultN+1]
END;
declare
       v_sal employees.salary%type;
       v_msg varchar2(50);
begin     
       select salary into v_sal
       from employees
       where employee_id = 150;
       
       --case 不能向下面这样用
       /*
       case v_sal when salary >= 10000 then v_msg := '>=10000' 
                  when salary >= 5000 then v_msg := '5000<= salary < 10000'
                  else v_msg := 'salary < 5000'
       end;
       */
 
       v_msg := 
             case trunc(v_sal / 5000)
                  when 0 then 'salary < 5000'
                  when 1 then '5000<= salary < 10000'
                  else 'salary >= 10000'
             end;
       
       dbms_output.put_line(v_sal ||','||v_msg);
end;
要求: 查询出 122 号员工的 JOB_ID, 若其值为 'IT_PROG', 则打印 'GRADE: A'; 
					    'AC_MGT', 打印 'GRADE B', 
					    'AC_ACCOUNT', 打印 'GRADE C'; 
					    否则打印 'GRADE D'

declare
       --声明变量
       v_grade char(1);
       v_job_id employees.job_id%type;
begin
       select job_id into v_job_id
       from employees
       where employee_id = 122;
       
       dbms_output.put_line('job_id: ' || v_job_id);
       
       --根据 v_job_id 的取值, 利用 case 字句为 v_grade 赋值
       v_grade :=  
               case v_job_id when 'IT_PROG' then 'A'
                             when 'AC_MGT' then 'B'
                             when 'AC_ACCOUNT' then 'C'
                             else 'D'
                end;
                
       dbms_output.put_line('GRADE: ' || v_grade);
end; 
循环
1. 简单循环
LOOP
	--要执行的语句;
	EXIT WHEN <条件语句> ;	/*条件满足,退出循环语句*/
END LOOP;
declare
       --初始化条件
       v_i number(3) := 1;
begin
       loop
       --循环体
        dbms_output.put_line(v_i);
	--循环条件
        exit when v_i = 100;
	--迭代条件
        v_i := v_i + 1;
       end loop;
end;
2. WHILE 循环(相较 1,推荐使用 2)
WHILE <布尔表达式> LOOP
	要执行的语句; 
END LOOP;
declare
       --初始化条件
       v_i number(3) := 1;
begin
       --循环条件
       while v_i <= 100 loop
	     --循环体
             dbms_output.put_line(v_i);
	     --迭代条件
             v_i := v_i + 1;
       end loop;
end; 
3. 数字式循环
FOR 循环计数器 IN [ REVERSE ] 下限 .. 上限 LOOP
	要执行的语句;
END LOOP;

每循环一次,循环变量自动加 1;使用关键字 REVERSE,循环变量自动减 1。跟在 IN REVERSE 后面的数字必须是从小到大的顺序,**而且必须是整数,不能是变量或表达式。可以使用 **EXIT**退出循环。

BEGIN
	FOR int	in 1..10 LOOP
		DBMS_OUTPUT.PUT_LINE('int 的当前值为: '||int); 
END LOOP;
 
END;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CaMxuOln-1610848840396)(F:\Oracle.assets\image-20201122172805422.png)]

例 6.
CREATE TABLE temp_table(num_col NUMBER);

DECLARE
	V_counter NUMBER := 10; BEGIN
	INSERT INTO temp_table(num_col) VALUES (v_counter ); 
	FOR v_counter IN 20 .. 25 LOOP
		INSERT INTO temp_table (num_col ) VALUES ( v_counter ); 
	END LOOP;
	INSERT INTO temp_table(num_col) VALUES (v_counter ); 
	FOR v_counter IN REVERSE 20 .. 25 LOOP
		INSERT INTO temp_table (num_col ) VALUES ( v_counter ); END LOOP;
	END ;

DROP TABLE temp_table;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KyjpV7gV-1610848840402)(F:\Oracle.assets\image-20201122174215774.png)]

 综合使用 if, while 语句, 打印 1 - 100 之间的所有素数
(素数: 有且仅用两个正约数的整数, 2, 3, 5, 7, 11, 13, ...).
declare
  v_flag number(1):=1;
  v_i number(3):=2;
  v_j number(2):=2;
begin

  while (v_i<=100) loop
        while v_j <= sqrt(v_i) loop
              if (mod(v_i,v_j)=0) then v_flag:= 0;
	      end if;
             
	      v_j :=v_j +1;
        end loop;
        
	if(v_flag=1) then dbms_output.put_line(v_i);
	end if;

        v_flag :=1;
        v_j := 2;
        v_i :=v_i +1;
   end loop;

end;


(法二)使用for循环实现1-100之间的素数的输出
declare
  --标记值, 若为 1 则是素数, 否则不是
  v_flag number(1) := 0;
begin
   for i in 2 .. 100 loop

       v_flag := 1;     
         
       for j in 2 .. sqrt(i) loop
           if i mod j = 0 then
              v_flag := 0;	
           end if;        
       end loop;
       
       if v_flag = 1 then
           dbms_output.put_line(i);
       end if;
       
   end loop;
end;

标号和 GOTO

PL/SQL 中 GOTO 语句是无条件跳转到指定的标号去的意思。语法如下:

GOTO	label;
. . .	. . .
<<label>>	/*标号是用<<	>>括起来的标识符 */
declare
  --标记值, 若为 1 则是素数, 否则不是
  v_flag number(1) := 0;
begin
   for i in 2 .. 100 loop
       v_flag := 1;     
         
       for j in 2 .. sqrt(i) loop
           if i mod j = 0 then
              v_flag := 0;
              goto label; 
           end if;        
       end loop;
       
       <<label>>
       if v_flag = 1 then
           dbms_output.put_line(i);
       end if;
       
   end loop;
end; 
NULL 语句

在 PL/SQL 程序中,可以用 null 语句来说明“不用做任何事情”的意思,相当于一个占位符,可以使某些语句变得有意义,提高程序的可读性。如:

DECLARE
	. . . 
BEGIN
	…
	IF v_num IS NULL THEN
		GOTO print1; END IF;
	…
	<<print1>>
	NULL;	-- 不需要处理任何数据。
END;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值