PL/SQL 块语法(匿名块)
[DECLARE]
---declaration statements
BEGIN
---executable statements
[EXCEPTION]
---exception statements
END
Ø 函数
定义函数的语法如下:
FUNCTION name [{parameter[,parameter,...])] RETURN datatypes IS
[local declarations]
BEGIN
execute statements
[EXCEPTION
exception handlers]
END [name]
Ø 存储过程
与函数不同,存储过程没有返回值,存储过程
不能由SQL 语句直接使用,只能通过EXECUT 命令或PL/SQL 程序块内部调用,定义存
储过程的语法如下:
PROCEDURE name [(parameter[,parameter,...])] IS
[local declarations]
BEGIN
execute statements
[EXCEPTION
exception handlers ]
END [name]
Ø 声明变量的语法如下:
Variable_name [CONSTANT] databyte [NOT NULL][:=|DEFAULT expression]
注意:可以在声明变量的同时给变量强制性的加上NOT NULL 约束条件,此时变量在初
始化时必须赋值。
给变量赋值
给变量赋值有两种方式:
1.直接给变量赋值
X:=200;
Y=Y+(X*20);
2.通过SQL SELECT INTO 或FETCH INTO 给变量赋值
SELECT SUM(SALARY),SUM(SALARY*0.1) INTO TOTAL_SALARY,TATAL_COMMISSION FROM EMPLOYEE WHERE DEPT=10;
Ø 常量
常量与变量相似,但常量的值在程序内部不能改变,常量的值在定义时赋予,他的声
明方式与变量相似,但必须包括关键字CONSTANT。常量和变量都可被定义为SQL 和用
户定义的数据类型。
ZERO_VALUE CONSTANT NUMBER:=0;
Ø LOB 数据类型
LOB(大对象,Large object) 数据类型用于存储类似图像,声音这样的大型数据对象,
LOB 数据对象可以是二进制数据也可以是字符数据,其最大长度不超过4G。LOB 数据类
型支持任意访问方式,LONG 只支持顺序访问方式。LOB 存储在一个单独的位置上,同时
一个"LOB 定位符"(LOB locator)存储在原始的表中,该定位符是一个指向实际数据的指针。
在PL/SQL 中操作LOB 数据对象使用ORACLE 提供的包DBMS_LOB.LOB 数据类型可分
为以下四类:
. BFILE
. BLOB
. CLOB
. NCLOB
Ø 操作符
= 等于操作符
!= 不等于操作符
<> 不等于操作符
:= 赋值操作
定义语言(Data Definition language)不能在执行部分中使用,DDL 语句与EXECUTE
IMMEDIATE 一起使用或者是DBMS_SQL 调用。
Ø IF判断
IF condition THEN
Statements 1;
Statements 2;
....
ELSE
Statements 1;
Statements 2;
....
END IF
Ø 循环控制
LOOP
statements;
END LOOP
例:
X:=100;
LOOP
X:=X+10;
IF X>1000 THEN
EXIT;
END IF
END LOOP;
Y:=X;
EXIT WHEN 语句将结束循环,如果条件为TRUE,则结束循环。
X:=100;
LOOP
X:=X+10;
EXIT WHEN X>1000;
X:=X+10;
END LOOP;
Y:=X;
WHILE..LOOP
X:=100;
WHILE X<=1000 LOOP
X:=X+10;
END LOOP;
Y=X;
FOR...LOOP
语法:
FOR counter IN [REVERSE] start_range....end_range LOOP
statements;
END LOOP;
X:=100;
FOR v_counter in 1..10 loop
x:=x+10;
end loop
y:=x;
Ø PL/SQL 记录
显式定义记录
TYPE record_type IS RECORD (field_definition_list);
例:
DELCARE
TYPE stock_quote_rec IS RECORD
(symbol stock.symbol%TYPE
, bid NUMBER(10,4)
, ask NUMBER(10,4)
, volume NUMBER NOT NULL:=0
, exchange VARCHAR2(6) DEFAULT 'NASDAQ'
);
real_time_quote stock_quote_rec;
variable
域定义时的%TYPE 属性用于引用数据库中的表或视图的数据类型和大小。
隐式定义记录
隐式定义记录中,我们不用描述记录的每一个域。这是因为我们不需要定义记录的结构,
不需要使用TYPE 语句,相反在声明记录变量时使用%ROWTYPE 命令定义与数据库表,
视图,游标有相同结构的记录,与TYPE 命令相同的是它是一种定义获得数据库数据记录
的好方法。
DECLARE
accounter_info accounts%ROWTYPR;
CURSOR xactions_cur(acct_no IN VARCHAR2) IS
SELECT action,timestamp,holding
FROM portfolios
WHERE account_nbr='acct_no';
xaction_info xactions_cur%ROWTYPE;
variable
有一些PL/SQL 指令在使用隐式定义记录时没有使用%ROWTYPE属性,比如游标
FOR 循环或触发器中的:old 和:new 记录。
DELCARE
CURSOR xaction_cur IS
SELECT action,timeamp,holding
FROM portfolios
WHERE account_nbr='37'
;
BEGIN
FOR xaction_rec in xactions_cur
LOOP
IF xactions_rec.holding='ORCL'
THEN
notify_shareholder;
END IF;
END LOOP;
Ø 给记录赋值
1、使用SELECT INTO
DECLARE
stock_info1 stocks%ROWTYPE;
stock_info2 stocks%ROWTYPE;
BEGIN
SELECT symbol,exchange
INTO stock_info1.symbol,stock_info1.exchange FROM stocks
WHERE symbol='ORCL';
SELECT * INTO stock_info2 FROM stocks
WHERE symbol='ORCL';
2、使用FETCH
如果SQL 语句返回多行数据或者希望使用带参数的游标,那么就要使用游标,这种情
况下使用FETCH 语句代替INTO 是一个更简单、更有效率的方法,但在安全性
较高的包中FETCH 的语法如下:
FETCH cursor_name INTO variable;
我们改写上面的例子:
DECLARE
CURSOR stock_cur(symbol_in VARCHAR2) IS
SELECT symbol,exchange,begin_date
FROM stock
WHERE symbol=UPPER(symbol_in);
stock_info stock_cur%ROWTYPE
BEGIN
OPEN stock_cur('ORCL');
FETCH stock_cur INTO stock_info;
触发器(Triggers)
触发器是一种自动执行响应数据库变化的程序。可以设置为在触发器事件之前或之后触
发或执行。能够触发触发器事件的事件包括下面几种:
DML 事件
DDL 事件
数据库事件
DML 事件触发器可以是语句或行级触发器。DML 语句触发器在触发语句之前或之后触
发DML 行级触发器在语句影响的行变化之前或之后触发。用户可以给单一事件和类型定义
多个触发器,但没有任何方法可以增强多触发器触发的命令。下表列出了用户可以利用的触
发器事件:
INSERT 当向表或视图插入一行时触发触发器
UPDATE 更新表或视图中的某一行时触发触发器
DELETE 从表或视图中删除某一行时触发触发器
CREATE 当使用CREATE 语句为数据库或项目增加一个对象时触发触发器
ALTER 当使用ALTER 语句为更改一个数据库或项目的对象时触发触发器
DROP 当使用DROP 语句删除一个数据库或项目的对象时触发触发器
START 打开数据库时触发触发器,在事件后触发
SHUTDOWN 关闭数据库时触发,事件前触发
LOGON 当一个会话建立时触发,事件前触发
LOGOFF 当关闭会话时触发,事件前触发
SERVER 服务器错误发生时触发触发器,事件后触发
创建触发器的语法如下:
CREATE [OR REPLACE] TRIGGER trigger_name
{before|after|instead of} event
ON {table_or_view_name|DATABASE}
[FOR EACH ROW[WHEN condition]]
trigger_body
只有DML 触发器(INSERT、UPDATE、DELETE)语句可以使用INSTEAD OF 触发
器并且只有表的DML 触发器可以是BEFORE 或AFTER 触发器。
Ø 游标