PL/SQL编程(上)

PL/SQL块的组成

1.执行部分是必须的,而声明部分和异常部分是可选的;
2.可以在一个块的执行部分或异常处理部分嵌套其他的PL/SQL块;
3.所有的PL/SQL块都是以“END;”结束。
4.每一条语句都必须以分号结束,每条SQL语句可以写成多行形式,同样必须使用分号结束。一行中也可以有多条SQL语句,但是他们之间必须以分号分隔。
5.End;结束后要加“/”。

例如,定义一个包含声明、执行和异常处理的块
DECLARE
  v_ename VARCHAR2(10);
BEGIN
  SELECT ename INTO v_ename FROM emp 
  WHERE empno=7844;
  DBMS_OUTPUT.PUT_LINE(v_ename);
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    DBMS_OUTPUT.PUT_LINE('There is not such a employee');
END;

有嵌套的PL/SQL块:

DECLARE
  v_sal NUMBER(6,2);
  v_deptno NUMBER(2);
BEGIN    
  BEGIN
    SELECT deptno INTO v_deptno FROM emp 
    WHERE empno=7844;
  END;
  SELECT avg(sal) INTO v_sal FROM emp 
  WHERE deptno=v_deptno;
  DBMS_OUTPUT.PUT_LINE(v_sal);
END;

匿名块
指动态生成,只能执行一次的块,不能由其他应用程序调用。
命名块
指一次编译可多次执行的PL/SQL程序,包括函数、存储过程、包、触发器等。它们编译后放在服务器中,由应用程序或系统在特定条件下调用执行。
命名块示例

CREATE OR REPLACE PROCEDURE showavgsal 
(p_deptno NUMBER)
AS
  v_sal NUMBER(6,2);
BEGIN
  SELECT avg(sal) INTO v_sal FROM emp 
  WHERE deptno=p_deptno;
  DBMS_OUTPUT.PUT_LINE(v_sal);
END showavgsal;

数据类型
1.%TYPE与%ROWTYPE
2.如果要定义一个类型与某个变量的数据类型或数据库表中某个列的数据类型一致(不知道该变量或列的数据类型)的变量,可以利用%TYPE来实现。
3.如果要定义一个与数据库中某个表结构一致的记录类型的变量,可以使用%ROWTYPE来实现。

注意:⑴ 变量的类型随参照的变量类型、数据库表列类型、表结构的变化
         而变化;
      ⑵ 如果数据库表列中有NOT NULL约束,则%TYPE与%ROWTYPE返回的数
        据类型没有此限制

实例:

DECLARE
  v_sal emp.sal%TYPE; --变量v_sal的类型与emp表的sal列类型相同
  v_emp emp%ROWTYPE; /*变量v_emp是一个记录类型,其中各个分量的
                       构成和类型与表emp相同*/
BEGIN
  SELECT sal INTO v_sal FROM emp WHERE empno=7844;
  SELECT * INTO v_emp FROM emp WHERE empno=7900;
  DBMS_OUTPUT.PUT_LINE(v_sal);
  DBMS_OUTPUT.PUT_LINE(v_emp.ename||v_emp.sal);
END; 

变量与常量的定义

变量定义的一般格式
variable_name [CONSTANT] datatype [NOT NULL] [DEFAULT|:=expression];
说明
变量或常量名称是一个PL/SQL标识符,应符合标识符命名规范;
每行只能定义一个变量;
如果加上关键字CONSTANT,则表示所定义的是一个常量,必须为它赋初值;
如果定义变量时使用了NOT NULL关键字,则必须为变量赋初值;
如果变量没有赋初值,则默认为NULL;
使用DEFAULT或“:=”运算符为变量初始化。

变量的作用域

<<OUTER>>
DECLARE
  v_ename  CHAR(16);
  v_outer  NUMBER(5);
BEGIN
  v_outer :=10;
  DECLARE
    v_ename CHAR(20); 
    v_inner DATE;
  BEGIN
    v_inner:=sysdate;
    v_ename:='INNER V_ENAME';
    OUTER.v_ename:='OUTER V_ENAME';
  END;
  DBMS_OUTPUT.PUT_LINE(v_ename);
END; 

用户定义记录类型及变量

例:利用记录类型以及记录类型变量,保存员工信息。
DECLARE
  TYPE t_emp IS RECORD(
     empno NUMBER(4), 
     ename CHAR(10),
     sal   NUMBER(6,2));
  v_emp t_emp;
BEGIN
  SELECT empno,ename,sal INTO v_emp 
  FROM emp WHERE empno=7844;
  DBMS_OUTPUT.PUT_LINE(v_emp.ename||' '||v_emp.sal);
END;

利用%ROWTYPE获取记录类型定义变量

DECLARE
  v_emp1 emp%ROWTYPE;
  v_emp2 emp%ROWTYPE;
  CURSOR c_emp IS
    SELECT empno,ename FROM emp WHERE deptno=10;
  v_emp10 c_emp%ROWTYPE; 
BEGIN
  SELECT * INTO v_emp1 FROM emp WHERE empno=7844;
  OPEN c_emp;  
  LOOP
    FETCH c_emp INTO v_emp10;
    EXIT WHEN c_emp%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(v_emp10.empno||' '||
                         v_emp10.ename); 
  END LOOP;  
  CLOSE c_emp;
END; 

在SELECT INTO语句中使用记录类型变量成员

DECLARE
  v_emp emp%ROWTYPE; 
BEGIN
  SELECT empno,ename,sal INTO v_emp.empno, 
    v_emp.ename,v_emp.sal FROM emp 
  WHERE empno=7844;
  DBMS_OUTPUT.PUT_LINE(v_emp.empno||
                       v_emp.ename||v_emp.sal);  
END;
DECLARE
  v_dept dept%ROWTYPE;
BEGIN
  v_dept.deptno:=50;
  v_dept.loc:='TIANJIN';
  V_dept.dname:='COMPUTER';
  UPDATE dept SET ROW=v_dept WHERE deptno=50;
END;

在DELETE语句中使用记录类型变量

扫描二维码关注公众号,回复: 9235769 查看本文章
DECLARE
   v_emp emp%ROWTYPE;
 BEGIN
   SELECT * INTO v_emp FROM emp 
   WHERE empno=7844;
   DELETE FROM emp WHERE deptno=v_emp.deptno;
 END; 

RETURNING

例如,将员工号为7844的员工工资提高100,同时返回修改后的工资。
DECLARE
  v_sal emp.sal%TYPE;
BEGIN
  UPDATE emp SET sal=sal+100 WHERE empno=7844 
  RETURNING sal INTO v_sal;
  DBMS_OUTPUT.PUT_LINE(v_sal);
END;

IF语句

例如,输入一个员工号,修改该员工的工资,如果该员工为10号部门,工资增加100;若为20号部门,工资增加160;若为30号部门,工资增加200;否则增加300。
DECLARE
  v_deptno emp.deptno%type;
  v_increment NUMBER(4);
  v_empno  emp.empno%type;
BEGIN
  v_empno:=&x;
  SELECT deptno INTO v_deptno FROM emp 
  WHERE empno=v_empno;
  IF v_deptno=10 THEN v_increment:=100;
  ELSIF v_deptno=20 THEN v_increment:=160;
  ELSIF v_deptno=30 THEN v_increment:=200;
  ELSE  v_increment:=300;
  END IF;
  UPDATE emp SET sal=sal+v_increment 
  WHERE empno=v_empno;
END;

CASE语句

例如,将前面的IF语句程序改成CASE语句的形式
DECLARE
  v_deptno emp.deptno%type;
  v_increment NUMBER(4);
  v_empno  emp.empno%type;
BEGIN
  v_empno:=&x;
  SELECT deptno INTO v_deptno FROM emp 
  WHERE empno=v_empno;
  CASE v_deptno  
    WHEN 10 THEN v_increment:=100;
    WHEN 20 THEN v_increment:=150;
    WHEN 30 THEN v_increment:=200;
    ELSE  v_increment:=300;
  END CASE;
  UPDATE emp SET sal=sal+v_increment 
  WHERE empno=v_empno; 
END; 
例如,根据输入的员工号,修改该员工工资。如果该员工工资低于1000,则工资增加200;如果工资在1000~2000之间,则增加150;如果工资在2000~3000之间,则增加100;否则增加50。
DECLARE
  v_sal emp.sal%type;
  v_increment NUMBER(4);
  v_empno  emp.empno%type;
BEGIN
  v_empno:=&x;
  SELECT sal INTO v_sal FROM emp 
  WHERE empno=v_empno;
  CASE   
    WHEN v_sal<1000 THEN v_increment:=200;
    WHEN v_sal<2000 THEN v_increment:=150;
    WHEN v_sal<3000 THEN v_increment:=100;
    ELSE v_increment:=50;
  END CASE;
  UPDATE emp SET sal=sal+v_increment 
  WHERE empno=v_empno;
END; 

循环结构

语法
LOOP
       sequence_of_statement;
       EXIT [WHEN condition] ;
END LOOP;
注意
在循环体中一定要包含EXIT语句,否则程序进入死循环。
例如,使用loop语句求得前100个自然数的和,并输出到屏幕。

DECLARE
  sum_i int:=0;
  i int:=0;
BEGIN
  LOOP
     i:=i+1;
     sum_i:=sum_i+i;
    EXIT WHEN i=100;
  END LOOP;
  dbms_output.put_line(‘前100个自然数的和是:  ’||sum_i);
END; 

WHILE循环

基本语法
WHILE condition LOOP 
        sequence_of_statement;
END LOOP; 

使用while语句求得前100个自然数的和,并输出到屏幕。
DECLARE
 sum_i int:=0;
  i int:=0;
BEGIN
  while i<=99 loop
     i:=i+1;
     sum_i:=sum_i+i;
  END LOOP;
  dbms_output.put_line(‘前100个自然数的和是:  ’||sum_i);
END;

FOR循环

基本语法
FOR loop_counter IN [REVERSE] low_bound..high_bound LOOP
     sequence_of_statement;
END LOOP;
注意:
循环变量不需要显式定义,系统隐含地将它声明为BINARY_INTEGER变量;
系统默认时,循环变量从下界往上界递增计数,如果使用REVERSE关键字,则表示循环变量从上界向下界递减计数;
循环变量只能在循环体中使用,不能在循环体外使用。

使用for语句求得前100个自然数中偶数的和,并输出到屏幕。
Declare
  sum_i int:=0;
  BEGIN
    for i in reverse 1…100 loop
      if mod(i,2)=0 then
      sum_i:=sum_i+i;-
  END if;
  end loop
  dbms_output.put_line(‘前100个自然数中偶数的和是:  ’||sum_i);
 end;

跳转结构

语法格式:
《标号》
  …
  GOTO 标号;
说明:
块内可以跳转,内层块可以跳到外层块,但外层块不能跳到内层。
IF语句不能跳入。不能从循环体外跳入循环体内。不能从子程序外部跳到子程序中。
由于goto语句的缺点,建议尽量少用甚至不用goto语句
DECLARE
   v_counter BINARY_INTEGER :=1;
BEGIN
   <<LABEL>>
   INSERT INTO temp_table VALUES(v_counter, 'Loop index');
   v_counter := v_Counter + 1;
   IF v_counter<=50 THEN
     GOTO LABEL;
   END IF;
END;
发布了36 篇原创文章 · 获赞 26 · 访问量 7582

猜你喜欢

转载自blog.csdn.net/weixin_43566977/article/details/103657150
今日推荐