一,常见的循环

--while循环
 procedure loop_while
 (
    start_value in number,
    end_value in number
 )
 is
    current_value number := start_value;
 begin

   while current_value <=end_value
   loop 
      dbms_output.put_line('now number:' || current_value);
      current_value:=current_value+1;
   end loop;           
 end loop_while;

指定循环的初始值和结束值之后,就可以看到将这2个值之间的数字一行行打印出来了;当然只要while循环条件的求值结果是true,循环就会继续下去,

如果求值条件为false或者null,循环就会终止。这个循环条件每执行一次循环体之前都会先进行判断,因此while循环并不能保证循环体一定能被执行。

所以如果我们无法提前预知所需要巡检的次数的情况下,就可以使用While来进行循环处理。


-数值型For循环
 procedure loop_num_for
 (
    lowest  in number,
    highest in number
 )
 is
 begin
    FOR even_number in lowest .. highest --升序
    loop
       --处理非平滑增长的索引
       if mod(even_number,2)=0
       then
          dbms_output.put_line('now number:' || even_number);
       end if;
    end loop;    
 end loop_num_for;



复制代码

这种循环在开始的时候就已经知道循环的次数了,注意这里不需要声明循环索引,因为PL/SQL会自动隐式的用一个integer类型的局部变量作为它的循环索引;

如果要降序循环,必须加上reverse关键字,并且循环上边界和下边界的顺利无需改变:


FOR even_number in reverse lowest .. highest
  loop
     dbms_output.put_line('now number:' || even_number);
  end loop;



另外需要说明的是,数值型FOR循环中,索引总是以1为单位递增或递减,所以如果我们的循环条件并非如此理想的平滑增长,我们就必须用一些逻辑代码或者技巧来

达到我们的目的。

      如果我们需要对很多行记录做处理时,就可以使用游标型FOR循环:

--游标型For循环
 procedure loop_cursor_for
 is
 begin
      declare cursor userinfo_cur is select * from userinfo_table;
      begin
        FOR userinfo_rec in userinfo_cur
        loop
           dbms_output.put_line('username is:' || userinfo_rec.user_name);              
        end loop;
      end;
 end loop_cursor_for;



复制代码

当游标中的所有记录都取出来后,FOR循环就会自动终止,这里不用显示OPEN、CLOSE游标,PL/SQL引擎会自动处理。

上面的循环语句都可以用EXIT 或者 EXIT WHEN来终止其循环,但最好不要这样做,因为这样可能会造成循环的逻辑出现问题,最终造成SQL代码难于跟踪和调试。

二,简单的程序

--1、开发存储过程:根据部门名称删除指定部门的所有员工,并返回删除人数。


CREATE OR REPLACE PROCEDURE p_del_emp(
        i_dname VARCHAR2,
        o_count OUT NUMBER
 )
 IS
        v_deptno dept.deptno%TYPE;
 BEGIN
        SELECT deptno INTO v_deptno FROM dept WHERE dname=i_dname;
        DELETE FROM emp WHERE deptno=v_deptno; 
        o_count := SQL%ROWCOUNT;      
 END; 

--2、开发存储过程:添加员工下列信息:ename,sal,hiredate,deptno。
 --empno由序列生成。添加成功以后,返回新员工的工号。
 CREATE OR REPLACE PROCEDURE p_add_emp(
 i_ename VARCHAR2,i_sal NUMBER,i_hiredate DATE,i_deptno NUMBER,o_empno OUT NUMBER
 )
 IS     
 BEGIN
    SELECT seq_emp_id.nextval INTO o_empno FROM dual;
    INSERT INTO emp(empno,ename,sal,hiredate,deptno) VALUES(o_empno,i_ename,i_sal,i_hiredate,i_deptno);
 END;
--3、开发存储过程:要求根据工号给指定员工增加工资20%,如果新工资高于3000,则不能修改并给出提示。
 CREATE OR REPLACE PROCEDURE p_add_sal(i_empno NUMBER,o_msg OUT VARCHAR2)
 IS 
   v_sal emp.sal%TYPE;
 BEGIN
   UPDATE emp SET sal=sal*1.2 WHERE empno=i_empno RETURNING sal INTO v_sal;
   IF v_sal > 3000 THEN
     ROLLBACK;
     o_msg := '工资太高';
   ELSE
     o_msg := '修改成功';
   END IF;
  
 END;