Oracle 存储过程详解(下)

前文链接:Oracle 存储过程详解(上)
和上篇一样,被 “[ ]” 包裹起来的表示可选输入项,被 “{ }” 包裹起来的表示必填项。

六、条件分支控制

1、IF - ELSE

  Oracle数据库支持使用 “IF - ELSE” 进行简单的分支判断,语法结构和MSSQL Server的语法类似:

IF { condition_1 } THEN 
	{ PL-SQL blocks A }
ELSE
	{ PL-SQL blocks B }
END IF;

  条件语句放在 IF 和 THEN 之间,条件语句成立时执行语句块A,否则执行语句块B。在 IF 结束后,要用 END 关闭整个 IF 程序段。
  注意,对于 IF- ELSE 字段而言,ELSE 并不是必须的,你可以只用 IF - THEN ,然后用 END 关闭 IF。

2、IF - ELSIF - ELSE

  多条件分支使用 “IF - ELSIF - ELSE” 进行判断,语法上比简单的 IF - ELSE 多了一小段:

IF { condition_1 } THEN
	{ PLSQL_BLOCKS_1 }
ELSIF [ condition_2 ] THEN
	{ PLSQL_BLOCKS_2 }
ELSIF [ condition_3 ] THEN
	{ PLSQL_BLOCKS_3 }
		.....
ELSE
	{ PLSQL_BLOCKS_n } 
END IF;

  注意 “ELSIF” 的写法,只要条件成立,系统就会执行其对应的程序段,同样要用 END 结束 IF。

3、示例

  以下是一个简单的示范,我们通过几个存储过程的配合获取教师们的平均薪资,并判断编号为“1002”的老师的工资是否大于该平均数:

create or replace procedure calculate(
    input_no IN teacher.tno%type,
    result OUT varchar2
)
as
    avgs teacher.tsalary%type;
    salary teacher.tsalary%type;
begin
    select avg(tsalary) into avgs from teacher;
    select tsalary into salary from teacher
    where tno = 1002;
    
    IF salary > avgs THEN
        result := 'More than the avg,';
    ELSIF salary = avgs THEN 
        result := 'Equal to the avg,';
    ELSE
        result := 'Less than the avg,';
    END IF;
end calculate;

  以下是运行结果:
在这里插入图片描述
  注意,在 “BEGIN - END” 字段中使用存储过程的时候不需要加 call 或是 exec ,否则会抛出异常ORA-06550。

4、IF - ELSE IF - ELSE

  有时候我们用惯了JAVA、C++等语言,可能会习惯于用 “IF - ELSE IF - ELSE” 这种结果,尽管严格来讲这并不是Oracle鼓励使用的语法,但它并不是不能使用,你可以看成在 ELSE 的程序段里面又塞进去了一个 IF - ELSE 程序段:

IF { condition_1 } THEN
	{ PL-SQL block 1 }
ELSE IF { condition_2 } THEN
		{ PL-SQL block 2 }
	ELSE
		{ PL-SQL block 3 }
	END IF; -- 同样,你写了几个IF,你就得用 END 关闭几个
END IF;

七、循环分支控制

1、LOOP循环

  LOOP循环以 “LOOP” 标记为始,以 “END” 标记为程序段的结尾,要想结束循环则需使用 “EXIT” 字段。LOOP 循环的语法如下:

LOOP 
	[  PL-SQL blocks  ]
	EXIT WHEN { exit_condition }
	-- IF { exit_condition } THEN EXIT;
	[  PL-SQL blocks  ] 
END LOOP;

  执行 EXIT 字段就意味着循环的结束,程序段会从 END LOOP 的下一行开始执行。下面是一个示例,我们通过存储过程 “createScore” 向 stu_score 表中添加多条随机生成的成绩信息:

create or replace procedure createScore(
    num_of_stu IN number
)
as
    score number := 0;		-- 成绩
    i number := 1001;		-- 循环标记
begin
    delete from stu_score;	-- 为了方便看到调用后的效果,每次执行前先清空一下表格
    LOOP
        select trunc(dbms_random.value(0, 100))
        into score from dual;
        -- trunc(number num):对数字 num 进行截尾取整
        -- dbms_random.value(min, max):随机生成 [min, max] 范围内的一个小数
        -- 上述两个方法都是系统自带的方法,有兴趣的同志可以去查查看

        insert into stu_score values(i, score);
        dbms_output.put_line(i || ', ' || score);
        EXIT WHEN (i - 1000) = num_of_stu;
        -- 下面是另一种结束循环的写法
        -- IF (i - 1000) = num_of_stu THEN EXIT;
        i := i + 1;
    END LOOP;
end;
/

declare counts number := 20;
begin
    createScore(counts);
end;
/

  LOOP 的操作简单易懂,上述代码执行完毕后会在表中添加20条随机生成的成绩信息。除了直接使用 LOOP 以外,我们还可以把把 FOR 与 LOOP 结合起来使用。

2、FOR LOOP循环

  在Oracle中 FOR 与 LOOP 配合使用进行遍历操作,由 FOR 字段指定循环的范围,在 LOOP 中完成循环的主程序段:

FOR { index } IN [ REVERSE ] { range_set }
LOOP 
	{ PL-SQL blocks }
END LOOP;

  其中,{ index } 表示遍历时的计数器;{ range_set } 是 FOR 循环的遍历范围,index 的类型将与该范围的子集相同;[ REVERSE ] 字段表示是否逆序遍历范围集合。
  在这里,我之所以把 index 称为计数器而非 JAVA 里所说的迭代变量,是因为在执行循环主体的时候,我们不能对 index 的值进行任何修改,我们可以通过变量获得 index 的拷贝,但不能改变 index 并最终影响循环的进程。FOR 循环必然要跑完整个遍历范围。下面是一个简单示例,遍历表格 teacher 并输出所有的名字信息:

SQL> set serveroutput on;
SQL> begin
  2      FOR item IN ( select * from teacher )
  3      LOOP
  4          dbms_output.put_line(' -> Name: ' || item.tname);
  5      END LOOP;
  6  end;
  7  /
-> Name: Tom
-> Name: Sam
-> Name: Tim
-> Name: Allen
-> Name: Lily

PL/SQL 过程已成功完成

  另一个是遍历数字集合的示例,我们通过系统方法获得10个随机数,然后求他们的平均值:

declare
    counts number := 10;
    sum_num number := 0;
    r_num number := 0;
    result number := 0;
begin
    dbms_output.put('Random number: ');
    for i in 0..counts loop
        select trunc(dbms_random.value(0, 100))
        into r_num from dual;
                
        -- 利用 IF - ELSE 控制输出格式
        if i <> 10 then
            dbms_output.put(r_num || ', ');
        else
            dbms_output.put(r_num);
        end if;

        sum_num := sum_num + r_num;
    end loop;
    result := sum_num / counts;	-- 求平均数
    dbms_output.put_line('');
    dbms_output.put_line('-> Result: ' || result);
end;

-- 执行结果
Random number: 87, 68, 91, 82, 14, 16, 68, 37, 60, 13, 53
-> Result: 58.9

3、WHILE循环

  另一种常用的循环是 WHILE 循环,和 FOR 循环的语法相似,区别在于WHILE 循环使用 BOOLEAN 条件语句控制循环的开闭:

WHILE ( { cycle_condition } ) LOOP
	{ PL-SQL blocks }
END LOOP;

  下面是一个示例,在这个例子中,我们通过过程 calc_sum 求从 1 开始到给定的参数 counter 的累加和,并在主程序段中输出这个结果:

declare
    result number := 0;
    counter number := 10;
begin
    while (counter <> 0) loop
        result := result + counter;
        counter := counter - 1;
    end loop;
    dbms_output.put_line('result: ' || result);
end;

-- 输出结果
result: 55

4、循环名称

  每次使用循环都需要用 END 将其关闭,但如果用了太多的循环语句段,我们可能会将它们弄混,而且过多的循环内容也需要一些有效的备注,使用双书名号可以让我们给循环命名,在使用 END 的时候,可以直接根据名字结束对应的循环:

<< loop_name >>
LOOP
	......
END LOOP loop_name;

八、游标

  在Java中使用过 ResultSet 类的同志对于游标这个概念应该不会陌生,Oracle和 ResultSet 的指针在用途上其实十分相似。在Oracle中执行CRUD操作的时候,系统会在内存中开辟一块缓冲区,将执行结果保存在缓冲区中。游标就是这个缓冲区里的指针,它的类型可以是系统标量类型也可以是记录类型,它可以有返回值。下面是游标的语法:

declare
    CURSOR cursor_name { (parameter_1 [, parameter_2..]) }
        [ RETURN datatype ]
    IS { PL-SQL select_statement };
    [ variable_list | record_variable ]
begin
    OPEN cursor_name; 	-- 打开游标
    -- 读取下一行的信息
    FETCH cursor_name INTO { variable_list | record_variable };
    ......
    CLOSE cursor_name;	-- 关闭游标
end;

附录

[1] Oracle中的for和while循环
[2] Oracle PL/SQL之LOOP循环控制语句
[3] ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不到)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值