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;