You are on page 1of 10

一、基 础与概念

1、PL/SQL 不区分大小写,除非是由引号引起来的字符串。
1、

2、 PL/SQL 标 识 符 的 命 名 规 则

标识符的最大长度是 30 个字符,包括字母,数字,$,_,#
不可包含保留字
要以字来打头
不能和同一块中的表中的字段名一样
3、命名规范

sql*plus substitution variable p_name


variable v_name
constant c_name
sql*plus global variable g_name
exception e_name
4、注销方式
--注释内容
/*……注释内容………….*/
5、只要表达式里有 NULL,则整个表达式的值为 NULL
BOOLEAN 和 NULL
这里要注意的是:NULL AND TRUE ==NULL
NULL AND FALSE==FALSE
NULL OR TRUE==TRUE
NULL OR FALSE ==NULL
6、PL/SQL Environment
PL/SQL Blcok-----mon-sql-----procedural statement executor
-----sql------------sql statement executor
7、分类
procedures:执行一个动作,做为一个 pl/sql 来执行,可以返回一个值
function:计算一个值,用于嵌入到表达式中,并必须返回一个值
package:把函数和过程逻辑的关联起来

8、pl/sql block structure


header: Contains the subprogram name, type, and arguments.Only
used for subprograms.
Declarative: Contains the local identifiers for the block.
Executable: Contains the SQL statements and PL/SQL control
statements.
Exception: Performs actions when errors occur.

9、 DCL 和 DDL 都不被 pl/sql 支持。DML 和 commit 可以被支持.

10、 一个嵌套块成为封闭块里的一个可执行语句,一个块可嵌套在任何允许放
置可执行语句的地方,包括执行部分和异常处理部分。

11、 PL/SQL 表达式不能包含组函数,但一个 PL/SQL 块里的 SQL 语句可以。


12、当一个语句中有混合的数据类型时,PL/SQL 可以动态转变。如:想把一个
NUMBER 值存进一个 VARCHAR2 的变量里,PL/SQL 会动态地把 NUMBER 值转变为
VARCHAR2 类型的字符值。

13、 PL/SQL 表达式可以包含 SQL 函数。


14、嵌套块里的语句不能包含一个异常段。
15、PL/SQL 中的 SELECT 语句必须使用 INTO 子句。
2、 数据类 型:
1) Base Scalar Datatypes
2) •

 VARCHAR2 :在 PL/SQL 中可以存储 2000,在 oracle8 中是 4000 字

 NUMBER [(precision, scale)]:当声明时。默认值是 null,

指数用 1 个字节
尾数中的每两个有效数字用 1 个字节
负数用 1 个字节
 DATE:存储日期型
 CHAR [(maximum_length)]: 如没有指定,数据类型为 CHAR 的列默
认长度为 1。这个长度的范围是 1 到 2000。
 LONG:用于长度不定,最大值为 2G 的字符型数据。
 Row 用来存二进制,在 PL/SQL 中最大长度是 32767,在 oracle8 中
是 255 字节
 LONG RAW:可以容纳 raw binary data
 BOOLEAN:只能为 true or false or null
 BINARY_INTEGER
 ROWID 数据类型:ROWID 是数据库中每行的唯一标识符,ROWID 在
磁盘上需要 10 个字节的存储空间,并使用 18 个字符来显示
 PLS_INTEGER

2) Composite Datatypes

 PL/SQL TABLES:
Primary Key:KEY 的类型是 BINARY_INTEGER
VALUE:真正的值
声明:TYPE type_name IS TABLE OF
{column_type | variable%TYPE | table.column%TYPE} [NOT
NULL]
[INDEX BY BINARY_INTEGER];
identifier type_name;
eg1:TYPE t_nametable IS TABLE OF VARCHAR(2)
INDEX BY BINARY_INTEGER;
引用:t_nametable(1):=’jact’
eg2:
DECLARE
TYPE dept_table_type IS TABLE OF dept%ROWTYPE
INDEX BY BINARY_INTEGER;
dept_table dept_table_type;
引用:dept_table(1).row1:=’jact’;

 PL/SQL RECORDS
定义: TYPE type_name IS RECORD
(field_declaration[, field_declaration]…);
identifier type_name;

TYPE record_name IS RECORD(


name varchar(20),
id number(9)
)
引用:
student record_name
student.name
student.id

3) 3)
4) Lob: 用来存二进制,最大长度是 4GB

CLOB:RECIPE
BLOB:PHOTO(可以容纳 4G 的二进制)
BFILE:MOVIE 把二进制存在一个扩展的文件中。容量是 4G
NCLOB

三、 PL/SQ L B lock Stru ctur e


DECLARE---Optional
-Variables,Constants,cursors,user-defined exceptions
BEGIN---Mandatory
-SQL statements
-PL/SQL control statements
EXCEPTION-Optional
-Actions to perform when errors occur
END:---Mandatory
Block typ e
Anonymous:[DECLARE]
BEGIN
……..
[EXCEPTION]
END;
Procedure:PROCEDURE name IS
[DECLARE]
BEGIN
……..
[EXCEPTION]
END;
Function:FUNTION name
RETURN datatype IS
[DECLARE]
BEGIN
……..
RETURN value;
[EXCEPTION]
END;

四、变 量
1、变量的赋值:identifier [CONSTANT] datatype [NOT NULL] [:= | DEFAULT
expr];
2、
变量名 number(9,2) NOT NULL :=0; // 在声明一个 PL/SQL 参数时,可以使用赋值
运算符 := 为该参数赋初值。如果没有为参数赋初值,参数会被设置为 null。如果参
数被定义 NOT NULL 约束,那么就必须赋初值。
3、变量的类型:变量名 number(9,2);
变量名 saray%type; //这样 value 的类型就和 saray 一样,也可以
用列名取代 saray
变量名 parts%rowtype
//parts 是表名,这是个记录类型的变量。其内部结构和 parts 一样
是根据表或视图的列来定义各变量
用表名做为前缀
结构和表的结构一样
4、在 PL/SQL 调用 sqlplus 的变量,在变量前面加”:”
:g_monthly_sal := v_sal / 12;

五、控 制程序流
1、 loop
程序段
exit [ when 表达式]
end loop;
可以为循环设定标签
EG:
BEGIN
<<Outer_loop>>
LOOP
v_counter := v_counter+1;
EXIT WHEN v_counter>10;
<<Inner_loop>>
LOOP
...
EXIT Outer_loop WHEN total_done = 'YES';
-- Leave both loops
EXIT WHEN inner_done = 'YES';
-- Leave inner loop only
...
END LOOP Inner_loop;
...
END LOOP Outer_loop;
END;

2、 while 表 达 式 loop
程序段
end loop;
3 、 for I in 1 .. 20 loop
程序段
end loop;
4、if [not]…..then
程序段
elsif ….then
程 序 段
else
程序段
end if;
5、 message1
<<message1>>
a:=a+1
注意:不可以同外层跳到里层
不可以从一个 IF 子句跳到另一个 IF 子句
不可以从异常处理块跳到当前块
6、 select into 为 变 量 赋 值
select name into v_name where …

六、游 标
游标的本质是 SQL 语句的一个工作区域,用于处理多行记录集的查询。
分类:Implicit cursors:由 DML 和 PL/SQL 的 SELECT 隐式的定义,不可以使用
open,fetch 和 close 去控制这个 sql 游标。每一次只处理一行。但是可
以使用游标的属性

Explicit cursors:由程序员定义, 显式游标用于返回多于一行的查询

以下讨论的都是显式游标
执行的 四个步骤

1、
1、 声明:定义游标的名字和结构,select 中可以使用 order by

2、 打开游标:执行查询同时绑定所有涉及到的变量
执行的内容:
为 select 分配内存并分析 select 语句
绑定输入的变量
配置指针在活动集的第一行
注 意 : 如果 查询不返回结果,不会引发 PL/SQL 的异常,你可以在执行 fetch
后测试返回的结果
如果游标内的声明包括 update。一样会执行行锁定
3、 Fetch:把当前行的值赋给变量,每个 fetch 都会把游标指针向下移动一行。
如果到了最后一行就会自动退出 for loop

4、 关 闭 : 释 放 活 动 的 集 , 可 以 再 次 使 用 open

游标的 几个属性 :
SQL%ROWCOUNT 受 最 近 执 行 的 SQL 语 句 影 响 的 行 的 数 目 。 ( 一 个 整 数 值 )
SQL%FOUND Boolean 属 性 , 如 果 最 近 的 SQL 语 句 影 响 了 一 行 或 多 行 , 其 值 为
TRUE 。
SQL%NOTFOUND Boolean 属 性 , 如 果 最 近 的 SQL 语 句 没 有 影 响 任 何 行 , 其 值 为
TRUE 。
SQL%ISOPEN 总是为 FALSE,原因是 PL/SQL 总是它们结束执行后立即关闭内隐游标。

例子
EG1:常规用法
CURSOR c1 IS
SELECT empno, ename
FROM emp;
emp_record c1%ROWTYPE;
BEGIN
OPEN c1;
. . .
FETCH c1 INTO emp_record;

EG2:使用 for 循环实现游标


DECLARE
CURSOR c1 IS
SELECT empno, ename
FROM emp;
emp_record c1%ROWTYPE;
BEGIN
FOR emp_record IN c1 LOOP
-- implicit open and implicit fetch occur
IF emp_record.empno = 7839 THEN
...
END LOOP; -- implicit close occurs
END;
游标 FOR 循环立时不需要 FETCH 语句的。游标打开,在循环中每次重复提取一行,所有
的行都处理后,游标会自动关闭。
EG3:不定义游标的方式
BEGIN
FOR emp_record IN ( SELECT empno, ename
FROM emp) LOOP
-- implicit open and implicit fetch occur
IF emp_record.empno = 7839 THEN
...
END LOOP; -- implicit close occurs
END;
EG4
:带变量的游标------ 你必须指定指定参数的数据类型,但不用指定大小
DECLARE
CURSOR c1
(v_deptno NUMBER, v_job VARCHAR2) IS
SELECT empno, ename
FROMemp
WHERE deptno = v_deptno
AND job = v_job;
BEGIN
OPEN c1(10, 'CLERK');
...

EG5:FOR UPDATE----实际上是把 select 出来的记录都加锁。其他事务不能对这些记


录加锁或者 update 这些。
SELECT ... FROM ...
FOR UPDATE [OF column_reference][NOWAIT]
DECLARE
CURSOR c1 IS
SELECT empno, ename
FROM emp
FOR UPDATE NOWAIT;

NOWAIT:返回一个 oracle 的错误信息如果此行给其他的会话锁住了。

EG6:WHERE CURRENT OF: 对于游标来说,处理记录的时候,是一条一条记录来处


理的,使用 WHERE CURRENT OF,实际上就是指明是游标正在处理的当前行记录。

注意:必须使用 FORUPDATE 去锁住行


使用 WHERE CURRENT OF 去指向当前的行
DECLARE
CURSOR c1 IS
SELECT ...
FOR UPDATE NOWAIT;
BEGIN
...
FOR emp_record IN c1 LOOP
UPDATE ...
WHERE CURRENT OF c1;
...
END LOOP;
COMMIT;
END;

七、处 理异常
Predefined Exception
BEGIN SELECT ... COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
statement1;
statement2;
WHEN TOO_MANY_ROWS THEN
statement1;
WHEN OTHERS THEN
statement1;
statement2;
statement3;
END;

…….
Non-Predefined Exception
DECLARE
e_products_invalid EXCEPTION;
PRAGMA EXCEPTION_INIT (
e_products_invalid, -2292);
v_message VARCHAR2(50);
BEGIN
. . .
EXCEPTION
WHEN e_products_invalid THEN
:g_message := 'Product code
specified is not valid.';
. . .
END;
User-Defined Exception

DECLARE
e_amount_remaining EXCEPTION;
. . .
BEGIN
. . .
RAISE e_amount_remaining;
. . .
EXCEPTION
WHEN e_amount_remaining THEN
:g_message := 'There is still an amount
in stock.';
. . .
END;

RAISE_APPLICATION_ERROR

DECLARE
…….
Invalidpart EXCEPTION;
BEGIN
…….
IF SQL%NOTFOUND THEN
RAISE invalidpart;
END IF;
EXCEPTION
WHEN invalidpart THEN
Raise_application_error(-20003,’Invalid Part id #’|| partnum);
WHEN OTHERS THEN
Raise_application_error(-20000,errNum||errMsg);
END
 使用 EXCEPTION 关键字在一个 PL/SQL 块的声明部分声明用户自定义异常
 使用 PL/SQL 命令 RAISE 检测用户自定义异常
 PL/SQL 可使用 Raise_application_error 过程返回一个用户自定义错误数和消息给调用环
境。所有的用户自定义错误消息必须在-20000 到-20999 之间
 PL/SQL 程序可以使用 WHEN OTHERS 异常处理来处理没有特定处理的所有异常
 PL/SQL 程序可以使用特殊的 SQLCODE 和 SQLERRM 函数返回最新的 oracle 错误号码
和消息
DECLARE
v_error_code NUMBER;
v_error_message VARCHAR2(255);
BEGIN
...
EXCEPTION
...
WHEN OTHERS THEN
ROLLBACK;
v_error_code := SQLCODE ;
v_error_message := SQLERRM ;
INSERT INTO errors VALUES(v_error_code,
v_error_message);
END;

数据库 联接
定义:CREATE DATABASE LINK link_name
CONNECT TO username IDENTIFIED BY password
USING sqlnet_string;
使用:表名@link_name

替代名
CREATE SYNONYM synonym_name FOR reference;
Eg:CREATE SYNONYM backup FOR backup@esal