PL/SQL 基础学习
一、PL/SQL
- 目前的PL/SQL包括两部分:
- 数据库引擎部分:------>数据库PL/SQL
- 独立引擎:可嵌入到许多产品(如C、Java等)工具中;------>工具PL/SQL,
- 两者的编程非常相似,都具有程序结构、语法和逻辑机制。
二、PL/SQL基本结构
- 块
- 标识符
- 数据类型
- 变量
- 赋值语句
1.块的基本结构
- 匿名块:一般在要运行的应用中说明,运行时传递给PL/SQL引擎处理,只能执行一次,不能被存储在数据库中。
- 命名块:是指编译一次之后可以多次执行的PL/SQL块,其中又包括存储过程、存储函数、包、触发器等。
[DECLARE]
/* 声明部分:在此声明PL/SQL用到的变量、类型及游标等 */
BEGIN
/* 执行部分:过程及SQL 语句,即程序的主要部分,实现块的功能*/
[EXCEPTION]
/* 执行异常部分:错误处理 */
END;
/*PL/SQL语句块中执行部分与结束部分是必须的,而声明部分和异常部分是可选的。*/
2.块的嵌套结构
- PL/SQL块可以嵌套使用,对块的嵌套层数没有限制。语法:
[DECLARE]
...... /*声明部分*/
BEGIN
...... /*主块的语句执行部分*/
BEGIN
...... /*子块的语句执行部分*/
[EXCEPTION]
...... /*子块的出错处理程序*/
END;
[EXCEPTION] /*主块的出错处理程序*/
END;
3.标识符
规则:
- 标识符必须以字母开头。
- 标识符可以由一个或多个字母、数字或特殊字符($、#、_)组成。
- 标识符长度不超过30个字符。
- 标识符内不能有空格。
注:lPL/SQL不区分大小写,如果希望标识符区分大小写或包含其他的字符,则可以使用带双引号的标识符,但是标识符的最大长度不能是30个字符(不包括双引号)
4. 数据类型
- PL/SQL变量数据类型有标量类型、参考类型、LOB类型、用户自定义类型;
- 标量类型:
- 数值类型:
number;binary_integer,pls_inteder
; - 字符类型:
VARCHAR2;CHAR; LONG
; - 日期类型:
DATE;TIMESTAMP;INTERVAL
; - 布尔类型:
BOOLEAN(TRUE,FALSE,NULL)
;
- 数值类型:
- 参考类型;
%TYPE
: 定义某个变量或列和原有的类型相同;%ROWTYPE
: 复合类型(多个列);- 大数据对象:
LOB,BFILE,BLOB
; - 自定义类型;创建用户自定义的类型后,该类型就被存储在数据库的数据字典中,数据字典
user_types
和user_objects
中记录此类型。
5.变量
-
变量的命名: 不可以使用保留字 如
BEGIN
和END
; -
变量的定义:
变量名 [CONSTANT] 数据类型 [NOT NULL][ := | DEFAULT PL/SQL表达式]
-
变量的作用域:PL/SQL变量,它的作用域是从该变量被声明开始到变量所在块结束;
6.赋值语句
-
直接赋值
-
变量名 := 常量或表达式;
例如:
v_num NUMBER:=5
;
-
-
通过
SELECT..INTO
语句赋值- 语法格式为:
SELECT 列值 INTO 变量名
- 语法格式为:
部分实例如下:
--定义一个包含子块的PL/SQL块,查询编号为“060001”的教师所在系的教师总人数。
SELECT * FROM TEACHER;
DECLARE
V_NUM NUMBER(10);
BEGIN
SELECT COUNT(*) INTO V_NUM FROM TEACHER WHERE T_DEPARTMENTID=(SELECT T_DEPARTMENTID FROM TEACHER WHERE T_ID=060001);
DBMS_OUTPUT.PUT_LINE('该教师所在系的总人数为:'||V_NUM);
END;
DECLARE
v_NUM NUMBER(20);
V_T_DEP NUMBER(5);
BEGIN
BEGIN
SELECT t_departmentid INTO V_T_DEP FROM TEACHER WHERE T_ID='060001';
END;
SELECT COUNT(*) INTO V_NUM FROM TEACHER WHERE t_departmentid=V_T_DEP;
DBMS_OUTPUT.PUT_LINE('该教师所在系的总人数为:'||V_NUM);
END;
--向职称表中插入一条新职称信息。
SELECT * FROM TITLE;
DECLARE
V_TITLE TITLE%ROWTYPE;
BEGIN
V_TITLE.TITLE_ID:=12;
V_TITLE.TITLE_NAME := '实习生';
INSERT INTO TITLE VALUES(V_TITLE.TITLE_ID,V_TITLE.TITLE_NAME);
COMMIT;
END;
--定义用户自定义的数据类型EMPLOYEES_TYPE。
CREATE OR REPLACE TYPE EMPLOYEES_TYPE
AS
OBJECT
(
ID NUMBER(10),
NAME VARCHAR2(20)
);
三、控制结构
1.分支结构
- IF语句
IF condition1 THEN
statement1;
ELSIF condition2 THEN
statement12;
ELSE
statement3;
END IF;
实例:
--7:查询系别号为1的教师人数是否超过5人。
SELECT * FROM TEACHER;
DECLARE
V_COUNT NUMBER(10);
BEGIN
SELECT COUNT(*) INTO V_COUNT FROM TEACHER WHERE t_departmentid=1;
IF V_COUNT >5 THEN
DBMS_OUTPUT.PUT_LINE('系别号为1的教师人数超过5人!');
ELSE
DBMS_OUTPUT.PUT_LINE('系别号为1的教师人数没有超过5人!');
END IF;
END;
--9:判断3个数中的最大值。
DECLARE
V_NUMBER1 NUMBER(10):=100;
V_NUMBER2 NUMBER(10):=20;
V_NUMBER3 NUMBER(10):=500;
BEGIN
IF V_NUMBER1 > V_NUMBER2 AND V_NUMBER1 > V_NUMBER3 THEN
DBMS_OUTPUT.PUT_LINE('三个数中最大的为:'||V_NUMBER1);
ELSIF V_NUMBER2 > V_NUMBER1 AND V_NUMBER2>V_NUMBER3 THEN
DBMS_OUTPUT.PUT_LINE('三个数中最大的为:'||V_NUMBER2);
ELSE
DBMS_OUTPUT.PUT_LINE('三个数中最大的为:'||V_NUMBER3);
END IF;
END;
- CASE语句
CASE 变量
WHEN 值1 THEN statement1;
WHEN 值2 THEN statement2;
...
[ELSE statementS;]
END CASE;
实例:
--10:用CASE语句判断v_grade变量的值是否等于A、B、C、D、E,并分别处理。
DECLARE
V_GRADE VARCHAR2(20):='B';
BEGIN
CASE V_GRADE
WHEN 'A' THEN
DBMS_OUTPUT.PUT_LINE('优秀');
WHEN 'B' THEN
DBMS_OUTPUT.PUT_LINE('良好');
WHEN 'C' THEN
DBMS_OUTPUT.PUT_LINE('一般');
WHEN 'D' THEN
DBMS_OUTPUT.PUT_LINE('及格');
WHEN 'E' THEN
DBMS_OUTPUT.PUT_LINE('不及格');
ELSE
DBMS_OUTPUT.PUT_LINE('没有成绩');
END CASE;
END;
2.循环结构
- 循环语句的基本形式有以下3种:
- 简单循环(
LOOP...END LOOP
); - WHILE循环(
WHILE ...LOOP...END LOOP
); - OR循环(
FOR...LOOP...END LOOP
)
- 简单循环(
- 退出循环的语法格式如下:
EXIT WHEN 条件
;IF 条件 THEN EXIT; END IF
;
注:
-
在简单循环和WHILE循环中,需要定义循环变量,不断修改循环标量的值,以达到控制循环次数的目的;
-
在FOR循环中,不需要定义循环变量,系统自动定义一个循环变量,每次循环变量的值自动增1或者减1,以控制循环的次数。
-
简单循环
- 简单循环的循环体至少执行一次,其语法格式如下:
LOOP statement; [EXIT;] END LOOP
--13:使用LOOP语句实现输出1-5之间的平方数。 DECLARE I NUMBER(5) :=1; BEGIN LOOP DBMS_OUTPUT.PUT_LINE(I||'的平方:'||I*I); I:=I+1; EXIT WHEN I>5; END LOOP; END; --14:使用LOOP循环向表中插入30条记录 SELECT * FROM TITLE; DECLARE I NUMBER(32) :=13; BEGIN LOOP INSERT INTO TITLE VALUES(I,'工程师'); I:=I+1; DBMS_OUTPUT.PUT_LINE('插入成功'); EXIT WHEN I>43; END LOOP; END;
-
WHILE循环
- l语法格式如下:
WHILE condition LOOP statement; END LOOP;
--WHILE 输出1-5之间的平方数。 DECLARE I NUMBER(5) :=1; BEGIN WHILE(I<=5) LOOP DBMS_OUTPUT.PUT_LINE(I||'的平方:'||I*I); I:=I+1; END LOOP; END; --14:使用WHILE循环向表中插入30条记录 SELECT * FROM TITLE; DECLARE I NUMBER(20) :=44; BEGIN WHILE (I<=73) LOOP INSERT INTO TITLE VALUES(I,'教授'); I:=I+1; DBMS_OUTPUT.PUT_LINE('插入成功'); END LOOP; END;
-
FOR循环
- 语法格式格式如下:
FOR loop_counter IN [REVERSE] lower_bound .. upper_bound LOOP statement; END LOOP;
注:
- 在执行FOR…LOOP语句时,循环变量被隐式地定义为INTEGER类型的局部变量,其值为初始值,所以不必显式地定义循环变量。默认情况下,循环变量从初始值递增到结束值,如果使用关键字
REVERSE
,则循环变量从结束值递减到初始值。但是无论循环变量是递增还是递减,初始值都必须小于结束值,且增量(减量)必须是1。 - 在FOR…LOOP语句中,可以像引用常量一样引用循环变量。因此,循环变量可以使用表达式,但不可以对其赋值。
- 循环变量的初始值和结束值可以是数据、变量或表达式,但值必须是整数。
- PL/SQL允许在执行时动态制定循环变量的初始值和结束值。
- 循环变量仅在循环语句中有效,当退出循环时,循环变量无效。
- 因为循环变量被隐式地定义为局部变量,所以任何同名的全局变量都被该变量覆盖。如果要引用全局变量,则必须使用标号和点号。
- 如果在嵌套的循环语句中,内层和外层的循环变量名相同,这时要在内部循环中使用外部循环的循环变量,必须使用标号和点号。
--13:使用FOR语句实现输出1-5之间的平方数。
DECLARE
I NUMBER(5) :=1;
BEGIN
FOR V_COUNTER IN 1 .. 5 LOOP
DBMS_OUTPUT.PUT_LINE(I||'的平方:'||I*I);
I:=I+1;
END LOOP;
END;
--14:使用FOR循环向表中插入30条记录
SELECT * FROM TITLE;
DECLARE
I NUMBER(20) :=74;
BEGIN
FOR V_COUNTER IN 74 .. 104 LOOP
INSERT INTO TITLE VALUES(I,'副教授');
I:=I+1;
DBMS_OUTPUT.PUT_LINE('插入成功');
END LOOP;
END;
--18:用FOR循环结构求10的阶乘。
DECLARE
I NUMBER(20) :=1;
V_SUM NUMBER(30):=1;
BEGIN
FOR V_COUNTER IN 1 .. 10 LOOP
V_SUM:=V_SUM*I;
I:=I+1;
END LOOP;
DBMS_OUTPUT.PUT_LINE(I||'的阶乘为:'||V_SUM);
END;
--19:反向输出1到5之间的整数。
BEGIN
FOR V_COUNTER IN REVERSE 1 .. 5 LOOP
DBMS_OUTPUT.PUT_LINE(V_COUNTER);
END LOOP;
END;
--20:计算10、20…100的累加和。
DECLARE
V_SUM NUMBER(10):=0;
BEGIN
FOR I IN 1 .. 100 LOOP
IF MOD(I,10)=0 THEN
V_SUM:=V_SUM+I;
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE(V_SUM);
END;