您的位置:首页 > 数据库 > Oracle

《Oracle Database 11g SQL 开发指南》学习笔记——第11章_PL/SQL编程简介

2012-09-04 16:57 441 查看
11.1、块结构

[DECLARE

declaration_statements

]

BEGIN

executable_statements

[EXCEPTION

exception_handing _statements

]

END;

/

每一条语句都由';'结尾,PL/SQL块由‘/’结尾。 SET SERVEROUTPUT ON命令打开服务器输出。

还可以用%TYPE关键字来定义变量类型,它告诉PL/SQL使用与表中列相同的类型。

11.3、在PL/SQL中,IF、THEN、 ELSE、ELSEIF、ENDIF等关键字来执行条件逻辑,还可以嵌套使用。

11.4、循环。

简单循环、while循环、for循环。

11.4.1、简单循环:直到显式结束循环之前一直运行。

LOOP

ststement

END LOOP; 要结束可以使用exit或exit when语句。

如:v_count :=0; loop v_count := v_count+1;

exit when v_count= 5; end loop;

在Oracle 11g中也可以使用CONTINUE 或CONTINUE WHEN 语句结束当前迭代;

如:v_count :=0; loop v_count := v_count+1;

if v_count = 3 then continue; end if ;

或者将此行换为:CIONTINUE WHEN v_count = 3;

exit when v_count= 5; end loop;

11.4.2、WHILE 循环:在某个条件出现之前一直运行。

如:v_count := 0; WHILE v_count<6

LOOP v_count := v_count+1; END LOOP;

11.4.3、FOR循环:预先确定次数。

如:FOR c IN [ REVERSE ] 1..5

LOOP

dbms_output.put_line(c);

END LOOP;

11.5、游标:可以使用游标(cursor)获取查询返回的记录。

步骤如下:1、声明一些变量,用于保存记录的列值。(注意使用%TYPE,类型要兼容)

2、声明游标并指定查询。(放在声明中:CURSOR cursor_name IS select_statement;)

3、打开游标。(在执行中:OPEN cursor_name)

4、每次从游标中获取一条记录,并将列值存储在第一步声明的变量中,然后对这些变量执行操作

FETCH cursor_name INTO variable[, variable···];

游标可能包含很多条记录,因此要使用循环,为确定循环是否结束,可以使用布尔变量coursor_name%NOTFOUND.

5、关闭游标。CLOSE cursor_name;

例如:SET SERVEROUTPUT ON

DECLARE

v_product_id products.product_id%TYPE;

v_name products.product_name%TYPE;

v_price products.product.price%TYPE;

CURSOR v_product_cursor IS

SELECT product_id name price FROM propucts ORDER BY product_id;

BEGIN

OPEN v_product_cursor;

LOOP

FETCH v_product_cursor

INTO v_product_id, v_name, v_price

EXIT WHEN v_product_cursor%NOTFOUND;

END LOOP;

END;

11.5.7、游标与FOR循环

利用for循环可以访问游标中的记录。当使用for循环时,可以不显式的打开和关闭游标——for循环会自动执行这些操作。

FOR record_name IN cursor_name LOOP statement1; statement2;··· ; END LOOP;不需要事先声明循环的记录型变量。

隐含open, fetch, 和close。

重写上例:SET SERVEROUTPUT ON

DECLARE

CURSOR v_product_cursor IS

SELECT product_id name price FROM propucts ORDER BY product_id;

BEGIN

FOR v_product IN v_product_cursor LOOP

DBMS.OUTPUT.PUT_LINE( v_product.product_id || v_product.name || v_product.price )

END LOOP;

END;

11.5.8、OPEN-FOR语句

DECLARE

TYPE t_product_cursor IS REF CURSOR RETURN products%ROWTYPE;声明一个 REF CURSOR类型

v_product_cursor t_product_cursor;

v_product products%ROWTYPE;

BEGIN

OPEN v_product_cursor FOR SELECT * FROM products WHERE product_id < 5;

LOOP

FETCH v_product_cursor INTO v_product;

EXIT WHEN v_product_cursor%NOTFOUND;

DBMS.OUTPUT.PUT_LINE( v_product.product_id || v_product.name || v_product.price );

END LOOP;

CLOSE v_product_cursor;

END;

REF CURSOR是一个指向游标的指针,这样声明的t_product_cursor结合OPEN FOR 语句就可以重用。

11.5.9、无约束游标

前面的游标都有具体的返回类型,称为约束游标;其返回类型必须与游标运行的查询中的列相匹配。无约束油表没有返回类型,因此可以运行任何查询。

DECLARE

TYPE t_cursor IS REF CURSOR ;声明一个 REF CURSOR类型,没有返回类型。

v_cursor t_cursor;

v_product products%ROWTYPE;

v_customer customers%ROWTYPE;

BEGIN

OPEN v_cursor FOR SELECT * FROM products WHERE product_id < 5;

LOOP

FETCH v_cursor INTO v_product;

EXIT WHEN v_cursor%NOTFOUND;

DBMS.OUTPUT.PUT_LINE( v_product.product_id || v_product.name || v_product.price );

END LOOP;

OPEN v_cursor FOR SELECT * FROM customers WHERE customer_id < 3;

LOOP

FETCH v_cursor INTO v_customer;

EXIT WHEN v_cursor%NOTFOUND;

DBMS.OUTPUT.PUT_LINE( v_customer.customer_id || v_customer.name );

END LOOP;

CLOSE v_cursor;

END;

11.6、异常。

系统预定义的异常:

ACCESS_INTO_NULL(ORA-06530):给未初始化对象赋值。

CASE_NOT_FOUND(ORA-06592):case中未找到匹配的when子句,也没有默认的else。

COLLECTION_IS_NULL(ORA-06531):试图将除exists之外的集合方法应用到一个未初始化的嵌套表或变长数组上。或企图给他们赋值。

CURSOR_ALREADY_OPEN(ORA-06511):试图打开已经打开的游标。

DUP_VAL_ON_INDEX(ORA-00001):试图向有唯一索引约束的列中插入重复值。

INVALID_CURSOR(ORA-01001):程序试图进行非法的游标操作。

INVALID_NUMBER(ORA-01722):试图将字符串转换成数字数字时失败。

LOGIN_DENIED(ORA-01017):试图用非法的用户名和密码连接数据库。

NO_DATA_FOUNC(ORA-01403):SELECT INTO 语句没有返回任何记录,或试图访问嵌套表中已经删除的元素,或者试图在表索引中访问未初始化的元素。

NOT_LOGGED_ON(ORA-01012):试图在连接数据库之前访问数据库中的数据。

PROGRAM_ERROR(ORA-06501):PL/SQL内部错误。

ROWTYPE_MISMATCH(ORA-06504):赋值中的宿主游标变量和PL/SQL游标变量返回类型不兼容。

SELF_IS_NULL(ORA-30625):试图在空对象中的调用MEMBER方法。

STORAGE_ERROR(ORA-06500):PL/SQL内存用尽,或内存出现问题。

SUBSCRIPT_BEYOND_COUNT(ORA-06533):试图通过大于集合中元素个数的索引值引用嵌套表或变长数组元素。

SUBSCRIPT_OUTSIDE_LIMIT(ORA-06532):试图通过合法范围之外的索引值(如-1)引用嵌套表或变长数组元素。

SYS_INVALID_ROWID(ORA-01410):将字符串转换成通用记录号rowid的操作失败,原因是该字符串并非合法的rowid。

TIMEOUT_ON_RESOURCE(ORA-00051):当数据库等待某项资源时发生超时。

TOO_MANAY_ROWS(ORA-01422):SELECT INTO 语句返回记录数多于一条。

VALUE_ERROR(ORA-06502):发生算数、转换、截或大小约束错误。

ZERO_DIVIDE(ORA-01476):试图用0除某个数字。

11.7、过程

11.7.1、创建存储过程

CREATE [ OR REPLACE ] PROCEDURE procedure_name [(parameter_name [IN | OUT | IN OUT ] type [,··· ]) ]

{IS | AS }

BEGIN

procedure_body

END;

11.7.2、调用过程,update_products_price( id ,p_factor)

位置表示法:CALL update_products_price( 1,1.5);

11g新增:命名表示法:CALL update_products_price( id=>1 ,p_factor=>1.5);

两种方式合起来是混合表示法。

11.7.3、获取有关过程的信息

从all_procedures中可以获得有关要访问的所有过程信息。

11.7.4、删除过程:DROP PROCEDURE update_products_price;

11.7.5、查看过程中的错误:SHOW ERRORS

11.8、函数

11.8.1、创建函数:CREATE [ OR REPLACE ] FUNCTION

function_name [(parameter_name [IN | OUT | IN OUT ] type [,··· ]) ]

RETURN type

{IS | AS }

BEGIN

function_body

END function_name;

例如:创建一个计算圆面积的函数:

CREATE FUNCTION circle_area (p_radius IN NUMBER )

RETUN NUMBRE

AS v_pi number :=3.1415926;

v_area number;

BEGIN

v_area := v_pi*POWER(p_radius,2);

RETURN v_area;

END circle_area;

11.8.2、调用函数:可以像调用其他数据库内置函数那样调用自定义的函数;

select circle_area(2) from dual;

oracle11g中可以使用命名表示法和混合表示法:select circle_area(p_radius =>2) from dual;

11.8.3、获取有关函数的信息

可以从user_procedures视图中获得有关函数的信息。

11.8.4、删除函数:DROP FUNCTION circle_area;

11.9、包。

包包含两部分:规范和包体;包的规范列出可用的过程、函数、类型、对象。所有数据库用户都可以访问这些条目,

因此称为公有项目。包体中任何没有在规范中列出的项目对于包体都是私有的对象。

11.9.1、创建包规范

CREATE [ OR REPLACE ] PACKAGE package_name

{ IS | AS }

package_specification

END package_name;

例如:CREATE PACKAGE product_package AS

TYPE t_ref_cursor IS REF CURSOR;

FUNCTION get_products_ref_cursor RETURN t_ref_cursor;

PROCEDURE update_product_price ( p_id IN products.product_id%TYPE, p_factor IN number);

END product_package;

11.9.2、创建包体

CREATE [ OR REPLACE ] PACKAGE BODY package_name

{ IS | AS }

package_body

END package_name;

下面例子为product_package创建包体:

CREATE PACKAGE BODY product_package AS

FUNCTION get_products_ref_cursor

RETURN t_ref_cursor IS

v_products_ref_cursor t_ref_cursor;

BEGIN

OPEN v_products_ref_cursor FOR

select product_id, name,price

from products;

RETURN v_products_ref_cursor;

END get_products_ref_cursor;

PROCEDURE update_product_price(

p_id IN products.product_id%TYPE,

p_factor IN number

) AS

v_product_count INTEGER;

BEGIN

SELECT COUNT(*)

INTO v_product_count

FROM products

WHERE prouct_id = p_id;

IF v_product_count = 1 THEN

UPDATE products

SET price = price * p_factor

WHERE product_id = p_id;

COMMIT;

END IF;

EXCEPTION

WHEN OTHERS THEN

ROLLBACK;

END update_product_price;

END product_package;

/

11.9.3、调用包中的函数和过程

select product_package.get_products_ref_cursor from dual;

CALL product_package.update_product_price(3 , 1.25);

11.9.4、获取包中的函数和过程信息

从user_procedures中检索object_name为product_package的所有信息。

11.9.5、删除包:DROP PACKAGE product_package;

11.10、触发器:当特定的SQL DML 语句在特定的数据库上运行时,由数据库自动运行的过程。

11.10.1、运行时机:可在DML语句运行前或者后被激活。分为行级触发器和语句级触发器。

当UPDATE语句在某个列上激活行级触发器时,这个触发器可以同时访问此列的原值和新值。也可以通过使用触发器条件来限制行级触发器的激活。

11.10.2、创建触发器

CREATE [ OR REPLACE ] TRIGGER trigger_name

{BEFOR |AFTER | INSTEAD OF | FOR } trigger_event

ON table_name

[ FOR EACH ROW ]

[ { FORWARD | REVERSE } CROSSEDITION ]

[ { FOLLOWS | PRECEDES } schema.other_trigger } ]

[ {ENABLE | DISABLE } ]

[ WHEN trigger_condition ] ]

BEGIN

trigger_body

END trigger_name;

其中[ { FORWARD | REVERSE } CROSSEDITION ]是11g新增的特性,一般用于数据库管理员和应用程序管理员

FORWARD 默认设置,当联机应用程序正在增加补丁或升级时对数据库进行某种改变,触发器被激活。REVERSE是在那之后。

{ FOLLOWS | PRECEDES } schema.other_trigger } Oracle 11g新增,规定一个触发器在schema.other_trigger 中规定的另一个触发器激活之后或者之前激活。

[ {ENABLE | DISABLE } ] Oracle 11g新增,指出创建时启用还是禁用此触发器。

11.10.3、获取有关触发器信息

从user_triggers视图可以获得触发器信息。从all_triggers中可以获得要访问的所有触发器信息。

SQL*PLUS 中SET LONG命令可以查看触发器的所有代码。

11.10.4、禁用和启用触发器 ALTER TRIGGER trigger_name DISABLE/ENABLE;

11.10.5、删除触发器:DROP TRIGGER trigger_name;

11.11 Oracle Database 11g新增的PL/SQL特性

11.11.1、SIMPLE_INTEGER 类型

它是BINARY_INTEGER的子类型,存储范围与BINARY_INTEGER相同但是不能存储null值。使用此类型时算术溢出被截断,因此溢出时不会产生错误

11.11.2、在PL/SQL中使用序列(可以使用nextval和currval伪列)

CREATE SEQUENCE s_product_id;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐