第二部分 Oracle PL/SQL基础 -...

446
第第第第 Oracle PL/SQL 第第 第第 PL/SQL 第第第第第第 在在 PL/SQL 在在在在在在在在在 在在在在在在在在在在在在 在在在在在在在 。, PL/SQL 在在在 。《 Oracle8I PL/SQL 在在在在在在在在在PL/SQL User’s Guide and reference在 §11.1 第第 在在在 Oracle5 在在在在在 PL/SQL 在 在 (在在3GL)在 在FortranCOBOL 在 C/C++在 在在在在在在在 。一,。 在在在4 在在在 4GL在4GL 在 在在 SQL在 在在 4GL 在在在在在在在在在 SQL 在在在在在 )。 4GL 在 在在 ,。 SQL 在在在在在在 Oracle 在在在 Oracle6 在在在在在在在 PL/SQL 在 在 在 在 。一。 SQL在 在 在 在 在 在 在 。。。;、。 -在 在在在在在在在 。。,。 Sybase 在 IBM 在 PL/SQL 在在在在在在在在在在在 在在在在在在 C在在 。一, Oracle 在在在在在在在在在在在 PL/SQL 在 在在在在 PL/SQL 在在 在在在在 C 在在在 在在在在在在在在在在在在在 PL/SQL 在在在在 Oracle9i 在 iAS 在在在在在在在 §11.2 SQL 第 PL/SQL 在在 Oracle 在 PL/SQL 在在在在 在在在在在在 SQL 在在在在在 §11.2.1 第第第 PL/SQL? PL/SQL 在 Procedure Language & Structured Query Language 在在在在 Oracle SQL 在在在 ANSI(American national Standards Institute) 在

Transcript of 第二部分 Oracle PL/SQL基础 -...

Page 1: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第二部分 Oracle PL/SQL基础

第十一章 PL/SQL 程序设计简介

在这部分用简短的篇幅描述一下 PL/SQL程序设计的基本知识。由于本教材是针对初学者,因而内容只涉及 PL/SQL的基础部分。希望深入了解的读者请参考目前书店销售的《Oracle8I PL/SQL高级程序设计》和《PL/SQL User’s Guide and reference》。

§11.1 概述早些的Oracle5以前是没有 PL/SQL这个产品的。由于当时数据库与编程的接口基本上都

使用高级语言(简称 3GL),如 Fortran、COBOL和 C/C++等。所以一般编程都是以高级语言为主,将数据库作为辅助的存储数据的工具来使用数据库系统。后来由于数据库的发展和软件技术的发展。出现了第 4 代开发工具,称为 4GL。4GL虽然在编程方面功能强大,但在与数据库接口上仍然采用 SQL语句(现在 4GL与数据库的通信仍以 SQL语句来实现)。4GL的功能是在处理界面上有优势,但在数据库的数据处理上仍不是它们的特长。鉴于数据库在SQL方面的优势,Oracle公司在Oracle6版本以后开发了 PL/SQL产品。起初它仅是一个辅助的产品。用它也只是弥补 SQL语句本身不进行过程编程的不足。但是后来由于数据库技术的发展。有些应用业务处理要求进行大量的数据处理。比如银行的年终结息;商场的日结、月结等。这类处理基本上不要求进行实时的人-机交互。而是只关心最后的结果。由于这类业务的需求增长,许多数据库公司纷纷在自己的数据库引擎上增加了存储过程这样的功能。比如Sybase的相应产品叫存储过程;IBM也叫存储过程,但它不但可以将类似 PL/SQL的程序写进数据库系统中,此外也可以将 C语言写的程序加进数据库中。处于这样的一种需求和时髦的推动,Oracle便在后来的版本中增强了 PL/SQL的功能。包括现在的许多系统的处理几乎是由 PL/SQL写成,而不是用 C来编写。这样的看法可以从目前的大量 PL/SQL存储包和Oracle9i的 iAS就可以看出来。

Page 2: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§11.2 SQL与 PL/SQL

与其它的开发工具类似,在Oracle的 PL/SQL工具中,可以使用标准 SQL的部分子集。

§11.2.1 什么是 PL/SQL?

PL/SQL是 Procedure Language & Structured Query Language 的缩写。Oracle的 SQL是支持 ANSI(American national Standards Institute)和 ISO92(International Standards Organization)标准的产品。PL/SQL是对 SQL语言存储过程语言的扩展。从 Oracle6以后,Oracle 的RDBMS附带了 PL/SQL。它现在已经成为一种过程处理语言,简称 PL/SQL(发音:pea ell sequel)。目前的 PL/SQL包括两部分,一部分是数据库引擎部分;另一部分是可嵌入到许多产品(如 C语言,JAVA语言等)工具中的独立引擎。可以将这两部分称为:数据库 PL/SQL和工具 PL/SQL。两者的编程非常相似。都具有编程结构、语法和逻辑机制。工具 PL/SQL另外还增加了用于支持工具(如Oracle Forms)的句法,如:在窗体上设置按钮等。本章主要介绍数据库 PL/SQL内容。

§11.2.1 PL/SQL的好处

§11.2.1.1 有利于客户/服务器环境应用的运行对于客户/服务器环境来说,真正的瓶颈是网络上。无论网络多快,只要客户端与服务器

进行大量的数据交换。应用运行的效率自然就回受到影响。如果使用 PL/SQL进行编程,将这种具有大量数据处理的应用放在服务器端来执行。自然就省去了数据在网上的传输时间。

§11.2.1.2 适合于客户环境PL/SQL由于分为数据库 PL/SQL部分和工具 PL/SQL。对于客户端来说,PL/SQL可以嵌

套到相应的工具中,客户端程序可以执行本地包含 PL/SQL部分,也可以向服务发 SQL 命令或激活服务器端的 PL/SQL程序运行。

§11.2.1.3 客户及服务器端的好处

2

Page 3: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

减少网络传输量 开发标准的代码 力争低偶联与高内聚性(少用全局变量和建立包来实现) 隐藏实现细节 统一的和集中的方式处理工程项目,以达到重用 更好地设计数据库应用(标准化、降低维护) 支持 SQL语句 支持面向对象编程 更好的性能 轻便性(portability) 更高的编程效率(productivity)

§11.2.2 PL/SQL 可用的 SQL语句

PL/SQL是Oracle系统的核心语言,现在 Oracle的许多部件都是由 PL/SQL写成。在 PL/SQL中可以使用的 SQL语句有:

在 PL/SQL中可以用的 SQL语句有:INSERTUPDATEDELETESELECT INTOCOMMITROLLBACKSAVEPOINT

提示:在 PL/SQL中只能用 SQL语句中的 DML 部分,不能用 DDL 部分,如果要在 PL/SQL中使用DDL(如 Create table 等)的话,只能以动态的方式来使用。

Oracle 的 PL/SQL 组件在对 PL/SQL 程序进行解释时,同时对在其所使用的表名、列名及数据类型进行检查。

PL/SQL 可以在 SQL*PLUS 中使用。 PL/SQL 可以在高级语言中使用。 PL/SQL可以 在Oracle的 开发工具中使用。 其它开发工具也可以调用 PL/SQL编写的过程和函数,如 Power Builder 等都可以调用服务器端的 PL/SQL过程。

3

Page 4: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§11.3 运行 PL/SQL程序PL/SQL程序的运行是通过Oracle中的一个引擎来进行的。这个引擎可能在Oracle的服务

器端,也可能在 Oracle 应用开发的客户端。引擎执行 PL/SQL中的过程性语句,然后将 SQL语句发送给数据库服务器来执行。再将结果返回给执行端。比如已经用下面的脚本创建了一个存储过程:create or replace procedure fundstat1(start_year_month in varchar2 , end_year_month in varchar2 ) is

year_month0 varchar2(7); --年月 stat_date0 date; --统计时间 bank_code0 varchar2(20); --经办行代码 no_id0 number(2); --经办行序号...

-- 声明光标, 用于 在各经办行信息表(bank_code)中取出每一个经办行名称 cursor get_bank is select bank_code , bank_name,no_id from bank_code order by no_id;begin

set transaction use rollback segment hdhouse_rs;-- SCO 上的回退段 begin if (substr(end_year_month,5,2) >= 1 . . . . . .

end;

则在 SQL*PLUS下运行可以用下面命令启动运行:SQL>execute funstat1(‘2001.01’,’2001.02’);

类似地,在 Power builder和Developer /2000下可以用下面语句来启动运行:EXECUTE fundstat1(‘2001.01’,’2001.03’);或date1 := ‘2001.01’;date2 := ‘2001.03’;EXECUTE fundstat1 ( :date1,:date2 );

4

Page 5: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§11.4 PL/SQL内置包除了Oracle引擎提供环境让程序设计者根据应用要求来开发各个存储过程、函数、包及

触发器外。Oracle系统本身提供了一套功能强大的内置包。这些系统包都以DBMS_开头进行命名。用这些包可以完成许多 Oracle 管理功能。关于 Oracle内置包的详细说明请参考《Oracle8I Supplied PL/SQL Packages Reference》原版资料。下面是一些常用包的简单说明:

DBMS_ALERT 数据库报警,允许会话间通信; DBMS_JOB 任务调度服务; DBMS_LOB 大对象操作用的包; DBMS_PIPE 数据库管道用的包; DBMS_SQL 动态 SQL所用的包; UTL_FILE 文本文件 I/O所用的包。

5

Page 6: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第十二章 PL/SQL 块结构和组成元素

本章给出编写 PL/SQL程序的基本结构和语句。

§12.1 PL/SQL结构 PL/SQL 块中可以包含子块; 子块可以位于 PL/SQL中的任何部分; 子块也即 PL/SQL中的一条命令; 已定义的对象有一定的作用范围。

举例:本例是 一个嵌套子块的结构:Declare /* 本部分可以定义变量、光标等。 */v_name varchar2(10);v_sql number(7,2);

Begin/* 执行部分 */. . . . . .

select ename, sal into v_name, v_sal from scott.emp where empno=’7777’;

begin /* 子块开始,也是执行语句 */. . . . . .

EXCEPTION /* 执行异常处理部分 */ . . . . . .

end;EXCEPTION/* 执行异常部分 */. . . . . .

6

Page 7: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

end; /* 本 PL/SQL 程序结束 */

§12.2 PL/SQL块PL/SQL程序由三个块组成,即 声明部分、执行部分、异常处理部分。PL/SQL块的结构如下:

Declare /* 声明部分: 在此 声明 PL/SQL用到的变量,类型及光标 */begin /* 执行部分: 过程及 SQL 语句 , 即程序的主要部分 */Exception /* 执行异常部分: 错误处理 */End;

其中 执行部分是必须的。块可以分为四类:无名块:动态构造,只能执行一次。命名块:加了标号的块。子程序:存储在数据库中的存储过程、函数及包等。当在数据库上建立好后可以在其它程序中调用它们。触发子:当数据库发生操作时,回触发一些事件,从而自动执行相应的程序。

§12.3 标识符PL/SQL程序设计中的标识符定义与 SQL 的标识符定义的要求相同。要求和限制有:

标识符名不能超过 30 字符; 第一个字符必须为字母; 不分大小写; 不能用’-‘(减号); 不能是 SQL 保留字。

举例 1: 合法的标识符:

7

Page 8: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

declare v_name varchar2(20); /* 存放 name 列的值 */v_sal number(9,2); /* 存放 sal 列的值 */. . . . . .

举例 2: 不合法的标识符:

declare v-name varchar2(20); /* 存放 name 列的值 */2001_sal number(9,2); /* 存放 sal 列的值 */

mine&yours number; -- 非法的标识符debit-amount number(10,4) ; -- 非法的标识符on/off char(1); -- 非法的标识符user id varchar2(20); -- 非法的标识符(不能用空格)

提示: 一般不要把变量名声明与表中字段名完全一样,如果这样可能得到不正确的 结果.

变量命名在 PL/SQL中有特别的究竟,建议在系统的设计阶段就要求所有编程人员共同遵守一定的要求。使得整个系统的文档在规范上达到要求。下面是建议的命名方法:变量名 意义V_variablename 程序变量E_exceptionName 自定义的异常标识T_TypeName 自定义的类型P_parameterName 存储过程、函数的参数变量C_ContantName 用 CONTANT 限制的变量

§12.4 PL/SQL 变量类型在前面的介绍中,有系统的数据类型,也可以自定义数据类型。下表是 Oracle类型和

PL/SQL中的变量类型的合法使用列表:

8

Page 9: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§12.4.1 变量类型

在Oracle8i中可以使用的变量类型有:类型 子类 说 明 范 围 ORACLE 限制

Char Character

String

Rowid

Nchar

定长字符串

接受 nls 数据

032767

可选,缺省=1

255

Varchar2 Varchar

String

Nvarchar2

可变字符串 032767

4000

2000

Binary_integer 带符号整数,为整数计算优化性能

Number(p,s) Dec

Double precision

Integer

Int

Numeric

Real

Small int

小数, Number 的子类型高精度实数整数, Number 的子类型整数, Number 的子类型与Number等价与Number等价整数, 比 integer 小

Long 变长字符串 0->2147483647 32,767 字节Date 日期型 公元前 4712 年 1 月

1 日至公元后 4712

年 12月 31日Boolean 布尔型 TRUE,

FALSE,NULL

不使用ROWID 存放数据库行号

例 1.declare

order_no number(3);cust_name varchar2(20);order_date date;emp_no integer := 25; -- 缺省为 25pi constant number := 3.14159;begin null;

9

Page 10: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

end;

§12.4.2 复合类型(记录和表)

ORACLE 在 PL/SQL 中除了提供象前面介绍的各种类型外,还提供一种称为复合类型的类型---记录和表。1. 记录类型定义记录类型语法如下:

TYPE record_type IS RECORD( Field1 type1 [NOT NULL] [:= exp1 ], Field2 type2 [NOT NULL] [:= exp2 ], . . . . . . Fieldn typen [NOT NULL] [:= expn ] ) ;

例 :-- 节选自在线代码 assign.sqlDECLARE TYPE t_rec1 type is record ( Field1 number, Field2 varchar2(5) );

TYPE t_rec2 IS RECORD( Field1 number, Field2 varchar2(5));

V_Rec1 t_rec1 type;V_recc1 t_rec2 type;

Begin/* 赋值 (要求类型一致) */ v_rec1 := v_rec2;

v_rec1.field1 := v_rec2.field1;v_rec2.field2 := v_rec2.field2;

end;

10

Page 11: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

可以用 select 语句对记录变量进行赋值,只要保证 记录字段与 查询结果列表中的字段相配即可。例:--节选自在线代码 select.sqlDECLARE-- 用 %TYPE 类型定义与表相配的字段TYPE t_studentrecord IS RECORD(Firstname sutdents.first_name%TYPE,

Lastname sutdents.last_name%TYPE,Major sutdents.major%TYPE );

-- 声明接收数据的变量v_stduent t_StudentRecord;Begin Select first_name,last_name,major Into v_student From students Where id=10000;End;

§12.4.3 使用%ROWTYPE

PL/SQL 可以声明与数据库行有相同类型的记录。例:--节选自在线 tabrec.sqlDECLARE TYPE t_studenttable is TABLE OF students%ROWTYPEINDEX BY BINARY_INTEGER;/* v_students 的每一元素是一个记录 */ v_students t_studentstable;Begin /* 将结果存到数组变量中 */select * into v_students(10001) from students

where id=10001;end;

11

Page 12: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§12.4.4 LOB类型

Oracle 提供了 LOB (Large OBject)类型,用于存储大的数据对象的类型。Oracle目前主要支持BFILE, BLOB, CLOB 及 NCLOB 类型。BFILE 存放大的二进制数据对象,这些数据文件不放在数据库里,而是放在操作系统的某个目录里,数据库的表里只存放文件的目录。BLOB存储大的二进制数据类型。每个变量存储大的二进制对象的位置。大二进制的大小<=4GB。CLOB存储大的字符数据类型。每个变量存储大字符对象的位置,该位置指到大字符数据块。大字符的大小<=4GB。NCLOB存储大的NCHAR字符数据类型。每个变量存储大字符对象的位置,该位置指到大字符数据块。大字符的大小<=4GB。

§12.4.5 用户定义的子类型

在Oracle7.2后的版本中,可以定义一种称为子类型的类型,子类型可以使真正类型的名字变为另外的名字(注意仅仅是一种真正类型的另外叫法)。子类型的声明使用 SUBTYPE命令说明。如:SUBTYPE CHARACTER IS CHAR;SUBTYPE INTEGER IS NUMBER(38,0); -- allows only whole numbers

这里子类型 CHARACTER 与真正类型 CHAR一样, 所以 CHARACTER是一个不受约束的子类型。 但是 INTEGER 是基本类型的一个子类型 NUMBER,所以 INTEGER 是受约束的子类型。

12

Page 13: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

定义子类型 语法如下:SUBTYPE subtype_name IS base_type[(constraint)] [NOT NULL];

例: DECLARE SUBTYPE BirthDate IS DATE NOT NULL; -- 基于 DATE 类型 SUBTYPE Counter IS NATURAL; -- 基于 NATURAL 子类型 TYPE NameList IS TABLE OF VARCHAR2(10); SUBTYPE DutyRoster IS NameList; -- 基于 TABLE 类型 TYPE TimeRec IS RECORD (minutes INTEGER, hours INTEGER); SUBTYPE FinishTime IS TimeRec; -- 基于 RECORD 类型 SUBTYPE ID_Num IS emp.empno%TYPE; -- 基于 column 类型使用子类型 一旦定义子类型,就可以在声明的地方使用子类型。DECLARE SUBTYPE Counter IS NATURAL; rows Counter;

DECLARE SUBTYPE Accumulator IS NUMBER; total Accumulator(7,2);

例。DECLARE SUBTYPE Numeral IS NUMBER(1,0); x_axis Numeral; -- 大小范围: -9 .. 9 y_axis Numeral;BEGIN x_axis := 10; -- 触发 VALUE_ERROR ...END;

类型的兼容性一个无约束的子类型可以与基本类型进行交换,如:DECLARE SUBTYPE Accumulator IS NUMBER;

13

Page 14: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

amount NUMBER(7,2); total Accumulator;BEGIN ... total := amount; ...END;不同的子类型也可以互换,如:

DECLARE SUBTYPE Sentinel IS BOOLEAN; SUBTYPE Switch IS BOOLEAN; finished Sentinel; debugging Switch;BEGIN ... debugging := finished; ...END;

不同的子类型也可以互换,如:DECLARE SUBTYPE Word IS CHAR(15); SUBTYPE Text IS VARCHAR2(1500); verb Word; sentence Text(150);BEGIN ... sentence := verb; ...END;

§12.4.6 数据类型的转换可以进行转换的隐式类型转换有:  BIN_INT  CHAR  DATE  LONG  NUMBER  PLS_INT  RAW  UROWID  VARCHAR2 

BIN_INT    X    X  X  X      X 

14

Page 15: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

  BIN_INT  CHAR  DATE  LONG  NUMBER  PLS_INT  RAW  UROWID  VARCHAR2 

CHAR  X    X  X  X  X  X  X  X 

DATE    X    X          X 

LONG    X          X    X 

NUMBER  X  X    X    X      X 

PLS_INT  X  X    X  X        X 

RAW    X    X          X 

UROWID    X              X 

VARCHAR2  X  X  X  X  X  X  X  X   

§12.5 运算符和表达式(数据定义)

与其他语言一样,为了完成所要求的各种处理,PL/SQL需要下面各个运算符和表达式。

§12.5.1 关系运算符关系运算符有:运算符  意义=  等于 <>, !=, ~=, ^=  不等于<  小于 >  大于 <=  小于或等于>=  大于或等于

15

Page 16: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§12.5.2 一般运算符一般运算符有:运算符  意义+  加号 -  减号*  乘号 /  除号 :=  赋值号=> 关系号 .. 范围运算符|| 字符连接符

§12.5.3 逻辑运算符逻辑运算符有:运算符  意义is null 是空值 Between 介于两者之间In 在一列值中间 And 逻辑与Or 逻辑或Not 取返,如 is not null, not in,

16

Page 17: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§12.6 变量赋值在 PL/SQL编程中,变量赋值是一个值得注意的地方,它的语法如下: variable := expression ;

variable 是一个 PL/SQL 变量, expression 是一个 PL/SQL 表达式.

§12.6.1 字符及数字运算特点

空值加数字仍是空值:null + < 数字> = null

空值加(连接)字符,结果为字符:null || <字符串> = < 字符串>

§12.6.2 Boolean 赋值

布尔值只有 TRUE, FALSE及 NULL 三个值。如:DECLAREdone BOOLEAN;the following statements are legal:BEGINdone := FALSE;WHILE NOT done LOOP

...END LOOP;

17

Page 18: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§12.6.3 数据库赋值数据库赋值是通过 select 语句来完成的。每执行select 语句一次只能赋值一次。一般要求被赋值的变量与select 中的列名要一一对应。如:DECLARE

emp_id emp.empno%TYPE;emp_name emp.ename%TYPE;wages NUMBER(7,2);BEGIN...SELECT ename, sal + commINTO emp_name, wages FROM empWHERE empno = emp_id;...END;

提示:不能将select 语句中的列赋值给布尔变量。

Declare V_string1 varchar2(10); V_string2 varchar2(15); V_numeric number;Begin V_string1 :=’Hello’; V_string2 := v_string1; V_numeric := -12.4;End;

§12.6.4 可转换的类型赋值

CHAR 转换为 NUMBERT使用 TO_NUMBER 函数来完成字符到数字的转换,如:v_total := to_number(‘100.0’) + sal;

18

Page 19: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

NUMBERT 转换为CHAR使用 TO_CHAR 函数可以实现 数字到字符的转换,如:v_comm := to_char(‘123.45’) || ’元’ ;

字符 转换为 日期使用 TO_DATE 函数可以实现 字符到日期的转换,如:v_date := to_date('2001.07.03','yyyy.mm.dd');

日期 转换为 字符使用 TO_CHAR 函数可以实现 日期到字符的转换,如:v_to_day := to_char(sysdate,'yyyy.mm.dd hh24:mi:ss') ;

可以在 SQL>下输入下面命令来验证以上的语句:select to_char(sysdate,'yyyy')||'年'||to_char(sysdate,'mm')||'月' ||to_char(sysdate,'dd')||'日' from dual;

TO_CHAR(SYSDAT--------------2001年 07月 02日SQL> alter session set nls_date_format ='yyyy"年"mm"月"dd"日"';

Session altered.

SQL> select sysdate from dual;

SYSDATE--------------2001年 04月 24日

SQL> select to_number('133')+200 from dual;

TO_NUMBER('133')+200-------------------- 333

SQL> select to_char('321')||'元' from dual;

19

Page 20: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

TO_CH-----321 元SQL> select to_date('2001.07.03','yyyy.mm.dd') from dual;

TO_DATE('2----------03-7月 -01

§12.7 变量作用范围以可见性在 PL/SQL编程中,如果在变量的定义上没有做到统一的话,可能会隐藏一些危险的错

误,这样的原因主要是变量的作用范围所致。与其它高级语言类似,PL/SQL的变量作用范围特点是:

变量的作用范围是在你所引用的程序单元(块、子程序、包)内。即从声明变量开始到该块的结束。

一个变量(标识)只能在你所引用的名字内是可见的。 当一个变量超出了作用范围,PL/SQL引擎就释放用来存放该变量的空间(因为它可能不用了)。

在子块中重新定义该变量后,它的作用仅在该块内。

§12.8 注释在PL/SQL里,可以使用两种符号来写注释,即:

使用双 ‘-‘ ( 减号) 加注释PL/SQL允许用双 - - (双减号) 来写注释,它的作用范围是只能在1行有效。如:V_Sal number(12,2); -- 工资变量。

使用 /* */ 来加一行或多行注释使用 /* . . . */ 在PL/SQL程序中加,可以对多行进行注释。如:如:

20

Page 21: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

/***********************************************//* 文件名: stattistcs_sal.sql *//* 功能:统计整个部门工资 *//* 作者: 赵元杰 *//* 修改日期 :2001.07.03 *//***********************************************/

或/*********************************************** 文件名: stattistcs_sal.sql 功能:统计整个部门工资 作者: 赵元杰 修改日期 :2001.07.03 ***********************************************/

提示:被解释存放在数据库中的PL/SQL 程序,一般系统自动将程序头部的注释去掉。只有在Procedure 之后的注释才被保留;另外程序中的空行也自动被去掉。建议:为了标准起见,最好使用 /* . . . */ 这样的注释语句。因为这样的注释在许多语言中是相同的。

§12.9 简单例子在我们给出编写 PL/SQL程序所需的各个语句之前,先给出一些简单的例子,目的是让

读者对 PL/SQL程序先有个感性认识。

§12.9.1 简单数据插入例子/* 本例子仅是一个简单的插入,不是实际应用。 */declare v_ename varchar2(20) := ‘赵元杰’;v_sal number(7,2) :=1234.56;v_deptno number(2) := 10;v_empno number(4) := 8888;

begininsert into emp ( empno, ename, JOB, sal, deptno , hiredate )

21

Page 22: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

values ( v_empno, v_ename, ‘自由职业’, v_sal, v_deptno, to_date(’1954.06.09’,’yyyy.mm.dd’) );commit;end;/show error

§12.9.2 简单数据删除例子

/* 本例子仅是一个简单的删除例子,不是实际应用。 */declare v_ename varchar2(20) := ‘赵元杰’;v_empno number(4) := 8888;

begindelete from emp where empno=v_empno and ename=v_ename;commit;end;/show error

第十三章 PL/SQL 处理流程

在PL/SQL程序中,要使程序能按照逻辑进行处理,除了有些语句是SQL语句外,还必须有能进行逻辑控制的语句。下面就介绍进行处理流程的语句结构。

§13.1 条件语句IF <布尔表达式> THEN

PL/SQL 和 SQL语句END IF;

22

Page 23: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

IF <布尔表达式> THENPL/SQL 和 SQL语句

ELSE其它语句

END IF;

IF <布尔表达式> THENPL/SQL 和 SQL语句

ELSIF < 其它布尔表达式> THEN其它语句

END IF;

提示: ELSIF 不能写成 ELSEIF

例:

--节选自在线代码 if1.sqlDECLARE V_numberseats rooms.number_seats%TYPE; V_comment varchar2(35);Degin Select number_seats into v_numberseats From rooms where room_id=99999; IF v_numberseats<50 then V_comment := ‘Fairly small’; Elsif v_numberseats < 100 then V_comment := ‘A little bigger’; Else V_comment := ‘Lots of room’; End if ;End;

§13.2 循环

1. 简单循环Loop

要执行的语句;

23

Page 24: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

end loop;--此循环将执行到遇到一条 exit 语句为止.

例 1. declare x number; begin x:= 0; loop x:=x+1; dbms_output.put_line(to_char(x)); exit when x=10; end loop; end;

例 2.

--节选自在线代码 simple.sql

DECLARE V_counter BINARY_INTEGER := 1;Begin LOOP Inert into temp_table Values( v_counter, ‘loop index’ ); V_counter := v_counter + 1; If v_counter > 50 then Exit; End if ; End loop;End;

例 3.

--节选自在线代码 exitwhen.sql

DECLARE V_counter binary_index := 1;Begin Loop Insert into temp_table Values ( v_counter,’ loop index ‘ );

24

Page 25: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Exit when v_counter > 50 ; End loop;End;

2. WHILE 循环While 循环

While <布尔表达式> loop 要执行的语句; end loop;

例 1.declare x number;

begin x:= 1; while x<10 loop dbms_output.put_line(to_char(x)||’还小于 10’); x:= x+1; end loop;

end;

例 2.

--节选自在线代码 while1.sql

DECLARE V_counter binary_integer := 1;Begin While v_counter <= 50 loop

Inert into temp_table Values( v_counter, ‘loop index ‘) ; V_counter := v_counter + 1; End loop;End;

3. 数字式循环For 循环

25

Page 26: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

For 循环计数器 in 下限 .. 上限 loop 要执行的语句;end loop;

FOR loop_counter IN [ REVERSE ] low_bound . . high_bound LOOP Sequence_of_statements;END LOOP;

例 1.

begin

for I in 1 .. 10 loop dbms_output.put_line(‘in=’||to_char(I));

end loop;

end;

例 2.

--节选自在线代码 forscope.sqlDECLARE

V_counter number := 7;

Begin

Inert into temp_table (num_col)

Values ( v_counter );

For v_counter IN 20 .. 30 loop

Insert into temp_table (num_col )

Values ( v_counter );

End loop;

Inert into temp_table (num_col )

Values( v_counter );

End ;

注:如果在 for 中用 INVERSE 关键字,则循环索引将从最大向最小进行迭代.

§13.3 标号和GOTO

PL/SQL中GOTO语句是无条件跳转到指定的标号去的意思。语法如下:

26

Page 27: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

GOTO label; . . . . . .<<label>>

例:

--节选自在线代码 goto.sql

DECLARE V_counter BINARY_INTEGER := 1;Begin Loop Inert into temp_table

Values( v_counter,’loop count’ );V_counter := v_counter + 1;If v_counter > 50 then Goto l_endofloop;End if;End loop;<<l_endofloop>>insert into temp_table ( char_col ) values(‘Done !’);

End ;

§13.4 NULL 语句

在 PL/SQL 程序中,null语可以用 null 语句来说明“不用做什么”的意思。如:declare

. . .

begin

if( v_num is null then

goto print1;

end if;

<<print1>>

NULL; -- 不需要处理任何数据。End;

27

Page 28: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第十四章 光标的使用

与在 SQL*PLUS 命令方式下不同,在 PL/SQL 程序中,对于处理多行记录的事务经常使用光标来实现。

§14.1 光标概念 为了处理 SQL 语句,oracle 必须分配一片叫上下文( context area )的区域来处理所必需的

信息,其中包括要处理的行的数目,一个指向语句被分析以后的表示形式的指针以及查询的活动集(active set).

光标是一个指向上下文的句柄( handle)或指针。通过光标, PL/SQL 可以控制上下文区和处理语句时上下文区会发生些什么事情。

§14.1.1 处理显式光标在 PL/SQL程序中定义的光标称作显式光标。下面是显式光标的使用介绍。1. 显式光标处理显式光标处理需四个 PL/SQL步骤:

cursor 光标名称 is 查询语句;open 光标名称;Fetch 光标名称 into 变量列表;Close 光标名称;

例 1.

declare cursor c1 is select ename, sal from emp where rownum<11;

v_ename varchar2(10);v_sal number(7,2);

28

Page 29: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

begin open c1; fetch c1 into v_ename, v_sal; while c1%found loop dbms_output.put_line(v_ename||to_char(v_sal) ); fetch c1 into v_ename, v_sal;end loop;close c1;end;

2.光标属性 %found 布尔型属性,当最近一次读记录时成功返回,则值为 true %nofound 布尔型属性,与%found相反. %isopen 布尔型属性, 当光标已打开时返回 true. %rowcount 数字型属性, 返回已从光标中读取得记录数.

3.参数化光标 在声明光标时,将未确定的参数说明成变量,在使用光标时给出光标变量的具体值(相当于实参)使得语句可以按照给出的条件进行查询。例 2:DECLARE Cursor c1 (view_pattern varchar2) IS Select view_name from all_views Where view_name like view_pattern’||% AND rownum <= 10 Order by view_name ; Vname varchar2(40);BEGIN For I1 in c1 ( ‘DBA’) loop DBMS_OUTPUT.PUT_LINE( I1.view_name ) ; END loop;END;

§14.1.2 处理隐式光标 所有的 SQL 语句在上下文区内部都是可执行的,因此都有一个光标指向上下文区,此光标就是所谓的SQL 光标(SQL cursor),与显式光标不同,SQL 光标不被程序打开和关闭。

29

Page 30: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例 3:

--节自在线代码 nomat1.sqlBEGIN

UPDATE rooms SET number_seats = 100

WHERE room_id = 99980;

-- 如果更新没有匹配则插入一新行 IF SQL%NOTFOUND THEN

INSERT INTO rooms ( room_id, number_seats )

VALUES ( 99980, 100 ) ;

END IF;

END;

例 4:

--节自在线代码 nomat2.sql

BEGIN

UPDATE rooms SET number_seats = 100

WHERE room_id = 99980;

-- 如果更新没有匹配则插入一新行 IF SQL%ROWCOUNT = 0 THEN

INSERT INTO rooms ( room_id, number_seats )

VALUES ( 99980, 100 ) ;

END IF;

END;例 5:

--节自在线代码 nodata.sql

DECLARE

V_roomdata rooms%ROWTYPE;

BEGIN

Select * into v_roomdata from rooms

Where room_id = -1 ;

IF SQL%NOFOUND THEN

INSERT INTO temp_table ( char_col )

VALUES ( ‘Not Found ! ‘) ;

END IF;

EXCEPTION

WHEN NO_DATA_FOUND THEN

INSERT INTO temp_table ( char_col )

VALUES ( ‘Not Found ! exception handle. ‘) ;

END;

30

Page 31: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§14.2 光标循环 在高级语言编程和 PL/SQL 编程中,经常使用“提取循环(fetch loop)” 来实现逐行提取所需数据的方法。

§14.2.1 简单循环可以使用 LOOP 和 END LOOP来实现简单循环。但这样的循环需要在循环体内说明跳出循环的语句,否则就会出现无限循环现象。--节自在线代码 simple.sql

DECLARE V_studentID students.id%TYPE; V_firstName students.first_name%TYPE; V_LastName students.last_name%TYPE;

CURSOR c_HistoryStudents ISSELECT id, first_name, last_name from studentsWHERE major = ‘History’;BEGIN Open c_HistoryStudents ; LOOP FETCH c_HistoryStudents INTO v_studentID, v_FirstName, V_LastName ; EXIT WHEN c_HistoryStudents%NOFOUND ; INSERT INTO registered_students(student_id, department,course ) VALUES ( v_StudentsID,’HIS’,301 ); INSERT INTO temp_table ( num_col, char_col ) VALUES ( v_StudentID, v_FirstName||’ ‘|| v_lastName ) ; END LOOP; CLOSE c_HistoryStudents; COMMIT;END;

提示: EXIT WHEN 是紧跟在 FETCH 后面。

31

Page 32: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§14.2.2 WHILE循环与简单循环不一样的是,while 循环是先判断后执行。只有满足条件才能执行其循环体内的语句;而简单循环至少执行一次。看下面例子:DECLARE

CURSOR c_HistoryStudents IS

SELECT id, first_name, last_name from students

WHERE major = ‘History’;

BEGIN

Open c_HistoryStudents ;

LOOP

FETCH c_HistoryStudents INTO v_studentData;

WHILE c_HistoryStudents%FOUND LOOP

INSERT INTO registered_students(student_id, department,course )

VALUES ( v_StudentsID,’HIS’,301 );

INSERT INTO temp_table ( num_col, char_col )

VALUES ( v_StudentID, v_FirstName||’ ‘|| v_lastName ) ;

-- 返回下一行,%FOUND 循环前检查 FETCH c_HistoryStudents INTO v_studentData;

END LOOP;

CLOSE c_HistoryStudents;

COMMIT;

END;

§14.2.3 光标 FOR 循环除上面的循环外,一种可以控制次数的循环就是 For 循环。--节选自在线代码 forloop.sqlDECLARE

CURSOR c_HistoryStudents IS SELECT id, first_name,last_name FROM students WHERE major = ‘History’;

BEGIN

FOR v_StudentData IN c_HistoryStudents LOOP

INSERT INTO registered_students(student_id, department,course ) VALUES ( v_StudentsID,’HIS’,301 );

32

Page 33: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

INSERT INTO temp_table ( num_col, char_col ) VALUES ( v_StudentID, v_FirstName||’ ‘|| v_lastName ) ; -- 循环前隐含检查 %NOFOUND

END LOOP; -- 自动关闭光标COMMIT;

END;

§14.2.4 关于NO_DATA_FOUND和%NOTFOUND

一般初学者对 Oracle的 NO_DATA_FOUND和%NOTFOUND两个保留字的用法不够了解,主要是它们从意义上是有些类似。其实它们的用法是有区别的,小结如下:

SELECT . . . INTO 语句触发 NO_DATA_FOUND; 当一个显示光标的 where 子句未找到时 触发 %NOTFOUND; 当UPDATE 或 DELETE 语句的where 子句未找到时 触发 SQL%NOTFOUND; 在光标的提取(Fetch)循环中要用 %NOTFOUND 或%FOUND 来确定循环的退出条件,不要用 NO_DATA_FOUND。

§14.2.5 SELECT FOR UPDATE 光标为了对正在处理(查询) 的行不被另外的用户改动,oracle 提供一个 FOR UPDATE 子句来

对所选择的行进行锁住。语法如下:SELECT . . . FROM FOR UPDATE [OF column_reference] [NOWAIT]

如果另一个会话已对活动集中的行加了锁,那么 SELECT FOR UPDATE 操作一直等待到其它的会话释放这些锁后才继续自己的操作,对于这种情况,如果加 NOWAIT 子句,如果这些行真的被另一个会话锁定,则 OPEN 立即返回并给出:ORA-0054 :resource busy and acquire with NOWAIT specified. 如果 使用 FOR UPDATE 声明光标,则可在 delete, update 语句中使用WHERE CURRENT OF 子句。例 6:--节选自在线代码 forupdate.sqlDECLARE V_NumCreadits classes.num_creadits%TYPE; CURSOR c_RegisteredStudents IS SELECT * FROM students WHERE is IN ( SELECT student_id from registered_students WHERE department = ‘HIS’ AND course = 101 ) FOR UPDATE OF current_credits;

33

Page 34: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

BEGIN

FOR v_Studentinfo IN c_RegisteredStudents LOOP SELECT num_credits INTO v_numcredits FROM classes WHERE department =’HIS’ AND course=101;

UPDATE students SET current_credits = current_credits + v_numcredits WHERE CURRENT OF c_RegusteredStudents; END LOOP;

COMMIT;END;

§14.3 光标变量前面所给出光标都是显式的光标,而且是静态的光标。Oracle从 PL/SQL Release2.2版以

后,声明的光标可以不是静态的,光标变量就是允许开发人员编写的程序在运行时与不同的语句相关联。光标变量在运行可以取不同的值。以达到灵活的目的。

§14.3.1 声明光标变量光标变量语法如下:TYPE type_name IS REF CURSOR RETURN return_type;

§14.3.2 为光标变量分配存储空间由于光标变量是一种引用类型,在使用前需要为其分配一片内存区,用下面语句完成分配:EXEC SQL ALLCATE :variable

§14.3.3 打开光标变量如果要将一个光标变量与一个特定的 select 语句关联,则需 Open 将其打开,语法如下:OPEN cursor_variable FOR select_statements;

34

Page 35: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§14.3.4 关闭光标变量关闭光标的语法如下: CLOSE cursor_variable;

§14.3.5 光标变量例子

例 1.光标变量在 PRO*C中使用:-- 节选自在线代码 cursor1.pcREM cursor1.pc

REM 这是一个 Pro*C 程序。/* 包括 C 和 SQL 头文件. */#include <stdio.h>EXEC SQL INCLUDE SQLCA;

/* SQL 声明部分:光标、变量都要这里声明 */EXEC SQL BEGIN DECLARE SECTION;

/* SQL 光标变量 */ SQL_CURSOR v_CursorVar;

/* 整数变量,用于查询表数据. */ int v_Table;

/* 用于 room的输出变量. */ int v_RoomID; VARCHAR v_Description[2001];

/* 用于 classes的输出变量. */ VARCHAR v_Department[4]; int v_Course;EXEC SQL END DECLARE SECTION;

/* 错误处理程序,用于打印错误和退出. */

35

Page 36: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

void handle_error() { printf("SQL Error occurred!\n"); printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1);}

int main() { /* 字符串输入变量. */ char v_Choice[20];

/* 设置错误处理,当 SQL出现错误时,可调用 handle_error() */

EXEC SQL WHENEVER SQLERROR DO handle_error();

/* 连接到数据库. */ EXEC SQL CONNECT :v_Username; printf("Connected to Oracle.\n");

/* 分配光标变量内存区. */ EXEC SQL ALLOCATE :v_CursorVar;

/* 显示提示信息。*/ printf("Choose from (C)lasses or (R)omms. Enter c or r: "); gets(v_Choice);

/* 确定连接表. */ if (v_Choice[0] == 'c') v_Table = 1; else v_Table = 2;

/* 使用嵌入 PL/SQL来打开光标变量 */

EXEC SQL EXECUTE BEGIN IF :v_Table = 1 THEN /* 为Class表打开变量 */ OPEN :v_CursorVar FOR SELECT department, course FROM classes; ELSE /* 为 room 表打开变量 */

36

Page 37: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

OPEN :v_CursorVar FOR SELECT room_id, description FROM rooms; END IF; END; END-EXEC;

/* 当取数完毕退出 */ EXEC SQL WHENEVER NOT FOUND DO BREAK;

/* 开始循环 */ for (;;) { if (v_Table == 1) { /* 取 class 信息 */ EXEC SQL FETCH :v_CursorVar INTO :v_Department, :v_Course;

/* 显示相应信息 */ printf("%.*s %d\n", v_Department.len, v_Department.arr, v_Course); } else { /* 取 room 信息 */ EXEC SQL FETCH :v_CursorVar INTO :v_RoomID, v_Description;

/* 显示相应信息 */ printf("%d %.*s\n", v_RoomID, v_Description.len, v_Description.arr); } }

/* 关闭光标变量 */ EXEC SQL CLOSE :v_CursorVar;

/* 断开数据库连接. */ EXEC SQL COMMIT WORK RELEASE;}

37

Page 38: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§14.3.6 光标变量

例 2.光标变量在 PL/SQL中使用:REM 选自在线代码 cursor2.sql REM 作者: Scott Urman.REM 中文注释:赵元杰CREATE OR REPLACE PROCEDURE ShowCursorVariable /* 变量声明。*/ (p_Table IN VARCHAR2) AS

/* 定义光标变量类型 */ TYPE t_ClassesRooms IS REF CURSOR;

/* 光标变量引用 */ v_CursorVar t_ClassesRooms;

/* 处理输出变量. */ v_Department classes.department%TYPE; v_Course classes.course%TYPE; v_RoomID rooms.room_id%TYPE; v_Description rooms.description%TYPE;BEGIN/* 根据输入参数来打开光标变量 */ IF p_Table = 'classes' THEN OPEN v_CursorVar FOR SELECT department, course FROM classes; ELSIF p_table = 'rooms' THEN OPEN v_CursorVar FOR SELECT room_id, description FROM rooms; ELSE

/* 输入错误值则触发错误 */ RAISE_APPLICATION_ERROR(-20000, 'Input must be ''classes'' or ''rooms'''); END IF; /* 处理循环,当处理完退出 */ LOOP IF p_Table = 'classes' THEN FETCH v_CursorVar INTO

38

Page 39: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

v_Department, v_Course; EXIT WHEN v_CursorVar%NOTFOUND;

INSERT INTO temp_table (num_col, char_col) VALUES (v_Course, v_Department); ELSE FETCH v_CursorVar INTO v_RoomID, v_Description; EXIT WHEN v_CursorVAR%NOTFOUND;

INSERT INTO temp_table (num_col, char_col) VALUES (v_RoomID, SUBSTR(v_Description, 1, 60)); END IF; END LOOP;

/* 关闭光标变量. */ CLOSE v_CursorVar;

COMMIT;END ShowCursorVariable;/

第十五章 错误处理

一个优秀的程序都应该能够正确处理各种出错情况,并尽可能从错误中恢复。Oracle 提供异常情况(EXCEPTION)和异常处理(EXCEPTION HANDLER)来实现错误处理。

§15.1 异常处理概念 异常情况处理(EXCEPTION)是用来处理正常执行过程中未预料的 事件,程序块的异常处理预定义的错误和自定义错误,由于 PL/SQL程序块一旦产生异常而没有指出如何处理时,程序就会自动终止整个程序运行. 异常处理部分一般放在 PL/SQL 程序体的后半部,结构为:

39

Page 40: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

EXCEPTION When first_exception then <code to handle first exception> When second_exception then <code to handle second exception>END;

异常处理可以按任意次序排列,但 Others 必须放在最后。

§15.1.1 预定义的异常处理

有两种类型的异常情态:用户定义(user_define) 和预定义 ( predefined )

预定义说明的 oracle 异常

ORACLE 错误 异常信息 说明ORA-0001 Dup_val_on_index 试图破坏一个唯一性限制ORA-0051 Timeout-on-resource 在等待资源时发生超时ORA-0061 Transaction-backed-out 由于发生死锁事务被撤消.ORA-1001 Invalid-cursor 试图使用一个无效的光标ORA-1012 Not-logged-on 没有连接到ORACLEORA-1017 Login-denied 无效的用户名/口令ORA-1403 Not-data-found 没有找到数据ORA-1422 Too-many-rows select into 返回多行ORA-1476 Zero-divide 试图被零除ORA-1722 Invalid-number 转换一个数字失败ORA-6500 Storage-error 内存不够引发的内部错误ORA-6501 Program-error 内部错误ORA-6502 Value-error 转换或截断错误ORA-6504 Rowtype-mismatch 缩主光标变量与 PL/SQL 变量 有不兼容行类型ORA-6511 Cursor-already-open 试图打开一个已存在的光标ORA-6530 Access-into-null 试图为 null 对象的属性赋值ORA-6531 Collection-is-null 试图将 Exists 以外的集合( collection) 方法应用于一个 null pl/sql 表上或 varray上ORA-6532 Subscript-outside-limit 对嵌套或 varray 索引的引用超出声明范围 以外ORA-6533 Subscript-beyond-count 对嵌套或 varray 索引得引用大于集合中 元素的个数.

40

Page 41: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§15.1.2 触发异常情态 当与一个异常情态相关的错误出现时,就会隐含引发该异常情态。用户定义的异常情态是通过显式使用 RAISE 语句来引发。--节选自在线代码 handle.sql

REM 选自在线代码 handle.sql REM 作者: Scott Urman.REM 中文注释:赵元杰DECLARE e_TooManyStudents EXCEPTION; -- 类型为 Exception,用于指示错误条件 v_CurrentStudents NUMBER(3); -- HIS-101学生注册当前号 v_MaxStudents NUMBER(3); -- HIS-101学生注册允许的最大号BEGIN /* 找出注册学生当前号和允许的最大号 */ SELECT current_students, max_students INTO v_CurrentStudents, v_MaxStudents FROM classes WHERE department = 'HIS' AND course = 101; /* 检查学生的号 */ IF v_CurrentStudents > v_MaxStudents THEN

/* 太多的学生注册,则触发例外处理 */ RAISE e_TooManyStudents; END IF;EXCEPTION WHEN e_TooManyStudents THEN /* 当太多的学生注册,就插入信息解释发生过错误 */

INSERT INTO log_table (info) VALUES ('History 101 has ' || v_CurrentStudents || 'students: max allowed is ' || v_MaxStudents);END;/

41

Page 42: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§15.1.3 处理异常情态 当引发一个异常情态时,控制就转向到 EXCEPTION 块异常情态部分,执行错误处理代码。语法如下: EXCEPTION WHEN exception_name THEN Sequence_of_statements1; WHEN exception_name THEN Sequence_of_statements2; WHEN OTHERS THEN Sequence_of_statements3;END;

例:对于不确定的错误使用 sqlerrm 将其显示出。--节选自在线代码 sqlerrm.sqlREM 作者: Scott Urman.REM 中文注释:赵元杰DECLARE e_TooManyStudents EXCEPTION; -- 类型为 Exception,用于指示错误条件 v_CurrentStudents NUMBER(3); -- HIS-101学生注册当前号 v_MaxStudents NUMBER(3); -- HIS-101学生注册允许的最大号 v_ErrorCode NUMBER; -- 错误处理代码变量 v_ErrorText VARCHAR2(200); -- 错误处理信息变量BEGIN /* 找出注册学生当前号和允许的最大号 */ SELECT current_students, max_students INTO v_CurrentStudents, v_MaxStudents FROM classes WHERE department = 'HIS' AND course = 101; /* 检查学生的号 */ IF v_CurrentStudents > v_MaxStudents THEN

/* 太多的学生注册,则触发例外 */ RAISE e_TooManyStudents; END IF;EXCEPTION WHEN e_TooManyStudents THEN /* 如果在HIS-101中有太多的学生注册,则插入日志信息解释已经发生的情况 */ for HIS-101. We will insert a log message explaining what has happened. */

42

Page 43: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

INSERT INTO log_table (info) VALUES ('History 101 has ' || v_CurrentStudents || 'students: max allowed is ' || v_MaxStudents); WHEN OTHERS THEN

/* 所有其它错误的处理 */ v_ErrorCode := SQLCODE; v_ErrorText := SUBSTR(SQLERRM, 1, 200); -- Note the use of SUBSTR here. INSERT INTO log_table (code, message, info) VALUES (v_ErrorCode, v_ErrorText, 'Oracle error occurred');END; /

§15.1.4 用户定义的异常处理 可以使用 RAISE_APPLICATION_ERROR 创建自己的错误处理。其语法如下:RAISE_APPLICATION_ERROR(error_number,error_message,[keep_errors] ) ;

这里的 error_number 是从 –20,000 到 –20,999 之间的参数, error_message 是相应的提示信息(< 512 字节), keep_errors 为可选,如果 keep_errors =TRUE ,则新错误将被添加到已经引发的错

误列表中。如果 keep_errors=FALSE(缺省),则新错误将替换当前的错误列表。--节选自在线代码 register.sqlREM 作者: Scott Urman.REM 中文注释:赵元杰CREATE OR REPLACE PROCEDURE Register ( p_StudentID IN students.id%TYPE, p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE) AS

v_CurrentStudents NUMBER; -- 班上学生的当前号 v_MaxStudents NUMBER; -- 班上学生的最大号BEGIN /* 找出学生的当前号和最大号 */ SELECT current_students, max_students INTO v_CurrentStudents, v_MaxStudents FROM classes

43

Page 44: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

WHERE course = p_Course AND department = p_Department;

/* 确认另外的学生是否有足够的教室*/ IF v_CurrentStudents + 1 > v_MaxStudents THEN RAISE_APPLICATION_ERROR(-20000, 'Can''t add more students to ' || p_Department || ' ' || p_Course); END IF;

/* 加一个学生在本班 */ ClassPackage.AddStudent(p_StudentID, p_Department, p_Course);

EXCEPTION WHEN NO_DATA_FOUND THEN

/* 教室信息不存在,触发错误处理*/ RAISE_APPLICATION_ERROR(-20001, p_Department || ' ' || p_Course || ' doesn''t exist!');END Register; /

§15.2 异常情态传播 由于异常情态 可以在声明部分和执行部分以及异常情态部分出现,因而在不同部分引发的异常情态也不一样。

§15.2.1 在执行部分引发异常情态 当一个异常情态在执行部分引发时,有下列情况:1)如果当前块对该异常情态设置了处理,则执行它并成功完成该块的执行,然后控制转给包含块。

2)如果没有对当前块异常情态设置定义处理器,则通过在包含块中引发它来传播异常情态。然后对该包含块执行步骤 1)。

44

Page 45: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§15.2.2 在声明部分引发异常情态

如果在声明部分引起异常情况,即在声明部分出现错误,那么该错误就能影响到其它的块。比如在有如下的 PL/SQL程序:DECLARE

Abc number(3)=’abc’;. . . . . .begin. . . . . .EXCEPTIONWHEN OTHERS THEN . . . . . .END;

例子中,由于 Abc number(3)=’abc’; 出错,尽管在 Exception 中说明了 WHEN OTHERS THEN语句,但WHEN OTHERS THEN也不会被执行。 但是如果在该错误语句块的外部有一个异常情态,则该错误就能被抓住,如:BeginDECLARE

Abc number(3)=’abc’;. . . . . .begin. . . . . .EXCEPTIONWHEN OTHERS THEN . . . . . .END;EXCEPTIONWHEN OTHERS THEN . . . . . .END;

45

Page 46: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§15.3 异常处理编程在一般的应用处理中,建议程序人员要用异常处理,因为如果你程序中不声明任何异常处理,则 在程序运行出错时,程序就被终止,并且也不提示任何信息。下面是使用系统提供的异常来编程的例子。例:这是真实例子的一部分:procedure delete_shift_fund(cur_accno varchar2,cur_procdate varchar2,rtn out number) is

beginset transaction use rollback segment hdhouse_rs;delete from shift_fund where out_acc_no=cur_accno;delete from shift_lst where acc_no=cur_accno and

to_char(proc_date,'yyyymmdd')=cur_procdate;commit;rtn:=1;

Exceptionwhen value_error then

rtn:=-1;rollback;

end;

在例子中,用到了when value_error then 语句。表示可能出现值赋值的错误。

§15.4 在 PL/SQL 中使用 sqlcode,sqlerrm

由于 oracle 的错误信息最大长度是 512 字节, 为了的到完整的错误提示信息,我们可用 sqlerrm 和 substr 函数一起得到错误提示信息。

sqlcode 返回错误代码数字,sqlerrm 返回错误信息.

如: sqlcode=+100 sqlerrm=’no data found ‘ sqlcode=0 sqlerrm=’normal, successfual completion’

例 1.

46

Page 47: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

declare . . . err_msg varchar2(100); begin /* 得到所有 ORACLE 错误信息 */ for err_num in 1 .. 9999 loop err_msg := sqlerrm(err_num); insert into errors values(err_msg);end loop;end;

例 2

-- 节选自在线代码 sqlerrm2.sql --节选自在线代码 sqlerrm2.sqlREM 作者: Scott Urman.REM 中文注释:赵元杰DECLARE v_ErrorText log_table.message%TYPE; -- Variable to hold error message textBEGIN /* SQLERRM(0) */ v_ErrorText := SUBSTR(SQLERRM(0), 1, 200); INSERT INTO log_table (code, message, info) VALUES (0, v_ErrorText, 'SQLERRM(0)');

/* SQLERRM(100) */ v_ErrorText := SUBSTR(SQLERRM(100), 1, 200); INSERT INTO log_table (code, message, info) VALUES (100, v_ErrorText, 'SQLERRM(100)');

/* SQLERRM(10) */ v_ErrorText := SUBSTR(SQLERRM(10), 1, 200); INSERT INTO log_table (code, message, info) VALUES (10, v_ErrorText, 'SQLERRM(10)');

/* SQLERRM with no argument */ v_ErrorText := SUBSTR(SQLERRM, 1, 200); INSERT INTO log_table (code, message, info) VALUES (NULL, v_ErrorText, 'SQLERRM with no argument');

/* SQLERRM(-1) */

47

Page 48: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

v_ErrorText := SUBSTR(SQLERRM(-1), 1, 200); INSERT INTO log_table (code, message, info) VALUES (-1, v_ErrorText, 'SQLERRM(-1)');

/* SQLERRM(-54) */ v_ErrorText := SUBSTR(SQLERRM(-54), 1, 200); INSERT INTO log_table (code, message, info) VALUES (-54, v_ErrorText, 'SQLERRM(-54)');

END; /

提示:虽然在 PL/SQL编程中,例外处理不是必须的,但建议编程人员要养成在 PL/SQL编程中指定相应的例外(错误处理)。最好针对明显可能出现的错误加以描述。否则,如果程序在运行时出现错误,程序就会被自动终止。而且许多被终止的 PL/SQL程序是不容易被用户发现的。

48

Page 49: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第十六章 存储过程和函数

ORACLE编写的程序一般分为两类,一种是可以完成一定功能的程序叫存储过程;另一种就是在使用时给出一个或多个值,处理完后返回一个或多个结果的程序叫函数。这两种程序都存放在Oracle数据库字典中。下面分别介绍这两种程序的编写方法。

§16.1 引言ORACLE 提供可以把 PL/SQL 程序存储在数据库中,并可以在任何地方来运行它。这样

就叫存储过程或函数。在本节中,主要介绍:1. 创建存储过程和函数2. 正确使用系统级的异常处理和用户定义的异常处理3. 建立和管理存储过程和函数

§16.2 存储过程与其它的数据库系统一样,Oracle的存储过程是用 PL/SQL语言编写的能完成一定处理

功能的存储在数据库字典中的程序。

§16.2.1 创建过程

建立内嵌过程 在 oracle server 上建立内嵌过程,可以被多个应用程序调用,可以向内嵌过程传递参数,也可以向内嵌过程传回参数.

创建过程语法:

create [or replace] procedure procedure_name [ (argment [ { in| in out }] type,

49

Page 50: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

argment [ { in | out | in out } ] type { is | as } <类型.变量的说明> ( 注: 不用 declare 语句 ) Begin <执行部分> exception <可选的异常处理说明>end;

这里的 IN 表示向存储过程传递参数,OUT 表示从存储过程返回参数。而 IN OUT 表示传递参数和返回参数;

在存储过程内的变量类型只能指定变量类型;不能指定长度; 在AS 或 IS 后声明要用到的变量名称和变量类型及长度; 在AS 或 IS 后声明变量不要加 declare 语句。

例 1.--节选自在线代码 modetest.sqlREM 作者: Scott Urman.REM 中文注释:赵元杰CREATE OR REPLACE PROCEDURE ModeTest ( p_InParameter IN NUMBER, p_OutParameter OUT NUMBER, p_InOutParameter IN OUT NUMBER) IS

v_LocalVariable NUMBER;

BEGIN /* 分配 p_InParameter 给 v_LocalVariable. */ v_LocalVariable := p_InParameter; -- Legal /* 分配 7 给 p_InParameter. 这是非法的,因为声明是 IN */ p_InParameter := 7; -- Illegal

/* 分配 7 给 p_InParameter. 这是合法的,因为声明是OUT */ p_OutParameter := 7; -- Legal

/* 分配 p_OutParameter 给 v_LocalVariable.这是非法的,因为声明是 IN */ v_LocalVariable := p_outParameter; -- Illegal

/* 分配 p_InOutParameter 给 v_LocalVariable. 这是合法的,因为声明是 IN OUT */ v_LocalVariable := p_InOutParameter; -- Legal

50

Page 51: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

/*分配 7 给 p_InOutParameter. 这是合法的,因为声明是 IN OUT */ p_InOutParameter := 7; -- LegalEND ModeTest;/

§16.2.2 使用过程 存储过程建立完成后,只要通过授权,用户就可以在 SQLPLUS 、Oracle开发工具或第三方开发工具来调用运行。Oracle 使用 EXECUTE 语句来实现对存储过程的调用。EXEC[UTE] procedure_name( parameter1, parameter2…);

例:CREATE PACKAGE emp_data ASTYPE EmpRecTyp IS RECORD (emp_id NUMBER(4),emp_name VARCHAR2(10),job_title VARCHAR2(9),dept_name VARCHAR2(14),dept_loc VARCHAR2(13));TYPE EmpCurTyp IS REF CURSOR RETURN EmpRecTyp;PROCEDURE get_staff (dept_no IN NUMBER,emp_cv IN OUT EmpCurTyp);END;/CREATE PACKAGE BODY emp_data ASPROCEDURE get_staff (dept_no IN NUMBER,emp_cv IN OUT EmpCurTyp) ISBEGINOPEN emp_cv FORSELECT empno, ename, job, dname, loc FROM emp, deptWHERE emp.deptno = dept_no AND emp.deptno = dept.deptnoORDER BY empno;END;END;/COLUMN EMPNO HEADING Number

COLUMN ENAME HEADING NameCOLUMN JOB HEADING JobTitle

51

Page 52: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

COLUMN DNAME HEADING DepartmentCOLUMN LOC HEADING LocationSET AUTOPRINT ONVARIABLE cv REFCURSOREXECUTE emp_data.get_staff(20, :cv)

§16.2.3 开发存储过程步骤

目前的几大数据库厂商提供的编写存储过程的工具都没有统一,虽然它们的编写风格有些相似,但由于没有标准,所以各家的开发调试过程也不一样。下面编写 PL/SQL存储过程、函数、包及触发器的步骤如下:

§16.2.3.1 编辑存储过程源码使用文字编辑处理软件编辑存储过程源码,要用类似 WORD 文字处理软件进行编辑时,要将源码存为文本格式。

§16.2.3.2 对存储过程程序进行解释在 SQLPLUS 或用调试工具将 存储过程程序进行解释;在 SQL>下调试,可用 start 或 get 等Oracle 命令来启动解释。如:SQL>start c:\stat1.sql

如果使用调试工具,可直接编辑和点击相应的按钮即可生成存储过程。

§16.2.3.3 调试源码直到正确我们不能保证所写的存储过程达到一次就正确。所以这里的调试是每个程序员必须进行的工作之一。在 SQLPLUS下来调试主要用的方法是:1. 使用 SHOW ERROR 命令来提示源码的错误位置;2. 使用 user_errors 数据字典来查看各存储过程的错误位置。

52

Page 53: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§16.2.3.4 授权执行权给相关的用户或角色如果调试正确的存储过程没有进行授权,那就只有建立者本人才可以运行。所以作为应用系统的一部分的存储过程也必须进行授权才能达到要求。 在 SQLPLUS下可以用GRANT 命令来进行存储过程的运行授权。GRANT语法:GRANT system_privilege | role TO user | role | PUBLIC[WITH ADMIN OPTION]GRANT object_privilege | ALL column ON schema.objectFROM user | role | PUBLIC WITH GRANT OPTION

变量:system_privilege: 系统权限role: 角色名user: 被授权的用户名object_privilege: 所授予的权限名字,可以是

ALTER DELETE EXECUTE INDEX INSERT REFERENCES SELECT UPDATE

Column: 列名schema: 模式名object: 对象名例子:GRANT team_leader TO crystal;GRANT INSERT, UPDATE ON sales TO larry WITH GRANTOPTION;GRANT ALL TO PUBLIC;.

§16.2.4 与存储过程相关数据字典

user_source 用户的存储过程、函数的源代码字典

53

Page 54: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

all_source 所有用户的存储过程、函数的源代码字典user_errors 用户的存储过程、函数的源代码存在错误的信息字典相关的权限:create any proceduredrop any procedure

如果某个用户没有权限来创建存储过程,则需要DBA将创建过程的权限授予某用户。如:sql>grant create any procedure to user1;

§16.3 创建函数Oracle的函数是一个独有的对象,它也是由 PL/SQL语句编写而成,但的不同的地方是:函数必须返回某些值,而存储过程可以不返回任何值。与创建存储过程类似,创建函数的语法如下:1.建立内嵌函数

CREATE FUNCTION语法如下:create [or replace] function function_name [ (argment [ { in| in out }] TYPE, argment [ { in | out | in out } ] type] return return_type { is | as } begin function_body

exception . . . . . . end;

例 1.

create or replace function text_len( t varchar2, l number ) return varchar2 as tmp varchar2(20); begin tmp := substr( t, 1, l ); return to_char(l)||’ ‘||tmp; end;

54

Page 55: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例 2. 较为复杂的函数:REM 选自 clasinfo.sqlREM 作者: Scott Urman.REM 中文注释:赵元杰CREATE OR REPLACE FUNCTION ClassInfo ( /* 如果教室全满,则返回 'Full' 如果教室超过 80%,则返回'Some Room' 如果教室超过 60%,则返回'More Room' 如果教室小于 60%,则返回'Lots of Room' 如果教室没有学生,则返回'Empty'. */ p_Department classes.department%TYPE, p_Course classes.course%TYPE) RETURN VARCHAR2 IS

v_CurrentStudents NUMBER; v_MaxStudents NUMBER; v_PercentFull NUMBER;BEGIN -- 得到学生的当前和最大值 SELECT current_students, max_students INTO v_CurrentStudents, v_MaxStudents FROM classes WHERE department = p_Department AND course = p_Course;

-- 计算当前的百分比. v_PercentFull := v_CurrentStudents / v_MaxStudents * 100;

IF v_PercentFull = 100 THEN RETURN 'Full'; ELSIF v_PercentFull > 80 THEN RETURN 'Some Room'; ELSIF v_PercentFull > 60 THEN RETURN 'More Room'; ELSIF v_PercentFull > 0 THEN RETURN 'Lots of Room'; ELSE RETURN 'Empty'; END IF;END ClassInfo;/

55

Page 56: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§16.4 过程和函数中的例外处理与编写存储过程一样,在编写 PL/SQL 函数时,也需要对可能出现的各种错误进行描述,以保证函数在运行中出现错误时,程序能按照我们定义的要求进行处理。

§16.4.1 使用系统定义的例外处理

§16.4.1.1 没有例外处理的缺点如果在编写时没有给出 EXCEPTION 的话,一旦出现例外的情况,Oracle就自动终止程序的运行。如果编写的程序没有给出例外处理,则当程序出错时用户无法得到提示,调试者也无法进行修改程序。所以,一般无论多简单的程序最好也要给出例外处理的要求。

§16.4.1.2 使用预定义的例外处理例。实际例子:procedure sum_interest_year(cur_procdate in varchar2 ,rtn out number) is

/***********************************************************************//* 程序名: sprocess.SQL *//* 功能: 由 PB 调用的 PL/SQL子过程集,公积金转移金额及利息的计算等.... *//* 编程语言: PL/SQL for ORACLE 7.3.2,oracle8 v8.x *//* 运行环境: ORACLE 7.3.X, oracle8i *//* 修 改 : 赵元杰 *//* 修改日期: 1999 06.25 */ /**********************************************************************/

datestr varchar2(10);ls_procdate varchar2(10);ls_year varchar2(10);

begin/*修改定期主表年终余额、利息、积数、状态位,将年余额按新的一年加入 per_fix_det,status='0';

56

Page 57: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

将 per_detail.status='1',per_fix_det.status='1',per_fix_det and per_detail 的余额转入 per_fix_abst,将年结数据加入年余额表 save_bal修改系统表日期 sssyspar.yearbegin=date_str*/

set transaction use rollback segment hdhouse_rs;select distinct to_char(procdate,'yyyymmdd') into ls_procdate

from vw_tmp_inte;select to_char(to_number(substr(yearbegin,1,4))+1) into ls_year

from sssyspar;if substr(ls_procdate,1,4)<>ls_year then

rtn:=-1;return;

elsif substr(ls_procdate,5,4)<>'0630' thenrtn:=-1;return;

end if;datestr:=substr(cur_procdate,1,4)||substr(cur_procdate,6,2)||substr(cur_procdate,9,2);update per_fix_abst set (avail_bal,acc_int,acc_int_fix,interest,

interest_b,crea_int,crea_int_b) =(select bal+inteval+inteval_fix,acumbase,acumbase_fix,

inteval_c+inteval_c_fix,inteval+inteval_fix,0,0from vw_tmp_inte where per_fix_abst.acc_no=vw_tmp_inte.accno

and per_fix_abst.emp_acc_no=vw_tmp_inte.emp_accno)

where nvl(acc_status,'0')='0';if sqlcode!=0 then

rtn:=sqlcode;rollback;return;

end if;

update per_abst set avail_bal=0,accu_int=0,interest=0where nvl(acc_status,'0')='0';if sqlcode!=0 then

rtn:=sqlcode;rollback;return;

end if;

update per_detail set status='1' where nvl(status,'0')='0'and to_char(crea_date,'yyyy/mm/dd')<=cur_procdate;

if sqlcode!=0 then

57

Page 58: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

rtn:=sqlcode;rollback;return;

end if;

update per_fix_det set status='1' where nvl(status,'0')='0'and to_char(crea_date,'yyyy/mm/dd')<=cur_procdate;

if sqlcode!=0 thenrtn:=sqlcode;rollback;return;

end if;

insert into per_fix_det(acc_no,emp_acc_no,tran_date,tran_val,tran_code,balance,db_cr_flag,cash_check,memo,crea_date,base_int,status,bank_code)select acc_no,emp_acc_no,to_date(substr(cur_procdate,1,4)||'/07/01','yyyy/mm/dd'),

avail_bal,'',avail_bal,'1','0','年结',to_date(substr(cur_procdate,1,4)||'/07/01','yyyy/mm/dd'),

0,'0',bank_codefrom per_fix_abst where nvl(acc_status,'0')='0';

if sqlcode!=0 thenrtn:=sqlcode;rollback;return;

end if;

insert into save_bal(acc_no,emp_acc_no,cal_year,balance,interest,interest_b,accu_int,accu_int_fix,rate_c,rate_c_fix,rate_b,rate_b_fix)

select acc_no,emp_acc_no,datestr,avail_bal,interest,interest_b,acc_int,acc_int_fix,sssyspar.rate_val_c,sssyspar.rate_fixval_c,sssyspar.rate_val_b,sssyspar.rate_fixval_b

from per_fix_abst ,sssysparwhere nvl(acc_status,'0')='0';

if sqlcode!=0 thenrtn:=sqlcode;rollback;return;

end if;

update sssyspar set yearbegin=substr(cur_procdate,1,4)||'-07-01';if sqlcode!=0 then

58

Page 59: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

rtn:=sqlcode;rollback;return;

end if;

commit;rtn:=1;exception

when no_data_found thenrtn:=sqlcode;rollback;

when others thenrtn:=sqlcode;rollback;

end;

§16.4.2 使用用户定义的例外处理+

§16.4.2.1 定义的用户例外处理PL/SQL可以让你定义自己的例外。与预定义不同,用户定义的例外必须声明且必须用RAISE语句来激活(raise)。

声明例外例外必须在PL/SQL块、子程序或包中进行声明。但不能在一个块里声明两次。但可以在两个块中对同一个例外进行声明。

§16.4.2.2 使用户 EXCEPTION_INIT处理在PL/SQL的程序中,除了所列出的系统错误代码外,实际上还有许多的可能错误。这些内部异常(错误)必须用OTHERS 或 EXCEPTION_INIT 来处理,实际程序(pragma)是一个编译指示器。它是通过一个叫附加说明来传给编译器。Pragma(也叫伪指令)是在编译时内处理,不是在运行时被处理。

59

Page 60: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DECLAREdeadlock_detected EXCEPTION;PRAGMA EXCEPTION_INIT(deadlock_detected, -60);

BEGIN...EXCEPTIONWHEN deadlock_detected THEN-- handle the errorEND;

§16.4.2.3 使用户 raise_application_error处理例:CREATE PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) AScurr_sal NUMBER;

BEGINSELECT sal INTO curr_sal FROM emp WHERE empno = emp_id;IF curr_sal IS NULL THEN/* 发布用户定义的错误信息 */raise_application_error(-20101, ’Salary is missing’);ELSEUPDATE emp SET sal = curr_sal + amount WHERE empno = emp_id;END IF;END raise_salary;

第十七章 创建包和使用包

Oracle系统可以把存储过程和函数按照功能的相关性存放在一起,这样的一组对象就叫做包。下面介绍包的建立和使用。

60

Page 61: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§17.1 引言把相关的过程和函数归类到一个起并赋予一定的管理功能和使用就叫包。把相关的模块归类成为包可使开发人员利用面向对象的方法进行内嵌过程的开发,从而提高系统性能。 包中包含过程和函数,它们共享公共的变量,公共的局部函数和过程。一个包由两个分开的部分组成.

包说明( package soecification) ( 定义包所包含的过程,函数,数据类型和变量) 包主体( package body ) ( 包中对象的代码 )

包说明和包主体分开编译,并作为两部分分开的对象存放,在数据库字典中,详见数据字典 user_source, all_source,dba_source.

§17.2 包的定义要想将相关的一组存储过程和函数存放在一起,必须创建相应的包。

包定义的语法如下:CREATE [OR REPLACE] PACKAGE package_name[AUTHID {CURRENT_USER | DEFINER}]{IS | AS}[PRAGMA SERIALLY_REUSABLE;][collection_type_definition ...][record_type_definition ...][subtype_definition ...][collection_declaration ...][constant_declaration ...][exception_declaration ...][object_declaration ...][record_declaration ...][variable_declaration ...][cursor_spec ...]

61

Page 62: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

[function_spec ...]

[procedure_spec ...]

[call_spec ...]

[PRAGMA RESTRICT_REFERENCES(assertions) ...]

END [package_name];

[CREATE [OR REPLACE] PACKAGE BODY package_name {IS | AS}

[PRAGMA SERIALLY_REUSABLE;]

[collection_type_definition ...]

[record_type_definition ...]

[subtype_definition ...]

[collection_declaration ...]

[constant_declaration ...]

[exception_declaration ...]

[object_declaration ...]

[record_declaration ...]

[variable_declaration ...]

[cursor_body ...]

[function_spec ...]

[procedure_spec ...]

[call_spec ...]

[BEGIN

sequence_of_statements]

END [package_name];]

§17.3 包的开发步骤与开发存储过程类似,包的开发需要几个步骤:1. 将每个存储过程调试正确;2. 用文本编辑软件将各个存储过程和函数集成在一起;3. 按照包的定义要求将集成的文本的前面加上包头;4. 按照包的定义要求将集成的文本的前面加上包体;5. 使用 SQLPLUS 或开发工具进行调试。

62

Page 63: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§17.4 包的头部说明包的头部的说明主要包括是将包所要包含的所有的存储过程、函数进行说明。严格来说,就是把形成包的所有存储过程和函数的名字、变量等进行说明,以便在包体部分进行描述。它所用语法是:CREATE [OR REPLACE] PACKAGE package_name[AUTHID {CURRENT_USER | DEFINER}]{IS | AS}[PRAGMA SERIALLY_REUSABLE;][collection_type_definition ...][record_type_definition ...][subtype_definition ...][collection_declaration ...][constant_declaration ...][exception_declaration ...][object_declaration ...][record_declaration ...][variable_declaration ...] [cursor_spec ...]

[function_spec ...]

[procedure_spec ...]

[call_spec ...]

[PRAGMA RESTRICT_REFERENCES(assertions) ...]

END [package_name];

§17.5 包体的说明包体是独立于包头的另外数据库对象,也就是说,在编写整个存储包时,虽然我们将包头和包体写在一个文件(一个程序)并在SQL>下进行解释生成包程序。但是经过Oracle的PL/SQL解释的程序会被分成包的头部、包的体部及存储过程、函数部分。当我们查询数据库字典时,可以看到Oracle数据库是将包头和包体分开的。 包体的创建语法如下:[CREATE [OR REPLACE] PACKAGE BODY package_name {IS | AS}[PRAGMA SERIALLY_REUSABLE;][collection_type_definition ...][record_type_definition ...][subtype_definition ...]

63

Page 64: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

[collection_declaration ...][constant_declaration ...][exception_declaration ...][object_declaration ...][record_declaration ...][variable_declaration ...][cursor_body ...][function_spec ...][procedure_spec ...][call_spec ...][BEGINsequence_of_statements]END [package_name];]

例子。创建包的例子:

REM 选自 clpack.sqlREM 作者: Scott Urman.REM 中文注释:赵元杰 CREATE OR REPLACE PACKAGE ClassPackage AS

--加一新的学生到指定的班. PROCEDURE AddStudent(p_StudentID IN students.id%TYPE, p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE);

-- 指定的班删除某个学生. PROCEDURE RemoveStudent(p_StudentID IN students.id%TYPE, p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE);

-- 触发删除学生的例外处理. e_StudentNotRegistered EXCEPTION;

-- 使用表类型来处理学生信息. TYPE t_StudentIDTable IS TABLE OF students.id%TYPE INDEX BY BINARY_INTEGER;

-- 在指定的班上返回 PL/SQL 表学生内容 PROCEDURE ClassList(p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE,

64

Page 65: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

p_IDs OUT t_StudentIDTable, p_NumStudents IN OUT BINARY_INTEGER);END ClassPackage;/

CREATE OR REPLACE PACKAGE BODY ClassPackage AS--加一新的学生到指定的班.

PROCEDURE AddStudent(p_StudentID IN students.id%TYPE, p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE) IS BEGIN INSERT INTO registered_students (student_id, department, course) VALUES (p_StudentID, p_Department, p_Course); COMMIT; END AddStudent;

-- 从指定班中删除一个学生.

PROCEDURE RemoveStudent(p_StudentID IN students.id%TYPE, p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE) IS BEGIN DELETE FROM registered_students WHERE student_id = p_StudentID AND department = p_Department AND course = p_Course;

-- 检查 DELETE 操作是否成功,如果无匹配的行,则触发错误处理 IF SQL%NOTFOUND THEN RAISE e_StudentNotRegistered; END IF;

COMMIT; END RemoveStudent;

-- 在指定的班上返回 PL/SQL 表学生内容 PROCEDURE ClassList(p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE, p_IDs OUT t_StudentIDTable, p_NumStudents IN OUT BINARY_INTEGER) IS

v_StudentID registered_students.student_id%TYPE;

65

Page 66: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

-- 声明取已经注册学生的信息的光标. CURSOR c_RegisteredStudents IS SELECT student_id FROM registered_students WHERE department = p_Department AND course = p_Course; BEGIN

/* p_NumStudents 变量为表索引,开始为 0;每次循环时增加。循环结束时,它存放有取到的行数量。并且以 p_IDs 返回 行数 */

p_NumStudents := 0;

OPEN c_RegisteredStudents; LOOP FETCH c_RegisteredStudents INTO v_StudentID; EXIT WHEN c_RegisteredStudents%NOTFOUND;

p_NumStudents := p_NumStudents + 1; p_IDs(p_NumStudents) := v_StudentID; END LOOP; END ClassList;END ClassPackage;/

§17.6 删除过程、函数和包对那些不再需要的存储过程、函数或包,只要具有 DROP ANY PROCEDURE权限,就

可以删除它们。1.删除过程我们可以 DROP PROCEDURE 命令对不需要的过程进行删除,语法如下:DROP PROCEDURE [user.]procudure_name;

与DROP PROCEDURE 有关的内容请参见 Alter Procedure和 Create Procedure。

66

Page 67: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

2.删除函数我们可以 DROP Function 命令对不需要的函数进行删除,语法如下:DROP FUNCTION [user.]function_name;

与DROP FUNCTION 有关的内容请参见 Alter Function和 Create Function。3.删除包我们可以 DROP PACKAGE 命令对不需要的包进行删除,语法如下:DROP PACKAGE [BOAY] [user.]package_name;

与DROP PACKAGE 有关的内容请参见 Alter package和 Create package。

§17.7 包的管理当开发已经将包创建在数据库中之后,就开始面临对包的管理的问题。由于包的源代码

是存放 Oracle的数据字典里,不象在文件系统下直接可以浏览和拷贝等那样方便,所以包的管理对DBA来说更具挑战性。下面是本人在日常工作对包的管理的一点小结。

§17.7.1 包有关的数据字典与Oracle系统的包有关的数据字典有:DBA_SOURCEDBA_ERRORS

1.DBA_SOURCE数据字典:DBA_SOURCE数据字典存放有整个Oracle系统的所有包、存储过程、函数的源代码。它的列及说明如下:列名 数据类型 是否空 说明Owner Varchar2(30) Not null 对象的主人Name Varchar2(30) Not null 对象名称Type Varchar2(12) 对象类型,可以是 PROCEDURE,FUNCTION,

PACKAGE,TYPE,TYPE BODY ,PACKAGE BODY

67

Page 68: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Line Number Not null 行号text Varchar2(4000) 源代码

2.DBA_ERRORS数据字典:DBA_ERRORS存放所有对象的错误列表。编程人员和DBA可以从中查看错误的对象名及错误内容。它的列说明如下:列名 数据类型 是否空 说明Owner Varchar2(30) Not null 对象的主人Name Varchar2(30) Not null 对象名称Type Varchar2(12) 对象类型,可以是 PROCEDURE,FUNCTION,

PACKAGE,TYPE,TYPE BODY ,PACKAGE BODYsequence number Not null 顺序号Line Number Not null 行号position number Not null 错误在行中的位置(列)text Varchar2(4000) 错误代码

§17.7.2 包中无效对象的查询和编译使用过Oracle的 PL/SQL编程的人员都有这样的体会,已经存放在数据字典中的存储过

程或函数有时会变为无效而不能运行。有经验的 DBA 会经常去浏览数据库系统内是否存在无效的对象,从而对其进行编译。1.查询无效的对象例子例 1. 自动产生无效对象的编译命令:/* 功能:自动产生无效对象的编译命令脚本 */ /* 作者:赵元杰 2001.10 *//* 使用版本:Oracle 7, oarcle8I */

/* 使用 SPOOL 将显示的信息(即脚本)写到文件 comp_objs.sql中 */SPOOL c:\comp_objs.sql

SELECT 'SET FEEDBACK ON' FROM DUAL;

68

Page 69: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

-- 产生无效对象的提示信息 和 产生 Alter 编译命令.-- 这里的CHR(10)是换行命令SELECT 'PROMPT Compile PROCEDURE ' || OBJECT_NAME || ' ...' || CHR(10) || 'ALTER PROCEDURE ' || OBJECT_NAME || ' COMPILE;' || CHR(10) || 'SHOW ERRORS;' || CHR(10) || 'PROMPT;' FROM USER_OBJECTS WHERE STATUS <> 'VALID' AND OBJECT_TYPE = 'PROCEDURE' ORDER BY OBJECT_NAME;

SELECT 'PROMPT Compile FUNCTION ' || OBJECT_NAME || ' ...' || CHR(10) || 'ALTER FUNCTION ' || OBJECT_NAME || ' COMPILE;' || CHR(10) || 'SHOW ERRORS;' || CHR(10) || 'PROMPT;' FROM USER_OBJECTS WHERE STATUS <> 'VALID' AND OBJECT_TYPE = 'FUNCTION' ORDER BY OBJECT_NAME;

SELECT 'PROMPT Compile PACKAGE ' || OBJECT_NAME || ' ...' || CHR(10) || 'ALTER PACKAGE ' || OBJECT_NAME || ' COMPILE;' || CHR(10) || 'SHOW ERRORS;' || CHR(10) || 'PROMPT;' FROM USER_OBJECTS WHERE STATUS <> 'VALID' AND OBJECT_TYPE = 'PACKAGE' ORDER BY OBJECT_NAME;

SELECT 'PROMPT Compile PACKAGE BODY ' || OBJECT_NAME || ' ...' || CHR(10) || 'ALTER PACKAGE ' || OBJECT_NAME || ' COMPILE BODY;' || CHR(10) || 'SHOW ERRORS;' || CHR(10) || 'PROMPT;' FROM USER_OBJECTS WHERE STATUS <> 'VALID' AND OBJECT_TYPE = 'PACKAGE BODY' ORDER BY OBJECT_NAME;

2.执行编译无效对象的脚本:用下面命令启动由 SPOOL产生的脚本就可以实现自动编译无效包对象。SQL>start c:\coomp_objs.sql

69

Page 70: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§17.7.3 包源代码的导出当我们在进行应用系统的移植、分析、升级等都需要将包的源代码导出。一般情况下,

Oracle不提供这样的操作。这里给出一个简单的导出方法供 PL/SQL程序人员参考。例 1. 自动产生重新创建所有 PL/SQ的命令:/* 功能:自动产生创建脚本的源代码。 *//* 作者: 赵元杰 2001.10 */

SELECT DECODE(ROWNUM, 1, 'CREATE OR REPLACE '|| RTRIM(RTRIM(us.text, CHR(10) )),RTRIM(RTRIM(us.text, CHR(10) ))) textFROM user_source us ORDER BY us.name , us.type , us.line;

例 2. 存储过程源代码的提取:/***************************************************************//* 文件名:exp_plsql.sql *//* 功能:导出存储过程的源代码 *//* 使用方法:在 SQL>用 start 运行 exp_plsql.sql 文件,如: *//* SQL>start c:\exp_plsq.sql *//* 在提示输入: *//* 在“导出对象名字:”中输入 PL/SQL过程的名字 *//* 在“导出文件名”中输入路径和导出的文件名 *//***************************************************************/

accept proc_name char prompt '导出对象名字:'accept file_name char prompt '导出文件名:'set pagesize 10000set verify offset termout offset feedback offcol dummy_col new_value max_len noprintselect max(length(text)) dummy_col from dba_sourcewhere upper(name) = upper('&proc_name');

set linesize &max_lenspool & file_name

70

Page 71: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SELECT name||' ('||type||')' "Infos about" from dba_sourceWHERE upper(name) = upper('&proc_name') and rownum < 2;

SELECT text "SQL-Code" from dba_source WHERE upper(name) = upper('&proc_name');

spool offset verify onset termout onset feedback on

SQL> start c:\exp_plsql.txt导出对象名字:f81_index_object导出文件名:c:\exp2SQL>

第十八章 触发器

触发器是许多关系数据库系统都提供的一项技术。在 oracle系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的 PL/SQL 块。

§18.1 触发器类型触发器在数据库里以独立的对象存储,它与存储过程不同的是,存储过程通过其它程序来启动运行或直接启动运行,而触发器是由一个事件来启动运行。即触发器是当某个事件发生时自动地隐式运行。并且,触发器不能接收参数。所以运行触发器就叫触发或点火(firing)。在Oracle 里,触发器事件指的是对数据库的表进行的 INSERT、UPDATE及DELETE 操作或对视图进行类似的操作。Oracle目前的版本将触发器的功能扩展到了触发 Oracle系统事件,如数据库的启动与关闭等。

71

Page 72: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§18.1.1 DML触发器

Oracle可以在 DML语句进行触发,可以在 DML 操作前或操作后进行触发,并且可以对每个行或语句操作上进行触发。

§18.1.2 替代触发器

由于在Oracle 里,不能直接对由两个以上的表建立的视图进行操作。所以给出了替代触发器。它就是Oracle8专门为进行视图操作的一种处理方法。

§18.1.3 系统触发器

Oracle8i 提供了第三种类型的触发器叫系统触发器。它可以在 Oracle数据库系统的事件中进行触发,如Oracle系统的启动与关闭等。

§18.2 创建触发器创建触发器的一般语法是:

CREATE [ OR REPLACE]TRIGGER trigger_name[ BEFORE|AFTER ]trigger_event ON table_reference[ FOR EACH ROW [WHEN trigger_condition] ]trigger_body;

当一个基表被修改( insert,update,delete)时要执行的内嵌过程。执行时根据其所依附的 基表改动而自动触发,因此与应用程序无关,用数据库触发器可以保证数据的一致性和完整性.

每张表最多可建立 12 个触发器,它们是:

before insert

72

Page 73: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

before insert for each rowafter insertafter insert for each row

before updatebefore update for each rowafter updateafter update for each row

before deletebefore delete for each rowafter deleteafter delete for each row

§18.2.1 创建DML触发器

触发器名与过程名和包的名字不一样,它是单独的名字空间,因而触发器名可以和 表 或过程 有相同的名字,但在一个模式中触发器名不能相同。

触发器的限制 触发器有下面一些限制:。触发器中不能使用控制语句 COMMIT,ROLLBACK, SVAEPOINT 语句;。由触发器所调用的过程或函数也不能使用控制语句;。触发器中不能使用 LONG,LONG RAW 类型;。触发器所访问的表受到远表的约束限制,即后面的“变化表”。

问题:当触发器被触发时,要使用被插入,更新或删除的记录中的列值,有时要使用操作前, 后列的值.实现: :new 修饰符访问操作完成后列的值 :old 修饰符访问操作完成前列的值例 1: 建立一个触发器,当职工表 emp 表被删除一条记录时,把被删除记录写到职工表删除日志表中去. /**********************************************************************//* 功 能 : 当员工表数据被删除时,记录被删除的记录。 *//* 文件名 : del_emp.sql */

73

Page 74: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

/* 作 者 : 赵元杰 2001.5.31 *//**********************************************************************/

create or replace trigger scott.del_emp before delete on scott.emp for each rowbegin -- 将 修改前数据插入到 日志记录 表 del_emp, 以供监督使用。 insert into emp_his( deptno , empno, ename , job ,mgr , sal , comm , hiredate ) values( :old.deptno, :old.empno, :old.ename , :old.job, :old.mgr, :old.sal, :old.comm, :old.hiredate ); end;

/show errors

§18.2.2 创建替代(Instead_of)触发器

Instead_of 用于对视图的 DML 触发,由于视图有可能是由多个表进行联结(join)而成,因而并非是所有的联结都是可更新的。但可以按照所需的方式执行更新,例如下面情况:--节选自在线代码 instead.sqlCREATE VIEW room_summary AS SELECT building,sum(number_seats) total_seats FROM rooms GROUP BY building;

在此视图中直接删除是非法的:SQL>DELETE FROM rooms_summary WHERE building=’Building 7’;DELETE FROM rooms_summary WHERE building=’Building 7’; *ERROR at line 1:ORA-01732:data manipulation operation not legal on this view

但是我们可以创建 Instead_of 触发器来为 DELETE 操作执行所需的处理,即删除 rooms 表中所有基准行:--节选自在线代码 instead.sql

74

Page 75: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE TRIGGER room_summary_delete INSTEAD OF DELETE ON room_summary FOR EACH ROWBEGIN -- 删除表 room 中行,这些行构成单个视图行。 DELETE FROM rooms WHERE building = :old.building;END room_summary_delete;

§18.2.3 创建系统触发器

Oracle8i 提供的系统触发器可以在DDL 或数据库系统上被触发。DDL 指的是数据定义语言,如 CREATE ,ALTER及DROP 等。而数据库系统事件包括数据库服务器的启动或关闭,用户的登录与退出、数据库服务错误等。创建系统触发器的语法如下:CREATE OR REPLACE TRIGGER [sachema.] trigger_name{BEFORE|AFTER}{ddl_event_list|database_event_list}ON { DATABASE | [schema.] SCHEMA }[ when_clause] trigger_body;

ddl_event_list: 一个或多个DDL 事件,事件间用 OR 分开;database_event_list: 一个或多个数据库事件,事件间用 OR 分开;下面给出系统触发器的种类和事件出现的时机(前或后):事件 允许的时机 说明启动 之后 实例启动时激活关闭 之前 实例正常关闭时激活服务器错误 之后 只要有错误就激活登录 之后 成功登录后激活注销 之前 开始注销时激活创建 之前,之后 在创建之前或之后激活撤消 之前,之后 在撤消之前或之后激活变更 之前,之后 在变更之前或之后激活系统触发器可以在数据库级(database)或模式(schema)级进行定义。数据库级触发器在任何事件都激活触发器,而模式触发器只有在指定的模式的触发事件发生时才触发。

75

Page 76: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例:建立一个当用户USERA登录时,自动记录一些信息的触发器:CREATE OR REPLACE TRIGGER loguserAconnectsAFTER LOGON ON SCHEMABEGININSERT INTO example.temp_tableVALUES(1,’LogUserAConnects fired!’);END loguserAconnects;

例:建立一个当用户USERB登录时,自动记录一些信息的触发器:CREATE OR REPLACE TRIGGER loguserAconnectsAFTER LOGON ON SCHEMABEGININSERT INTO example.temp_tableVALUES(2,’LogUserAConnects fired!’);END loguserBconnects;

例:建立一个当所有用户登录时,自动记录一些信息的触发器:CREATE OR REPLACE TRIGGER logALLconnectsAFTER LOGON ON SCHEMABEGININSERT INTO example.temp_tableVALUES(3,’LogUserAConnects fired!’);END logALLconnects;

SQL>connect usera/useraConnected.SQL>connect userb/userbConnected.SQL>connect scott/tigerConnected.SQL>select * from temp_table;

Num_COL CHAR_COL-------------- -------------------------------- 3 LogALLConnects fired! 2 LoguserBConnects fired! 3 LogALLConnects fired! 3 LogALLConnects fired! 1 LoguserAConnects fired!

76

Page 77: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§18.2.4 触发器触发次序Oracle 对事件的触发共有 16种,但是它们的触发是有次序的,基本触发次序如下:

1) 执行 BEFORE语句级触发器;2) 对与受语句影响的每一行: a) 执行 BEFORE语句行级触发器b) 执行 DML语句c) 执行 AFTER行级触发器

3)执行 AFTER语句级触发器

§18.2.5 使用触发器谓词 ORACLE 提供三个参数 INSERTING,UPDATEING,DELETING 用于判断触发了哪些操作。谓词的行为如下:谓词 行为INSERTING 如果触发语句是 INSERT 语句,则为 TRUE,否则为 FALSEUPDATING 如果触发语句是 UPDATE语句,则为 TRUE,否则为 FALSEDELETING 如果触发语句是 DELETE 语句,则为 TRUE,否则为 FALSE

例--节选自在线代码 Rschange.sql

REM 选自:RSchange.sqlREM 作者: Scott Urman.REM 中文注释:赵元杰CREATE OR REPLACE TRIGGER LogRSChanges BEFORE INSERT OR DELETE OR UPDATE ON registered_students FOR EACH ROWDECLARE v_ChangeType CHAR(1);BEGIN /* INSERT 用’I’, DELETE用’D’, UPDATE 用’U’ */ IF INSERTING THEN v_ChangeType := 'I';

77

Page 78: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ELSIF UPDATING THEN v_ChangeType := 'U'; ELSE v_ChangeType := 'D'; END IF;

/* 在RS_audit 记录所有的改变,使用 sysdate 来产生系统时间邮戳, 使用 user 返回当前用户的标识 */

INSERT INTO RS_audit (change_type, changed_by, timestamp, old_student_id, old_department, old_course, old_grade, new_student_id, new_department, new_course, new_grade) VALUES (v_ChangeType, USER, SYSDATE, :old.student_id, :old.department, :old.course, :old.grade, :new.student_id, :new.department, :new.course, :new.grade);END LogRSChanges;/

§18.3 删除和使能触发器当触发器创建完成后,程序员和 DBA 管理员要经常关心数据库实例中的触发器的情况。对于不必需的触发器,要进行删除或使触发器无效,从而使系统的性能有所提高。删除触发器的命令语法如下:DROP TRIGGER trigger_name;

例:从数据子字典中删除某个触发器:SQL> select trigger_name from user_triggers;

TRIGGER_NAME------------------------------SET_NLS

SQL> drop trigger set_nls;

触发器已丢弃使触发器无效的命令是ALTER TRIGGER,它的语法如下:ALTER TRIGGER triiger_name [DISABLE | ENABLE ];

78

Page 79: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

如:SQL> ALTER TRIGGER updatemajorstats DISABLE;

SQL> alter table students disable all triggers;

§18.4 创建触发器的限制编写触发器程序时有些限制,希望程序人员注意下面的一些情况:1.代码大小:一般的触发器的代码大小必须小于32K;如果大于这个限制,可以将其拆成几个部分来写。2.触发器中有效的语句:可以包括DML SQL语句,但不能包括DDL 语句。ROLLBACK, COMMIT, and SAVEPOINT也不能使用。但是,对于“系统触发器( system triggers)”可以使用CREATE/ALTER/DROP TABLE和Alter … COMPILE语句。3. LONG, LONG RAW和LOB的限制:

不能插入数据到LONG或LONG RAW; 来自LONG或LONG RAW的数据可以转换成字符型(如CHAR和VARCHAR2),但是只允许32KB;

使用LONG或LONG RAW不能声明变量; 在LONG或LONG RAW列中不能用:NEW 和 :PARENT; LOB中的:NEW变量不能修改,例如:

:NEW.Column := ...

4. 引用包变量的限制:如果UPDATE 或 DELETE语句测到与当前的 UPADTE冲突,则 Oracle 执行 ROLLBACK到 SAVEPOINT上并重新启动更新。这样可以要出现多次才能成功。

79

Page 80: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§18.5 变异表关于变异表的详细资料见《Oracle8I Application developer’s Guide》12 Using triggers

变异表( mutating table ) 是被 DML语句正在进行 UPDATE, DELETE 或 INSERT的表。对于触发器而言该表是定义触发器的表。 另一种情况是在定义表时使用 DELETE CASCADE 参考完整性限制的也是变异表。对于变异表来说,Oracle对它的访问有限制,见下表:

图: 变异表( mutating 图)

例如:考虑下面例子:CREATE OR REPLACE TRIGGER Emp_countAFTER DELETE ON Emp_tabFOR EACH ROWDECLAREn INTEGER;BEGINSELECT COUNT(*) INTO n FROM Emp_tab;DBMS_OUTPUT.PUT_LINE(’ There are now ’ || n ||’ employees.’);END;

原始 EMP 表

80

Emp 表ENAME SALSIMTH 1000JOHN 1100WARD 1120

Emp 表ENAME SALSIMTH 1000JOHN 1100WARD 1120

行触发下面语句update emp set sal=sal*1.1;

由于是变异表而不能修改

After行触发引起的限制

Select salFrom empWhere …

Page 81: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

当我们输入下面语句时,会出现错误:DELETE FROM Emp_tab WHERE Empno = 7499;

ORA-04091: table SCOTT.Emp_tab is mutating, trigger/function may not see it

如:-- 节选自在线代码 tables.sqlCREATE TABLE registered_students ( Student_id number(5) not null, Department char(3) not null, Course number(3) not null, Grande char(1), CONSTRAINT rs_grande Check ( grande IN ( ‘A’,’B’,’C’,’E’ )), CONSTRAINT rs_student_id FOREIGN KEY ( student_id ) REFERENCES students ( id ), CONSTRAINT rs_department_course FOREIGN KEY ( department,course ) REFERENCES classes ( department, course ));

此表 Registered_students 有两个参考完整性限制,students,classes都是 Registered_students 的限制表。在对 Registered_students 执行 DML 语句的时侯,Registered_students本身也是变化的。由于这些限制的影响,students,classes也都需被 DML 语句改变或查询。 对于这类表,触发器主体中 SQL 语句不允许进行:。读取或修改触发语句的任何变异表。。读取或修改触发表的限制表的主键,唯一值列或外键列。对于上述的限制,可以用行级触发器来进行触发,如果在 INSERT语句中只影响一行的话,则触发器不把它当变异表对待。但是对于象 Insert into xxx 。。。 select xxx这样的语句。无论其返回是否是多行都当变异表对待。总之,变异表是那些具有主系关系的表,对于这样的表,在 Oracle触发器里进行 DML操作会受到限制。

81

Page 82: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§18.5.1 变异表典型例子

下面给出两个例子来说明触发器对变异表的影响。例 1:可以被执行的触发器,下面触发器 cascadeRSinserts虽对 stdents 表和 classes 表进行修改。但是由于该触发器不修改关键字列,所以可以正常被执行:CREATE OR REPLACE TRIGGER cascadeRSinsertsBEFORE INSERT On registered_students FOR EACH ROWDECLAREV_credits classes.num_credits%TYPE;BEGINSELECT num_credits FROM classes WHERE department =:new.departmentAND course =:new.course;

-- 可以修改 stduents 表UPDATE students SET current_credits=current_credits+v_creditsWHERE ID =:new.student_id;

-- 可以修改 classes 表,将学生总数加 1UPDATE classes SET current-stduents = current_students + 1WHERE deptment = :new.department AND course =:new.course;

END cascadeRSinserts;

例 2:下面的触发器不能被执行 CREATE OR REPLACE TRIGGER limitMajorsBEFORE INSERT OR UPDATE OF major On students FOR EACH ROWDECLARE

V_maxstudents CONSTANT NUMBER := 5;V_CurrentStudents NUMBER;BEGINSELECT COUNT(*) INTO v_CurrentStudents FROM studentsWHERE major = :new.major;IF v_CurrentStudents + 1 > V_maxStudents THENRAISE_APPLICATION_ERROR(-20000,’Too mant students in major ‘||:new.major );END IF;END limitMajors;

82

Page 83: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

当我们对 students 表进行UPDATE时,就触发了上面的触发器,但是它的执行出现错误:SQL>Update students set major=’History’ where id=10003;UPDATE students*ERROR at line 1:ORA-04091:table EXAMPLE.STUDENTS is mutating,trigger/function May not see it

由于触发器 limitMajors 查询自己的表就是变异表。所以在执行 limitMajors 触发器时出现 ORA-04091 错误。

§18.5.2 变异表错误的处理

在上例中,由于用了行级触发(FOR EACH ROW )而使 students 变成了变异表,从而导致不能对 students 表进行查询。但是可以将上面 limitMajors 触发器中 FOR EACH ROW 去掉使它变为语句级触发器。再对触发器中用到的 :new.major 值进行修改,变为两个触发器,一个是行级触发器,另一个是语句级触发器。另外还要建立一个包来存放 :new.major 值。从而可以被执行。CREATE OR REPLACE PACKAGE Studentdata ASTYPE t_Majors IS TABLE OF students.major%TYPEINDEX BY BINARY_INTEGER;TYPE t_IDS IS TABLE OF students.ID%TYPEINDEX BY BINARY_INTEGER;

V_studentsmajors t_majors;V_studentsIDs t_Ids;V_numEntries BINARY_INTEGER :=0;END Studentdata;

CREATE OR REPLACE TRIGGER RlimitMajorsBEFORE INSERT OR UPDATE OF major ON students FOR EACH ROWBEGINStudentdata.v_numEntries := studentsdata.v_numEntries + 1;Studentdata.v-studentMajors(studentdata.v_numEntries) := :new.major;Studentdata.v_studentIDs (studentdata.v_numEntries) := :new.id;END RlimitMajors;

CREATE OR REPLACE TRIGGER SlimitMajors

83

Page 84: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

BEFORE INSERT OR UPDATE OF major ON studentsBEGINv_MaxStudents CONSTANT NUMBER := 5;v_CurrentStudents NUMBER;

v_studentID students.ID%TYPE;v_Major student.major%TYPE;

BEGINFOR v_loopindex IN 1 .. studentdata.V_numEntries loop v_studentID := studentdata.v_stidentIDs(v_loopindex);v_major := studentdata.v_studentmajors(v_loopindex);

SELECT count(*) INTO v_currentstudents FROM studentsWHERE major = v_major;

IF v_currentstudents > v_maxstudents THENRAISE_APPLICATION_ERROR(-20000,’Too many students for major ‘||v_major||‘because of student ‘|| v_studentID);END IF;END LOOP;

END SlimitMajors;

§18.6 触发器数据字典与管理当我们根据应用的特殊要求而不得不编写触发器来完成一定的操作时,触发器的源代码

就已经存放在实例的数据字典中,我们了解数据字典的目的主要是管理触发器,比如使触发器有效或无效或删除触发器或导出触发器源代码等。

§18.6.1 触发器数据字典与触发器有关的数据字典有:user_triggersall_triggersdba_triggers作为DBA, 只要了解DBA_TRIGGERS就可以了。下面是DBA_TRIGGERS的列说明:

84

Page 85: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

列名 数据类型 是否空 说明Owner Varchar2(30) Not null 触发器的主人Trigger_Name Varchar2(30) Not null 触发器名称Trigger_Type Varchar2(16) 触发器类型,可以是:

Before each row, After each rowBefore statement, After statement

Triggering_event Varchar2(26) Not null 语句,可以是 INSERT,UPDATE,DELETETable_owner Varchar2(30) Not null 表的主人Table_name Varchar2(30) Not null 表名Referencing_name

Varchar2(87) 引用名,可以是OLD 或 NEW

When_clause Varchar2(4000) When 条件status Varchar2(8) 如果是DISABLE,则不触发Description Varchar2(4000) 触发器描述Trigger_body long 当触发时要进行的动作

§18.6.2 无效触发器的编译触发器与存储过程一样,也存在无效的情况。DBA要及时发现无效触发器并对它们进行编译。下面是对数据库内无效触发器的编译自动产生命令脚本的方法。1.产生编译触发器的脚本:SPOOL c:\comp_trig.sql

SELECT 'SET FEEDBACK ON' FROM DUAL;

SELECT 'PROMPT Compile TRIGGER ' || OBJECT_NAME || ' ...' || CHR(10) || 'ALTER TRIGGER ' || OBJECT_NAME || ' COMPILE;' || CHR(10) || 'SHOW ERRORS;' || CHR(10) || 'PROMPT;' FROM USER_OBJECTS WHERE STATUS <> 'VALID' AND OBJECT_TYPE = 'TRIGGER' ORDER BY OBJECT_NAME;

2.运行脚本 comp_trig.sql实现对无效触发器的编译:START c:\comp_trig.sql

85

Page 86: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

86

Page 87: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第十九章 外部存储过程

我们知道,Oracle的 PL/SQL只是一种简单的专用语言,它的特长在于与数据库进行数据处理和交换方面。在要求苛刻的应用里,还得要与其它的语言配合起来用才能完成用户的复杂要求。如科学计算,网上主页的设计等都需要专门的语言来完成。为此,Oracle专门在与其它高级语言和开发工具方面进行一些接口工作。到目前为止,除了可以在Oracle的开发工具中嵌入 PL/SQL语言和在 C/C++和 Java语言上嵌入 PL/SQL程序块外,可以在 PL/SQL中调用由 C 或 JAVA写的程序。

§19.1 什么是外部例程外部例程(external procedure)是用 C语言或 Java语言写成的过程,这些程序可以被 PL/SQL来调用。在最新的版本里,Oracle8i 提供了一种叫 Java虚拟机的部件,它是作为Orcle8I 的一部分的Oracle JServer 允许我们创建 Java过程,并将它们直接存储到数据库中。外部例程有下面一些特点: C外部例程必须放在共享库中。Extproc进程在调用该库的过程时动态地将库进行加载。在NT平台上的外部例程被编译成一个DLL库。UNIX 操作,如 Solaris 操作系统也把外部例程编译成共享库.SO。 Java 外部例程要用 Java工具或 Create OR Replace Java 语句将外部例程加到数据库中。 调用 C 外部例程的每个会话都是由一个 SQL*NET 监听器生成的 extproc进程(NT叫

thread)。在MTS下,extproc进程是由共享服务器进程生成的,其生存期与使用该共享服务器的所有会话相同。调用 Java外部例程不会生成 extproc进程。

监听器和 extproc进程都必须驻留在数据库所在的主机上。 外部例程也可以回调数据库来执行其它的 SQL语句或 PL/SQL 块。C语言的回调是通过

Oracle8的OCI 或 PRO*C来实现的。而 Java 的回调是通过 JDBC 或 SQLJ来实现。 一个给定的会话在处理过程中既可以调用 C的外部例程,也可以调用 java 外部例程. 由于 JSP是按照模式对象加载的,所以访问 Java的存储子程序的授权要通过数据库来实现。

Oracle8I 可以无须通过包装而直接调用 JSP。该包对于编译来说是必不可少的。

87

Page 88: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§19.2 C外部例程Oracle系统在很早的版本就已经支持了 C语言和 PL/SQL语言的联合开发环境。也就是说可以在 C/C++中嵌入 PL/SQL 块。但到 Oracle8后,才允许将 C 或 java写成程序,在建立数据库中,允许 PL/SQL程序来调用它们。下面简要给出 C语言外部例程的编程介绍。

88

Page 89: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§19.2.1 调用步骤为了完成外部例程的调用,必须进行下面步骤:1)用 C语言编制外部例程,并将该程序进行编译在共享库中;2)配置NET8参数文件和启动监听器进程;3)创建库数据字典对象来代表操作系统库;4)通过创建一个把 PL/SQL参数影射到 C参数的 PL/SQL包,用来发布外部例程。1.建立C 过程编码比如我们要建立的代码如下:#include <stdio.h>void OutputString(path,message)char* path;char * message;{FILE * file_handle;File_handle = fopen(path,”w”);Fprint(file_handle,”%s\n”,message);Fclose(file_handle);}

比如我们将文件存为 outstr.c 。接下来就是将代码编译成为一个共享库。比如在 Solaris 操作系统中,可以用下面命令来完成:cc –G –o /home/utils/stringlib.so outstr.c

2.配置NET8监听器配置监听器需要对 listener.ora和 tnsnames.ora 文件进行编辑。下面给出二文件的配置文本:1) listener.ora文件EXTPROC_LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = # Local connections. (ADDRESS_LIST =

89

Page 90: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

(ADDRESS = (PROTOCOL = IPC)(KEY = icache)) ) )

SID_LIST_EXTPROC_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = s450 ) (ORACLE_HOME = /home1/ias/app/oracle/product/1.0.2) (SID_NAME = s450 ) ) (SID_DESC = (ORACLE_HOME = /home1/ias/app/oracle/product/1.0.2) (SID_NAME = iCache_extproc) (PROGRAM = extproc) ) )

2) tnsnames.ora文件# TNSNAMES.ORA Network Configuration File: # /home/ias/app/oracle/product/1.0.2/network/admin/tnsnames.ora# Generated by Oracle configuration tools.

DBSVR-ICACHE = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = icache)) ) (CONNECT_DATA = (SID = icache) ) )

ORA_ICACHE = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = icache)) ) (CONNECT_DATA = (SID = icache)

90

Page 91: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

) )

ORA_ICACHE_ORIGIN = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = <originHostName>)(PORT = <originPortNumber>)) ) (CONNECT_DATA = (SERVICE_NAME = <originServiceName>) ) )

# Internal mame for local Oracle8i Cache.

INST1_HTTP = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = dbsvr)(PORT = 1521)) ) (CONNECT_DATA = (SERVER = shared) (SERVICE_NAME = MODOSE) (PRESENTATION = http://admin) ) )

# Support for mod_ose over normal TCP connections.# Oracle8i Cache's origin database.# Support for external procedures within Oracle8i cache.# Descriptive name to connect to cache via OEM performance monitor.

EXTPROC_CONNECTION_DATA = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = ipc)(KEY = icache)) ) (CONNECT_DATA = (SID = iCache_extproc) (SERVER = DEDICATED) ) )

91

Page 92: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

S450 = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.3)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = s450) ) )

3.创建库库就是存储在操作系统目录下的库,它必须在Oracle数据字典中登记。由于共享库位于数据库的外部,因此 PL/SQL需要数据库使用某些符号来代表该库。现在我们用:CREATE LIBRARY library_name ( IS | AS )‘operating_system_path’ ;

命令来创建库。其中:library_name是要创建的库名字; operating_system_path 是共享库在文件系统中的完整路径。例如:CREATE LIBRARY Stringlib AS ‘/home/utils/stringlib.so’ ;

同样,我们可以用下面命令将库从数据字典中删除:DROP LIBRARY library_name;

4.发布外部例程为了使 PL/SQL能调用外部例程,必须对其进行发布。发布是通过创建包来实现的。建立包有几个作用:1)首先,把 PL/SQL参数隐射为 C类型;2)是位置标识来确认调用过程相关参数;3)包负责通知 PL/SQL外部库的名称。包是由 子程序、使用的参数及跟在后面的 AS EXTERAL(Oracle8 要求 ) 或 AS LANGUAGE(Oracle8I要求)组成。包可以是独立的过程或函数。下面是语法:Oracle8 建立包的语法:CREATE OR REPLACE { PROCEDURE |FUNCTION } procedure_name [parameter_list]

92

Page 93: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

AS EXTERNAL LIBRARY library_name[NAME external_name][LANGUAGE C][CALLING STANDARD { C | PASCAL} ][WITH CONTEXT ][PARAMETERS (external-parameter_list) ] ;

Oracle8i 建立包的语法:CREATE OR REPLACE { PROCEDURE |FUNCTION } procedure_name [parameter_list]AS LANGUAGE CLIBRARY library_name[NAME external_name][CALLING STANDARD { C | PASCAL} ][WITH CONTEXT ][PARAMETERS (external-parameter_list) ] ;

其中:LIBRARY 必须的子句。用于说明共享库名。NAME 用于说明 C过程的名称。如果没有NAME子句,则缺省为 PL/SQL。名称在数据库里都是以大写字母进行存放,如果 C用大小写混合命名,则要双引号括起。LANGUAGE 与 AS EXTERNAL 共同使用。用来说明外部例程使用的语言,如果不使用该语句,缺省为 C语言。CALLING STANDARD 调用标准可以是 C 或 Pascal 。缺省为 C语言。WITH CONTEXT 在外部例程回调数据库时使用。该子句将给 C过程增加一个参数,以便 C过程可以得到必要的OCI句柄。PARAMETERS 参数子句说明了 PL/SQL参数映射到外部例程 C语言参数的方式。如果没有说明映射方式,则数据库使用缺省的映射方式。例:CREATE OR REPLACE PROCEDURE outputstring(P_path IN VARCHAR2,P_Message IN VARCHAR2 ) AS EXTERNALLIBRARY StringLibNAME “outputstring”PARAMETERS ( p_path STRING, P_Message STRING);

93

Page 94: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

5.使用外部例程当创建完包后,就可以从 PL/SQL 块中调用OutputString了。下面例子在/tmp目录下建立一个文件叫 output.txt,该文件内包含一行字符:“Hello World!”。选自在线代码:callOS.sql

SQL>BEGINOutputString(‘/tmp/output.txt’,’Hello World!’ );End;

PL/SQL procedure sucessfully completed.

SQL>exit

$cat /tmp/output.txt

Hello World!

§19.2.2 参数映射( 转换)

对于两种不同的语言来说,通信的主要问题之一是数据类型的转换。在外部例程调用来说,要解决包中参数的 PL/SQL数据类型如何映射到参数 C语言的数据类型的问题。此外还需要注意: 在 PL/SQL中,任何变量可以是空的(即 null),而 C语言没有空的概念,必须使用

indicator的变量来传递参数是否为空的信息。 PL/SQL包括了 C语言中没有的数据类型,同样,C语言也包括了 PL/SQL没有的数据类

型。如 C语言中没有DATE,BOOLEAN类型,同样 PL/SQL对 2个、4个字节的整数不加区分。

PL/SQL接纳不同字符集的字符变量,因此,这些字符集要通知 C语言。 C语言要求从确认从 PL/SQL 传递过来的字符串当前值或最大长度。创建过程或函数中的 PARAMETERS 就是用来解决参数映射问题的特别参数。PRAMETERS(external_parameter_list);

94

Page 95: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

external_parameter_list 是一个参数表,它可以是多个项,而每一项的结构可以是:{ parameter_name | SELF | RETURN } property[BY REFERENCE | VALUE ] [ external_datatype ]

其中:parameter_name 是参数名,external_datatype 是赋予该参数的 C语言数据类型,property 可以是 INDICATOR、LENGTH、MAXLEN、CHARSETID、CHARSETFORM 之一。1.PL/SQL与C语言数据类型比较由于 PL/SQL和 C语言没有相同的数据类型,因而 Oracle8专门为每一种 PL/SQL数据类型提供对应的默认数据类型。我们可以在需要时加载它们。比如外部数据类型为CHAR对应 C数据类型是 char;外部数据类型 UNSIGNED CHAR对应 C语言数据类型是Unsigned char等。在编写外部例程时,建议程序人员一定要注意它们之间的差别。

2.使用 PARAMETERS子句使用 PARAMETERS就是在建立过程或函数时带 PARAMETERS参数说明。比如前面的例子就是简单使用的样例:C函数定义为:#include <stdio.h>void OutputString(path,message)char* path;char * message;{. . . . . .

PL/SQL 过程的 PARAMETERS说明为:CREATE OR REPLACE PROCEDURE outputstring(P_path IN VARCHAR2,P_Message IN VARCHAR2 ) AS EXTERNALLIBRARY StringLibNAME “outputstring”PARAMETERS ( p_path STRING, P_Message STRING);

95

Page 96: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第二十章 会话间通信

PL/SQL 提供了两个内装包 DBMS_PIPE 和 DBMS_ALTER用于连接到同一台机器的数据库的会话间发送消息。

§20.1 DBMS_PIPE

DBMS_PIPE包实现在 oracle 数据库内的“数据库管道(database pipe)”。即连接到相同的oracle 实例上的不同会话可以通过管道发送和接收消息。 管道是以异步(asynchronous)的方式进行工作的,一旦一个消息发出去就不能再检索到该信息了。 管道可以有多个读者(reader-接收消息的人)和一个写者(writer-发送消息的人).管道的处理顺序是:1)写者将一系列数据用DBMS_PIPE.PACK_MESSAGE打包;2)写者用DBMS_PIPE.SEND_MESSAGE将打包的数据送到消息缓冲区;3)读者用DBMS_PIPE.RECEIVE_MESSAGE将消息接收下来;4)读者用DBMS_PIPE.UNPACK_MESSAGE将消息解包。

§20.1.1 发送消息

发送消息需两个步骤:1)数据打包;2)经管道发送出去。1.打包 PACK_MESSAGE

可以对不同类型的数据打包,定义如下:

96

Page 97: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

PROCEDURE PACK_MESSAGE ( item IN VARCHAR2);PROCEDURE PACK_MESSAGE ( item IN NUMBER);PROCEDURE PACK_MESSAGE ( item IN DATE);PROCEDURE PACK_MESSAGE_RAW ( item IN RAW);PROCEDURE PACK_MESSAGE_ROWID ( item IN ROWID);

由于缓冲区大小为 4096 字节,因而被打包的数据不能超过该大小,否则得到 ORA-06558 错误提示。1. SEND_MESSAGE

当调用一次或多次 PACK_MESSAGE过程将本地消息缓冲区填充了数据后,就可用SEND_MESSAGE过程将该缓冲区的内容通过管道发送出去:

FUNCTION SEND_MESSAGE ( pipename IN VARCHAR2, Timeout IN INTEGER DEFAULT MAXWAIT, Maxpipesize IN INTEGER DEFAULT 8192) RETURN INTEGER;

§20.1.2 接收消息

DBMS_PIPE 提 供 三 个 过 程 用 于 接 收 管 道 消 息 , 它 们 是 :RECEIVE_MESSAGE,NEXT_ITEM_TYPE, UNPACK_MESSAGE。1. RECEIVE_MESSAGE

从管道中接收消息并放在本地缓冲区中,然后再用 UNPACK_MESSAGE从该缓冲区检索出消息。RECEIVE_MESSAGE 定义为:FUNCTION RECEIVE_MESSAGE ( pipename IN VARCHAR2, Timeout IN DEFAULT MAXWAIT ) RETURN INTEGER;

Timeout 等待消息的最大时间(秒),缺省为 86400000秒(1000天),如果 Timeout=0,则 RECEIVE_MESSAGE立即返回。返回值

0 成功

97

Page 98: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

1 超时,即在等待的时间内还没有消息发过来。2 在管道中的消息太长。3 内部错误。

2. NEXT_ITEM_TYPE

NEXT_ITEM_TYPE 返回缓冲区中下一项数据的类型,用以确定用哪个类型的变量接收数据。NEXT_ITEM_TYPE 定义如下:FUNCTION NEXT_ITEM_TYPE RETURN INTEGER;

返回值0 没有其它项6 NUMBER9 VARCHAR211 ROWID12 DATE23 RAW

3. UNPACK_MESSAGE

UNPACK_MESSAGE从该缓冲区检索出消息。

§20.1.3 示例例 1. 发送消息的 PL/SQL 程序REM 选自 logRSins.sqlREM 作者: Scott Urman.REM 中文注释:赵元杰.

CREATE OR REPLACE TRIGGER LogRSInserts BEFORE INSERT ON registered_students FOR EACH ROWDECLARE v_Status INTEGER;BEGIN

98

Page 99: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

/* 先 将包存放在缓冲区. */ DBMS_PIPE.PACK_MESSAGE('I');

/* 打包当前用户和邮戳 */ DBMS_PIPE.PACK_MESSAGE(user); DBMS_PIPE.PACK_MESSAGE(sysdate);

/* 打包新的值. */ DBMS_PIPE.PACK_MESSAGE(:new.student_ID); DBMS_PIPE.PACK_MESSAGE(:new.department); DBMS_PIPE.PACK_MESSAGE(:new.course); DBMS_PIPE.PACK_MESSAGE(:new.grade);

/* 送信息到 'RSInserts' 管道. */ v_Status := DBMS_PIPE.SEND_MESSAGE('RSInserts');

/* 如果发送不成功,则触发错误处理 */

IF v_Status != 0 THEN RAISE_APPLICATION_ERROR(-20010, 'LogRSInserts trigger ' || 'couldn''t send the message, status = ' || v_Status); END IF; END LogRSInserts;/

--接收消息的 pro*c 程序/* 选自RSinsert.pc程序接收 RSInserts 管道的信息。然后将信息记录到文件中。*/

/* C 和 SQL 头文件 */#include <stdio.h>EXEC SQL INCLUDE sqlca;

EXEC SQL BEGIN DECLARE SECTION; /* 连接到数据库的用户名和口令 */ char *v_Connect = "example/example";

/* 声明状态变量 DBMS_PIPE */ int v_Status; VARCHAR v_Code[5];

99

Page 100: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

/* 送信息到管道的变量. */ VARCHAR v_Userid[9]; VARCHAR v_Changedate[10]; int v_StudentID; VARCHAR v_Department[4]; int v_Course; VARCHAR v_Grade[2]; short v_Grade_ind;EXEC SQL END DECLARE SECTION;

/* 日志文件的指针 */FILE *outfile;

void sqlerror();

int main() {

/* 设置错误处理 */ EXEC SQL WHENEVER SQLERROR DO sqlerror();

/* 连接数据库 */ EXEC SQL CONNECT :v_Connect;

/* 打开日志文件光标. */ outfile = fopen("rs.log", "w");

/* 主循环,当遇到错误时停止. */ for (;;) {

/* 休眠直到信息被收到为止,如果没有指定超时的时间,则用缺省值 */

EXEC SQL EXECUTE BEGIN :v_Status := DBMS_PIPE.RECEIVE_MESSAGE('RSInserts'); END; END-EXEC;

if (v_Status == 0) { /* 成功收到信息,则先得到第 1个数据元素。 */

v_Code.len = 5; EXEC SQL EXECUTE BEGIN DBMS_PIPE.UNPACK_MESSAGE(:v_Code); END;

100

Page 101: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END-EXEC; v_Code.arr[v_Code.len] = '\0';

if (!strcmp(v_Code.arr, "STOP")) { /* 停止接收,退出循环 */ break; }

/* 收到其余的信息,包括用户标识、日期及 新值 */

v_Userid.len = 9; v_Changedate.len = 10; v_Department.len = 4; v_Grade.len = 2; EXEC SQL EXECUTE DECLARE v_ChangeDate DATE; BEGIN DBMS_PIPE.UNPACK_MESSAGE(:v_Userid); DBMS_PIPE.UNPACK_MESSAGE(v_ChangeDate); :v_Changedate := TO_CHAR(v_ChangeDate, 'DD-MON-YY'); DBMS_PIPE.UNPACK_MESSAGE(:v_StudentID); DBMS_PIPE.UNPACK_MESSAGE(:v_Department); DBMS_PIPE.UNPACK_MESSAGE(:v_Course); DBMS_PIPE.UNPACK_MESSAGE(:v_Grade:v_Grade_ind); END; END-EXEC;

/* 空字符串 */ v_Userid.arr[v_Userid.len] = '\0'; v_Changedate.arr[v_Changedate.len] = '\0'; v_Department.arr[v_Department.len] = '\0';

if (v_Grade_ind == -1) v_Grade.arr[0] = '\0'; else v_Grade.arr[v_Grade.len] = '\0';

/* 打印日志文件日期. */ fprintf(outfile, "User: %s Timestamp: %s", v_Userid.arr, v_Changedate.arr); fprintf(outfile, " ID: %d Course: %s %d Grade: %s\n", v_StudentID, v_Department.arr, v_Course, v_Grade.arr);

101

Page 102: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

} else if (v_Status == 1) { /* RECEIVE_MESSAGE 调用超时. 回到循环再等待. */ continue; } else { /* RECEIVE_MESSAGE 调用出错误. 打印和退出 */

printf("RECEIVE_MESSAGE Error! Status = %d\n", v_Status); EXEC SQL ROLLBACK WORK RELEASE; exit(1); }

} /* 主循环结束 */ /* 关闭文件 */ fclose(outfile);

/* 断开数据库连接. */ EXEC SQL COMMIT WORK RELEASE;}

/* 错误处理函数. 在屏幕显示错误信息和退出 */

void sqlerror() {

printf("SQL Error!\n"); printf("%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);

EXEC SQL WHENEVER SQLERROR CONTINUE;

EXEC SQL ROLLBACK RELEASE;}

例 2:/* Available online as debug.pc */#include <stido.h>EXEC SQL INCLUDE sqlca;EXEC SQL BEGIN DECLARE SECTION; Char *v_connect = “example/example” Int v_status;. . . . . .

102

Page 103: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

REM 选自 debug.sqlREM 作者: Scott Urman.REM 中文注释:赵元杰.

CREATE OR REPLACE PACKAGE Debug AS -- 等待的最大秒数 v_TimeOut NUMBER := 10;

-- 主Debug 过程. PROCEDURE Debug(p_Description IN VARCHAR2, p_Value INVARCHAR2);

-- 设置Debug 环境 PROCEDURE Reset;

-- 引起后台程序退出. PROCEDURE Exit;END Debug;/

CREATE OR REPLACE PACKAGE BODY Debug as

v_CurrentPipeName VARCHAR2(30);

PROCEDURE Debug(p_Description IN VARCHAR2, p_Value INVARCHAR2) IS v_ReturnCode NUMBER; v_Handshake VARCHAR2(10); BEGIN /* 如果管道还没有,则说明它. */ IF v_CurrentPipeName IS NULL THEN v_CurrentPipeName := DBMS_PIPE.UNIQUE_SESSION_NAME; END IF;

/* 发送 'DEBUG' 信息和: - 握手信息名 - 描述 - 值 */ DBMS_PIPE.PACK_MESSAGE('DEBUG'); DBMS_PIPE.PACK_MESSAGE(v_CurrentPipeName); DBMS_PIPE.PACK_MESSAGE(p_Description);

103

Page 104: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_PIPE.PACK_MESSAGE(p_Value); v_ReturnCode := DBMS_PIPE.SEND_MESSAGE('DebugPipe');

IF v_ReturnCode != 0 THEN RAISE_APPLICATION_ERROR(-20210, 'Debug.Debug: SEND_MESSAGE failed with ' || v_ReturnCode); END IF;

/* 等待在管道上返回握手信息 */ v_ReturnCode := DBMS_PIPE.RECEIVE_MESSAGE(v_CurrentPipeName);

IF v_ReturnCode = 1 THEN -- 超时 RAISE_APPLICATION_ERROR(-20211, 'Debug.Debug: No handshake message received'); ELSIF v_ReturnCode != 0 THEN -- 其它错误 RAISE_APPLICATION_ERROR(-20212, 'Debug.Debug: RECEIVE_MESSAGE failed with ' || v_ReturnCode); ELSE -- 检查握手信息. DBMS_PIPE.UNPACK_MESSAGE(v_Handshake); IF v_Handshake = 'Processed' THEN -- Output processed. NULL; ELSE -- 非握手信息 RAISE_APPLICATION_ERROR(-20213, 'Debug.Debug: Incorrect handshake message received'); END IF; END IF; END Debug;

PROCEDURE Reset IS/* 检查后台程序在运行。否则触发错误 */

v_ReturnCode NUMBER; BEGIN DBMS_PIPE.PACK_MESSAGE('TEST'); v_ReturnCode := DBMS_PIPE.SEND_MESSAGE('DebugPipe');

IF v_ReturnCode != 0 THEN RAISE_APPLICATION_ERROR(-20200, 'Debug.Reset: SEND_MESSAGE failed with ' || v_ReturnCode);

104

Page 105: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END IF;

/* 后台程序在相同管道上回答,即超时。 因此后台程序未准备好并触发错误 */ v_ReturnCode := DBMS_PIPE.RECEIVE_MESSAGE('DebugPipe', v_TimeOut); IF v_ReturnCode = 1 THEN -- 超时 RAISE_APPLICATION_ERROR(-20201, 'Debug.Reset: Daemon not ready'); ELSIF v_ReturnCode != 0 THEN -- 其它错误 RAISE_APPLICATION_ERROR(-20202, 'Debug.Reset: RECEIVE_MESSAGE failed with ' || v_ReturnCode); ELSE -- 后台程序准备好. NULL; END IF; END Reset;

PROCEDURE Exit IS v_ReturnCode NUMBER; BEGIN -- 发送 'STOP' 信息. DBMS_PIPE.PACK_MESSAGE('STOP'); v_ReturnCode := DBMS_PIPE.SEND_MESSAGE('DebugPipe');

IF v_ReturnCode != 0 THEN RAISE_APPLICATION_ERROR(-20230, 'Debug.Exit: SEND_MESSAGE failed with ' || v_ReturnCode); END IF; END Exit;

END Debug;/

例 3.校园网计费系统的实例,当用户从WEB 上修该其口令时,通过管道传给 C 语言程序,C语言程序完成 PROXY,E_MAIL服务器的口令修改等。 ( 因为 PL/SQL 编写的程序不支持直接写 NETSCAPE 中目录服务器操作)

1)存储过程如下: procedure cust_chgpasswd(name1 in varchar2, passwd1 in varchar2,

105

Page 106: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

passwd2 in varchar2,iaction in varchar2) is result number(2) := 0; ldap_hostip1 varchar2(30); /* D?B<server host IP */ ldap_port1 varchar(6); /* Directory Port */ ldap_pwd1 varchar2(30); /* such as: 1234567890 */ ldap_str1 varchar2(30); /* o=Airius.com,uid=zxj */ mailhost2 varchar2(50); /* Mail server host IP */

begin begin select ldap_hostip, ldap_port, ldap_pwd, ldap_str, mailhost into ldap_hostip1,ldap_port1,ldap_pwd1,ldap_str1,mailhost2 from acctsys_ldap where rownum=1; exception when no_data_found then ldap_hostip1 := '210.42.96.48'; ldap_port1 := '389'; ldap_pwd1 := '1234567890'; ldap_str1 := 'o=Airius.com'; mailhost2 := 'whuci.edu.cn'; end;

if iaction = '确 认' then if passwd1=passwd2 then result := acctsysd.execute_system('pipe_mod_ldap_user '|| name1 ||' '|| passwd1 ); if result = 0 then htp.p(blink(' 用 户 : ' || name1 || ' 密码修改成功!') );

else htp.p(blink(' 用 户 : ' || name1 || ' 密码修改失败, 口令不变 !') ); end if; else htp.p(blink(' 用 户 : ' || name1 || ' 密码修改失败 (口令不变)!') ); end if; /* passwd1=passwd2 */ end if; acctsys.custom; end;

. . . . . .

106

Page 107: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

2)由存储过程调用的 包 的源代码如下:/* 文 件 名: ACCTSYSD.SQL */ /* 作者:赵西建 1998.11. *//* 修改:赵元杰 1999.12.01 */

CREATE OR REPLACE PACKAGE acctsysd ASFUNCTION execute_sql(command in VARCHAR2,

timeout in NUMBER DEFAULT 6000)RETURN NUMBER;

FUNCTION execute_system(command in VARCHAR2, timeout in NUMBER DEFAULT 6000) RETURN NUMBER;

PROCEDURE stop(timeout in NUMBER DEFAULT 6000);END;/

CREATE OR REPLACE PACKAGE BODY acctsysd ASFUNCTION execute_system(command in VARCHAR2,

timeout in NUMBER DEFAULT 6000) RETURN NUMBER IS

status NUMBER;result VARCHAR2(20);command_codeNUMBER;pipe_name varchar(30);

BEGIN

pipe_name := DBMS_PIPE.UNIQUE_SESSION_NAME;

DBMS_PIPE.PACK_MESSAGE('SYSTEM'); DBMS_PIPE.PACK_MESSAGE(pipe_name); DBMS_PIPE.PACK_MESSAGE(command); /* insert into tst values(' send command='||command, to_char(sysdate,'yyyy.mm.dd hh24:mi:ss')); */ status := DBMS_PIPE.SEND_MESSAGE('acctsysd', timeout);

IF status <> 0 THEN

107

Page 108: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

RAISE_APPLICATION_ERROR(-20010, '执行 EXECUTE SYSTEM 出错! ' ||to_char(status));

END IF;

status := DBMS_PIPE.RECEIVE_MESSAGE(pipe_name, timeout); /*insert into tst values('reveive pipe_name ='||pipe_name ,

to_char(sysdate,'yyyy.mm.dd hh24:mi:ss')); */

IF status <> 0 THEN RAISE_APPLICATION_ERROR(-20011, '执行 EXECUTE SYSTEM 出错! ' || to_char(status)); END IF;

DBMS_PIPE.UNPACK_MESSAGE(result);

IF result <> 'done' THENRAISE_APPLICATION_ERROR(-20012,

'Execute_system: done not received.'); END IF; DBMS_PIPE.UNPACK_MESSAGE(command_code);

RETURN command_code;

END ; /* execute_system */

/************************************************************************/

FUNCTION execute_sql(command in VARCHAR2, timeout in NUMBER DEFAULT 10)

RETURN NUMBER IS status NUMBER; result VARCHAR2(20); command_code NUMBER; pipe_name VARCHAR2(30); BEGIN pipe_name := DBMS_PIPE.UNIQUE_SESSION_NAME; DBMS_PIPE.PACK_MESSAGE('SQL');

108

Page 109: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_PIPE.PACK_MESSAGE(pipe_name); DBMS_PIPE.PACK_MESSAGE(command);

status := DBMS_PIPE.SEND_MESSAGE('acctsysd', timeout); IF status <> 0 THEN RAISE_APPLICATION_ERROR(-20020, 'Execute_sql: Error while sending. Status = ' || to_char(status)); END IF;

status := DBMS_PIPE.RECEIVE_MESSAGE(pipe_name, timeout); IF status <> 0 THEN RAISE_APPLICATION_ERROR(-20021, 'Execute_sql: Error while reveiving. Status = ' || to_char(status)); END IF;

DBMS_PIPE.UNPACK_MESSAGE(result); IF result <> 'done' THEN RAISE_APPLICATION_ERROR(-20022, 'Execute_sql: done not received.'); END IF;

DBMS_PIPE.UNPACK_MESSAGE(command_code); DBMS_OUTPUT.PUT_LINE('SQL command execute. result = ' || to_char(command_code)); RETURN command_code; END; /* execute_sql;*/

PROCEDURE stop(timeout in NUMBER DEFAULT 10) ISstatus NUMBER;

BEGINDBMS_PIPE.PACK_MESSAGE('STOP');status := DBMS_PIPE.SEND_MESSAGE('acctsysd', timeout);

IF status <> 0 THEN RAISE_APPLICATION_ERROR(-20030, 'Stop: Error while sending. Status = ' || to_char(status)); END IF;

END ; /* stop;*/

END;/

109

Page 110: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

show errors;

/

/***************************************************************************//* 文 件 名: ACCTSYSD.PC for LDAP */ /* 功 能: 建立多种管道,如:增删用户(email & proxy),修改密码 *//* 创建文件,执行系统(unix)命令等。 *//* 编程语言:PRO* C *//* *//* 运行环境: ORACLE 7.3.X ( for SUN Solaris 2.5 ) *//* ORACLE 8.0.X ( for SUN Solaris 2.x ) *//* *//* 作 者: 赵西建 *//* 修 改: 赵元杰 *//* 修改日期: 2000.01.23 增加 add_ldap,chk_ldap,del_ldap *//* *//***************************************************************************/ #include <stdio.h>#include <pwd.h>#include <shadow.h>#include <ctype.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <sys/file.h>#include <sys/stat.h>#include <sys/types.h>

#include "examples.h"#include "ldap.h"#include "lber.h"#include "usermnt.h"

int setupwd();int chkpwd();int chkpwd_direct();int writeacl();int writePROXY();int AppendUser();

char *GetnSalt(char *AsciiPwd);

110

Page 111: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

int chk_ldap_user (char *username, char *passwd );

static void do_other_work();unsigned long global_counter = 0;static void free_mods( LDAPMod **mods );

#defineNMODS 12

#define PIPE_EXECUTESYS "pipe_executesys"#define PIPE_CHK_LDAP_USER "pipe_chk_ldap_user"#define PIPE_GETLDAPUSER "pipe_get_ldap_user"#define PIPE_ADDLDAPUSER "pipe_add_ldap_user"#define PIPE_MODLDAPUSER "pipe_mod_ldap_user"#define PIPE_DELLDAPUSER "pipe_del_ldap_user"

#define MAXLINESIZE 2048#define LINEFMT "%s %s %s %s %s"#define TEMPFMT "%s %s"#define GMTVARS internet,ip_no,age,mac_no,arap#define TMPVARS internet,temp

int get_ldap_user();int get_ldap_group();int setupwd_sup();

#define DEBUG_FLAG 1void DEBUG_PRINT(char *debugmsg) { if (DEBUG_FLAG) printf("提示: %s\n", debugmsg); }

/* 管道命令参数 */char internet[10], ip_no[15], age[15],mac_no[15],arap[15],temp[1024];char pwdfile[128], passwd[32], username[32], cuid[32];char cgid[32], pw_age[32];char usercomment[126], homedir[128], shell[64];int cmdflag, xgid, xuid;char cmdstr[32];

struct passwd userattr;

char ldap_hostip[30], ldap_port[10], ldap_pwd[30];char ldap_dn[30], ldap_str[30];

111

Page 112: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

char ldap_user[30], ldap_group[30], ldap_pass[30];char ldap_flag[4], PwdFile[256];

EXEC SQL INCLUDE SQLCA;EXEC SQL BEGIN DECLARE SECTION; char *uid = "coteam/armszxj"; int status , row_cnt, user_cnt; VARCHAR command[20]; VARCHAR value[2000]; VARCHAR return_name[30]; VARCHAR ORA_username[30]; VARCHAR ORA_password[32]; VARCHAR proxydir[30]; VARCHAR ORA_uname[30]; VARCHAR ORA_pwd[30]; VARCHAR ORA_aclfile[60]; VARCHAR ORA_run_comm[30]; VARCHAR ORA_router_ip[128]; VARCHAR ORA_acclst[128]; VARCHAR acce_fg[2]; VARCHAR ORA_ip[15],ORA_mac[15],ORA_age[8]; VARCHAR ORA_ldap_hostip[30]; VARCHAR ORA_ldap_port[10]; VARCHAR ORA_ldap_pwd[30]; VARCHAR ORA_ldap_str[30]; VARCHAR ORA_ldap_dn[30]; VARCHAR ORA_ldap_cn[30]; VARCHAR ORA_ldap_uid[30]; VARCHAR ORA_givename[30]; VARCHAR ORA_email[30]; VARCHAR ORA_mailhost[30]; VARCHAR ORA_altmail[30]; VARCHAR ORA_mailquota[10]; VARCHAR ORA_tel_no[30]; VARCHAR ORA_grp_name[30]; VARCHAR ORA_user_chn[30]; VARCHAR ORA_user_clrpwd[30]; varchar user_name[30]; EXEC SQL END DECLARE SECTION;

112

Page 113: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

void sql_error() { char msg_buffer[512]; int msg_length; int buffer_size = 512; EXEC SQL WHENEVER SQLERROR CONTINUE;

sqlglm(msg_buffer, &buffer_size, &msg_length); printf("执行 ORACLE 语句出错 ! \n"); printf("%.*s", msg_length, msg_buffer); printf("系统继续...\n"); }

main(){ char msg_buffer[512]; int msg_length; int buffer_size = 512;

EXEC SQL CONNECT :uid; if ( sqlca.sqlcode < 0 ) { printf("连接ORACE出错,确认 ORACLE 系统是否 已启动!\n"); sqlglm(msg_buffer, &buffer_size, &msg_length); printf("ORACLE 出错:%.*s\n", msg_length, msg_buffer); printf("现退出系统。。。\n"); exit(0); } printf("连接 ORACLE 成功 ...\n");

EXEC SQL WHENEVER SQLERROR DO sql_error(); printf("正等待 WEB 端 命令... \n");

EXEC SQL EXECUTE BEGIN

DBMS_PIPE.RESET_BUFFER; END; END-EXEC;

while(1){ char PPnewpasswd[32];

113

Page 114: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

char PPoldpasswd[32]; char pathofpwdfile[256];

EXEC SQL EXECUTE BEGIN :status := DBMS_PIPE.RECEIVE_MESSAGE('acctsysd'); IF :status = 0 THEN DBMS_PIPE.UNPACK_MESSAGE(:command); END IF; END; END-EXEC; if (status != 0) { printf("接收命令出错."); printf(" status: %d\n", status); }else { command.arr[command.len] = '\0'; /* printf("接收命令 command=%s\n",command.arr ); */ /*----------------------------------------------------*/ if (!strcmp((char *) command.arr, "STOP")) { printf("Acctsysd exiting.\n"); break; } /*----------------------------------------------------*/ else if (!strcmp((char *) command.arr, "SYSTEM")) {

EXEC SQL EXECUTE BEGIN DBMS_PIPE.UNPACK_MESSAGE(:return_name); DBMS_PIPE.UNPACK_MESSAGE(:value); END; END-EXEC;

value.arr[value.len] = '\0'; return_name.arr[return_name.len]='\0'; /*

114

Page 115: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

printf("接收命令 return_name=%s\n",return_name.arr ); printf("接收命令 value=%s\n",value.arr ); */ sscanf((char *)value.arr, "%s ", cmdstr);

/*---------------------------------------------------- if(!strcmp((char *)PIPE_EXECUTESYS, cmdstr)) { sscanf((char *)value.arr, "%s %s", cmdstr, pwdfile); } ----------------------------------------------------*/

if(!strcmp((char *)PIPE_GETLDAPUSER, cmdstr)) {

sscanf((char *)value.arr, "%s %s %s", cmdstr, ldap_user, ldap_flag); DEBUG_PRINT("取 LDAP 用户 "); status = get_ldap_user(ldap_user,ldap_flag);

}

if(!strcmp((char *)PIPE_ADDLDAPUSER, cmdstr)) { sscanf((char *)value.arr, "%s %s ", cmdstr, ldap_user); status = add_ldap_user(ldap_user); } if(!strcmp((char *)PIPE_DELLDAPUSER, cmdstr))

{ sscanf((char *)value.arr, "%s %s ", cmdstr, ldap_user); status = del_ldap_user( ldap_user ) ;

}

if(!strcmp((char *)PIPE_MODLDAPUSER, cmdstr)){

sscanf((char *)value.arr, "%s %s %s", cmdstr, ldap_user, ldap_pass );

115

Page 116: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

status = mod_ldap_user( ldap_user, ldap_pass );

}/*--------------------------------------------------*/

if(!strcmp((char *)PIPE_CHK_LDAP_USER, cmdstr)) {

sscanf((char *)value.arr, "%s %s %s", cmdstr, ldap_user, ldap_pass ); status = chk_ldap_user( ldap_user, ldap_pass ); /* if ( status == 0 ) printf(" 用户 %s 存在, %d !\n",user_name.arr, user_cnt ); else printf(" 用户 %s 不存在!\n", ldap_user ); */

} /*----------------------------------------------------*/

value.arr[0] = '\0';

EXEC SQL EXECUTE BEGIN DBMS_PIPE.PACK_MESSAGE('done'); DBMS_PIPE.PACK_MESSAGE(:status); :status := DBMS_PIPE.SEND_MESSAGE(:return_name); END; END-EXEC; if (status) { printf("Acctsysd Error while responding to system command."); printf(" status: %d\n", status); } }

/* 系统命令结束 */

else if (!strcmp((char *)command.arr, "SQL")) { EXEC SQL EXECUTE BEGIN DBMS_PIPE.UNPACK_MESSAGE(:return_name); DBMS_PIPE.UNPACK_MESSAGE(:value); END;

116

Page 117: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END-EXEC; value.arr[value.len] = '\0'; printf("将要执行:'%s'\n", value.arr); EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL EXECUTE IMMEDIATE :value; status = sqlca.sqlcode; EXEC SQL WHENEVER SQLERROR DO sql_error(); EXEC SQL EXECUTE BEGIN DBMS_PIPE.PACK_MESSAGE('done'); DBMS_PIPE.PACK_MESSAGE(:status); :status := DBMS_PIPE.SEND_MESSAGE(:return_name); END; END-EXEC; if (status) { printf("Acctsysd Error while responding to sql command."); printf(" status: %d\n", status); } } else { printf("无效命令: %s\n", command.arr); } } } /* While(1) 结束 */

EXEC SQL COMMIT WORK RELEASE;exit(0);}/* 主程序 main() 结束 */

. . . . . .

117

Page 118: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§20.2 DBMS_ALERT

DBMS_ALERT 包实现对数据库会话的警报(ALERT),警报是当事务进行提交时发送的一条消息。下表是警告的错误信息: 错误信息 存储过程ORU-10001 lock request error, status: N SIGNAL

ORU-10015 error: N waiting for pipe status WAITANY

ORU-10016 error: N sending on pipe ’X’ SIGNAL

ORU-10017 error: N receiving on pipe ’X’ SIGNAL

ORU-10019 error: N on lock request WAIT

ORU-10020 error: N on lock request WAITANY

ORU-10021 lock request error; status: N REGISTER

ORU-10022 lock request error, status: N SIGNAL

ORU-10023 lock request error; status N WAITONE

ORU-10024 there are no alerts registered WAITANY

ORU-10025 lock request error; status N REGISTER

ORU-10037 attempting to wait on

uncommitted signal from same session WAITONE

§20.2.1 使用警告可以在应用中为各种可能事件进行注册,然后用WAITANY过程等待可能的出现事件。应用也可以使用WAITONE或WAITANY来支持超时选件。

§20.2.2 警告所用的各个过程

1.注册警告的过程REGISTER

可以使用 DBMS_ALERT.REGISTER 过程对应用进行注册,对已经注册的应用也可以用REMOVE去掉注册。DBMS_ALERT.REGISTER的语法如下:

118

Page 119: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_ALERT.REGISTER (name IN VARCHAR2);

这里的name 是 本次会话的警告名字。

2.删除警告的过程REMOVE

对于不再需要的已经注册的警告,可以用REMOVE去掉。语法如下:DBMS_ALERT.REMOVE (

name IN VARCHAR2);

这里的name 是 本次会话的警告名字。

3.删除所有警告的过程REMOVEALL

本过程可以注册列表中删除会话中的所有警告。它的语法如下:DBMS_ALERT.REMOVEALL;

4.设置缺省的过程SET_DEFAULTS 可以在循环下来设置警告,这个过程主要是设置循环检测的间隔。语法如下:DBMS_ALERT.SET_DEFAULTS (

polling_interval IN NUMBER);

5.消息过程SIGNAL 警告消息是通告 signal 过程来实现发送。语法如下:DBMS_ALERT.SIGNAL (

name IN VARCHAR2,

message IN VARCHAR2);

6.等待警告过程WAITANY 用WAITONE来等待一个警告的发生,一旦警告已经发出,语法如下:

119

Page 120: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_ALERT.WAITANY (name OUT VARCHAR2,message OUT VARCHAR2,status OUT INTEGER,timeout IN NUMBER DEFAULT MAXWAIT);

其中:name 警告发生的名字message 返回警告的信息status 返回值: 0 – 警告发生 1 – 超时timeout 等待一个警告的最大时间

错误:-20000, ORU-10024: 没有注册的警告措施: 在等待前必须注册一个警告

§20.2.3 警告例子例:当你正在按部门统计员工的平均工资时,你的应用需要知道是否有员工的工资在改变。DBMS_ALERT.REGISTER(’emp_table_alert’);

readagain:

/* ... 读emp表并显示结果 */DBMS_ALERT.WAITONE(’emp_table_alert’, :message, :status);

if status = 0 then goto readagain; else

/* ... error condition */

类似,要为emp建立一个触发器:CREATE TRIGGER emptrig AFTER INSERT OR UPDATE OR DELETE ON emp

BEGIN

DBMS_ALERT.SIGNAL(’emp_table_alert’, ’message_text’);

END;

当不再需要注册的警告时,可以用下面语句删除:

120

Page 121: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_ALERT.REMOVE(’emp_table_alert’);

§20.3 DBMS_PIPE 和 DBMS_ALERT

DBMS_PIPE 和 DBMS_ALERT

两个包都作为 PL/SQL来实现 都连接到同一个实例中来实现会话间的发送消息 警告是基于事件的,不是管道的 当警告已作过通知后,所有注册的会话都接收到该消息。 警告在消息中只能传递单一的字符串,通过管道则可把消息缓冲区的所有内容都发送出

去。 管道发送的消息比警告复杂,所以管道更容易用于双向通信。

第二十一章 数据库作业和文件 I/O

除前面介绍的DBMS包外, PL/SQL包还提供 DBMS_JOB, UTL_FILE包。DBMS_JOB包在运行系统期间定期运行内置过程;而 UTL_FILE 可添加对操作系统文件执行读和写的功能。

121

Page 122: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§21.1 数据库作业

DBMS_JOB包可以在 PL/SQL程序中调度,使得它们在特定的时间运行。作业的运行是将它提交给一个队列,同时用参数指定该作业的运行时间。用户可从数据字典中查看作业的信息以及提交的情况。

§21.1.1后台进程

Oracle 实例是由许多在系统中运行的进程组成的。不同的进程负责不同方面的工作,例如 SNP 进程负责数据库的快照及作业队列。Oracle7 可以有 10 个进程,编号为 SNP0 至 SNP9;Oracle8 可以有 36 个进程,编号为 SNP0 至 SNP9,SNPA 至 SNPZ。参数文件 INITsid.ora 有三个参数控制 SNP 进程的行为:参数 缺省值 返回值 说明JOB_QUEUE_PROCESSES 0 0,10 要启动的进程数,0不会执行任何作业JOB_QUEUE_INTERVAL 60 1,3600 进程唤醒之间的时间间隔JOB_QUEUE_KEEP_CONNEC

TIONS

FALSE TRUE,FALSE 控制 SNP进程是否关闭它的远程数据库连接

§21.1.2运行作业

有两种方式运行作业:将作业提交给作业队列;强行立即执行。当作业被提交给作业队列时,在对它进行调度时一个 SNP进程将会运行它。如果被指定后,那么该作业稍后就可以自动执行。如果是强行立即执行,则只能运行一次。1.提交作业 SUBMIT

PROCEDURE SUBMIT ( job OUT BINARY_INTEGER, What IN VARCHAR2, Next_date IN DATE DEFAULT SYSDATE, Interval IN VARCHAR2 DEFAULT NULL,

122

Page 123: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

No_parse IN BOOLEAN DEFAULT FALSE ) ;

Job BINARY_INTEGER 在创建时赋予的号码(作业号)What varchar2 作业的 PL/SQL代码Next_date date 作业的下一次运行的时间Interval varchar2 计算作业再次运行的时间函数No_parse boolean, true 作业代码在第一次被执行前不分析。

例REM tmpins1.sqlREM Version 1.0, last updated 5/18/97REM This version of TempInsert will remove itself from the job queue ifREM the sequence number is more than 15, as described inREM Chapter 18 of _Oracle8 PL/SQL Programming_ by Scott Urman.

PROMPT Creating procedure...CREATE OR REPLACE PROCEDURE TempInsert (p_NextDate IN OUT DATE) AS v_SeqNum NUMBER; v_StartNum NUMBER; v_SQLCode NUMBER; v_Errmsg VARCHAR2(60);BEGIN SELECT temp_seq.nextval INTO v_SeqNum FROM dual; -- See if this is the first time we're called BEGIN SELECT num_col INTO v_StartNum FROM temp_table WHERE char_col = 'TempInsert Start';

-- We've been called before, so insert a new value INSERT INTO temp_table (num_col, char_col) VALUES (v_SeqNum, TO_CHAR(SYSDATE, 'DD-MON-YY HH24:MI:SS')); EXCEPTION WHEN NO_DATA_FOUND THEN -- First time we're called, so insert INSERT INTO temp_table (num_col, char_col) VALUES (v_SeqNum, 'TempInsert Start');

123

Page 124: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END;

-- If we've been called more than 15 times, exit. IF v_SeqNum - V_StartNum > 15 THEN p_NextDate := NULL; END IF;

COMMIT;END TempInsert;/

-- 用下面命令提交作业:PROMPT Submitting to job queue...VARIABLE v_JobNum

BEGIN DBMS_JOB.SUBMIT(:v_JobNum, 'TempInsert(next_date);', SYSDATE, 'SYSDATE + (5/(24*60*60))');END;/

PRINT v_JobNum

提交后,系统就从 sys.jobseq 为该作业指派一个作业号。要确定每天运行多少次,由 SYSDATE + (60/(24*60*60)) 决定,比如要 30秒运行一次,则写成 SYSDATE + (30/(24*60*60)) ,每 2分钟运行一次,则 SYSDATE + (2*60/(24*60*60))一天运行一次,则 SYSDATE + (( 24*60*60 )/(24*60*60)) 或 SYSDATE +1 .

§21.1.3失效作业

如果作业运行失败,则 oracle 会自动运行它,如果第 2 次作业运行失败,则在 1分钟后尝试运行,如果第 3 次作业运行失败,则在 2分钟后尝试运行,如果第 4 次作业运行失败,则在 4分钟后尝试运行,… ,如果作业 16 次失败,则该作业被置为失效作业。 你可以用 run 命令运行一个失效作业,如果成功则失败计数复位为 0。BROKEN过程可用于改变作业的状态:PROCEDURE BROKEN ( job IN BINARY_INTEGER,

124

Page 125: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Broken IN BOOLEAN, Next_date IN DATE DEFAULT SYSDATE ) ;

如果作业已经损坏,则 Oracle不会去运行它。但是可以用DBMS_JOB.RUN程序去运行它。

1.将作业标记为损坏:过程 DBMS_JOB.BROKEN语法为:DBMS_JOB.BROKEN (job IN BINARY_INTEGER,broken IN BOOLEAN,next_date IN DATE DEFAULT SYSDATE);

job 作业号broken 作业损坏布尔值, next_data 下次刷新的日期例:设置作业 25为损坏,并设置下次运行的日期为将来的星期一:EXEC DBMS_JOB.BROKEN(25,FALSE,next_day(sysdate,’MONDAY’));

2.运行损坏的作业:DBMS_JOB.RUN (job IN BINARY_INTEGER,force IN BOOLEAN DEFAULT FALSE);

例:直接运行 25 号作业:EXEC DBMS_JOB.RUN(25);

§21.1.4删除作业

对于用 DBMS_JOB.SUBMIT过程提交的作业,可以用 DBMS_JOB.REMOVE 过程对其进行取消。要取消某个作业,先要从数据字典 user_jobs中查出:

125

Page 126: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

job作业编号; log_user登录的用户; what PL/SQL 块的名字注意: 用户可以从作业队列中删除作业,但是当前正在运行的操作不会立即被中断,即在完成当前正在进行的操作后才停止下次的运行。

用户只能删除属于自己的作业,不能删除其他用户的作业。

例:要查出 PL/SQL 块名为 tmpint 的作业所对应的作业编号,并从队列中删除它:

1) 先登录到 scott帐户中:

SQL> connect scott/tiger@ora816Connected.

2)查询 SCOTT用户的作业:SQL> select job,log_user, WHAT from user_jobs;

JOB LOG_USER WHAT---------- ------------------------------ -------------------- 25 SCOTT TmpInt;

3)从队列中删除属于 scott所有的 作业 tmpint,其作业号为 25 :SQL> exec dbms_job.remove(25);

PL/SQL procedure successfully completed.

§21.1.5修改作业参数

如果对已经提交的作业某些参数不满意,可以通过下面过程实现对作业参数的修改:

126

Page 127: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

1.DBMS_JOB.CHANGE 程序:DBMS_JOB.CHANGE (job IN BINARY_INTEGER,what IN VARCHAR2,next_date IN DATE,interval IN VARCHAR2,instance IN BINARY_INTEGER DEFAULT NULL,force IN BOOLEAN DEFAULT FALSE);

job 运行的作业号.what PL/SQL 程序next_date 下次刷新的日期interval 间隔启动的时间函数。instance 数据库实例名,如果是(缺省)null,则为当前的实例。Force 如果是 FALSE 则要求的实例必须运行。否则返回错误。注:instance和Force 是Oracle8I才提供的新功能。它们用于并行环境。例:如要将作业编号为 25的作业改为每 3天运行一次,则:EXEC DBMS_JOB.CHANGE(25, null, null, ‘SYSDATE+3’ ) ;

2.DBMS_JOB.WHAT 程序:可以更该作业的定义,语法如下:DBMS_JOB.WHAT (job IN BINARY_INTEGER,what IN VARCHAR2);

job 正在运行的作业号what PL/SQL 程序.

下面例子更改作业编号为 25 的变为另外的程序:EXEC DBMS_JOB.WHAT(25,’scott.emppackage’);

3.DBMS_JOB.NEXT_DATE 程序:可以更改作业下次运行的时间,语法如下:

127

Page 128: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_JOB.NEXT_DATE (job IN BINARY_INTEGER,next_date IN DATE);

job 开始运行的作业号.next_date 下次刷新的日期。例:比如将作业号为 25 的作业改为每天运行一次:EXEC DBMS_JOB.NEXT_DATE(25,’SYSDATE+1’);

4.DBMS_JOB.INTERVAL 程序:可以更改 Oracle 运行作业的下次日期。语法如下:DBMS_JOB.INTERVAL (job IN BINARY_INTEGER,interval IN VARCHAR2);

job 作业号interval 日期函数,作业运行前求值。如:sysdate + 7 表示每星期运行一次next_day(sysdate,’TUESDAY’) 表示每周二运行一次null 只运行一次。

例1:如让25号作业永远不运行,则:EXEC DBMS_JOB.NEXT_DATE(26,null);

例2:如让25号作业每星期日运行一次,则:EXEC DBMS_JOB.NEXT_DATE(26, next_day(sysdate,’SUNDAY’) );

§21.1.6与作业参数有关数据字典

dba_jobs, user_jobs 记录作业的信息dba_jobs_running 描述正在运行的作业

128

Page 129: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§21.2 文件 I/O

在 PL/SQL 2.3 及后来的版本,通过 UTL_FILE包可实现对文件进行 I/O,但目前还不能对二进制文件进行 I/O。ORACLE 8 允许使用 BFILE读取二进制文件(在后面章节讨论)。

§21.2.1 安全性

客户端通过 TEXT_IO包来使创建的文件可以存放在客户端的任何地方。1.数据库安全性 服务器上是通过叫做“可访问目录(accessible directory)”来指定 UTL_FILE可以写入的目录。即通过在参数文件 INITsid.ora 中的 UTL_FILE_DIR参数定义:UTL_FILE_DIT = directory_name

UTL_FILE_DIR参数的指定有一些要求,DBA要根据环境来设置此参数。2.操作系统安全性 ORACLE 用户是该目录的所有者,因此 oracle 应具有对该目录的读写权。在该目录下创建的任何文件都归Oracle所有。如果需要其他的操作系统用户也要访问该目录的文件,还要操作系统的授权才行。

§21.2.2 打开和关闭文件

在UTL_FILE中的所有操作都使用文件的句柄来实现。文件句柄就是 PL/SQL中用来标识文件的值,它类似于DBMS_SQL中使用的光标。所有的文件句柄都是 UTL_FILE.FILE_TYPE类型。文件句柄由 OPEN 返回,并作为 IN(输入)类型参数传递给 UTL_FILE中的其它子程序使用。1.文件打开(FOPEN)

129

Page 130: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

使用 FOPEN 函数可以打开输入或输出文件。在使用中,所打开的文件一次只 能用于输入或用于输出。不能同时都用于输入、输出。FOPEN 函数的语法如下:FUNCTION FOPEN ( location IN VARCHAR2, Filename IN VARCHAR2, Open_mode IN VARCHAR2)RETURN FILE_TYPE;

Location 文件目录路径Filename 要打开的文件名,如果打开方式为“w”,则现存的文件被覆盖。Open_mode 文件的打开方式,“r”表示读文本;“w”表示写文本;“a”表示追加。Return value 返回的值。2.使用max_linesize 参数的文件打开在Oracle 8.0.5以后的版本,可以用下面函数来打开文件:FUNCTION FOPEN (location IN VARCHAR2, Filename IN VARCHAR2, Open_mode IN VARCHAR2, Max_linesize IN BINARY_INTEGER )RETURN FILE_TYPE;

这里的max_linesize 表示文件的最大行数。可以在 1-32767 范围内,缺省为 1024。

3.关闭文件(FCLOSE)当文件被打开后,就需要在用完后进行关闭,用下面函数实现对文件的关闭:PROCEDURE FCLOSE(file_handle IN OUT FILE_TYPE ) ;

这里 file_handle是文件句柄。4.判断文件的打开(IS_OPEN)

文件是否被打开,可以用 IS_OPEN 函数来实现。如果文件已经打开,则返回 TRUE;否则返回 FALSE。FUNCTION IS_OPEN(file_name IN FILE_TYPE);RETURN BOOLEAN;

130

Page 131: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

5.使用 FCLOSE_ALL关闭所有文件对于那些想省事的编程人员,可以用 FCLOSE_ALL来在程序的后部一次就关闭掉所有被打开的文件。它的语法很简单:PROCEDURE FCLOSE_ALL;

§21.2.3文件输出

Oracle PL/SQL 包 提 供 5 个 过 程 来 实 现 将 数 据 输 出 到 文 件 中 。 它 们 是PUT、PUT_LINE、NEW_LINE、PUTE及 FFLUSH。下面分别给出说明。1.PUT过程PROCEDURE PUT(file_handle IN FILE_TYPE, buffer IN VARCHAR2);

通过 PUT 过程可以将字 符追加到文件中,如果需要的话,可以使用 PUT_LINE 或NEW_LINE在行中加入行结束符。这里的 file_handle 是文件的句柄(标识);buffer 是等待写入文件的字符串。如果文件打开没有使用“w”或“a”,则引发错误。

2.NEW_LINE过程PROCEDURE NEW_LINE( file_handle IN FILE_TYPE, Lines IN NATURAL:=1);

表示行结束符,它与操作系统有关。这里的 lines 是输出的行结束符的个数。缺省为 1。即输出一个新行。如果文件打开没有使用“w”或“a”,则引发错误。3.PUT_LINE过程PROCEDURE PUT_LINE( file_handle IN FILE_TYPE, buffer IN VARCHAR2);

通过 PUT_LINE过程等价于 PUT与NEW_LINE一起的功能。

131

Page 132: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

这里的 file_handle 是文件的句柄(标识);buffer 是等待写入文件的字符串。如果文件打开没有使用“w”或“a”,则引发错误。4.PUTF过程PROCEDURE PUTF( file_handle IN FILE_TYPE, Format IN VARCHAR2, Arg1 IN VARCHAR2 DEFAULT NULL, Arg2 IN VARCHAR2 DEFAULT NULL, Arg3 IN VARCHAR2 DEFAULT NULL, Arg4 IN VARCHAR2 DEFAULT NULL, Arg5 IN VARCHAR2 DEFAULT NULL );

这里的 file_handle 是文件的句柄(标识);arg1 至 arg5是可省的变量。Format是带有字符和带有特殊符号“%s”和“\n”的格式说明。

5.FFLUSH过程前面介绍的 PUT、PUT_LINE、NEW_LINE、PUTE 输出的数据首先是放在缓冲区里。当缓冲区填满后,缓冲区的内容自动被写入到文件。但我们可以不需要等待缓冲区填满就立即强行写入指定的文件。FFLUSH就是完成这样的过程:PROCEDURE FFLUSH( file_handle IN FILE_TYPE ) ;

§21.2.3文件输入

文件输入使用的过程只有一个。即 GET_LINE过程。此过程可以完成每次从指定的文件中读入一行文本并将文本送到缓冲区。新行的字符不包括在返回字符串中。PROCEDURE FFLUSH ( file_handle IN FILE_TYPE , Buffer OUT VARCHAR2 );

这里的 file_handle 是文件的句柄(标识);buffer 将 写 入 的 缓 冲 区 , 如 果 文 件 没 有 以 读 (“r”) 的 方 式 打 开 , 则 引 发UTL_FILE.INVALID_OPERATION 异常。

132

Page 133: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

当从文件中读入最后一行时,异常 NO_DATA_FOUND就会发生。如果读入空行就会返回空字符 NULL。

§21.2.4文件操作例子

下面例子选自原版资料 :

例子.

下面例子写一行文本字符:Hello, world!

I come from Zork with greetings for all earthlings.

my_world varchar2(4) := ’Zork’;

...

PUTF(my_handle, ’Hello, world!\nI come from %s with %s.\n’,

my_world,

’greetings for all earthlings’);

第二十二章 在 PL/SQL 使用 SQL语句

在 PL/SQL 程序中主要用 SQL(Structured Query Language ) 进行编程,本章主要讨论在 PL/SQL 中使用 SQL 语句及保证数据一致性的事务控制语句等。

133

Page 134: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§22.1在 PL/SQL 使用DML语句

1. SQL 语句 表 2.1 SQL语句类别 类 别 SQL 语句数据操纵语句 SELECT,INSERT,UPDATE,DELETE

SET TRANSACTION,EXPLAIN PLAN

数据定义语句 DROP ,CREATE,ALTER,GRANT,REVOKE

事务控制 COMMIT, ROLLBACK,SAVEPOINT会话控制 ALTER SESSION,SET ROLE

系统控制 ALTER SYSTEM

嵌入式 SQL CONNECT,DETCLARE CURSOR,

ALLOCATE

2. 在 PL/SQL 中使用 SQL 在 PL/SQL 程序中只能使用 DML 和 事务控制,不能使用 DDL 语句。虽然 EXPLAIN PLAN 被归为 DML 类,但也不能使用。

3. 在 PL/SQL 中使用 DDL 在 PL/SQL V2.1 以后的版本可以采用动态的方法来使用 DDL 语句。 4. 使用 select 语句在 PL/SQL 中, select 语句中只能处理一行,如果匹配了多行,则提示

ORA-01427 : single –row query returns more than one row. 要想返回一条记录,应该采用光标方法。--节选自在线 select.sqlDECLARE V_studentRecord students%ROWTYPE; V_department classes.department%TYPE; V_course classes,course%TYPE;Begin-- 返回一条记录 Select * into v_studentRecord From students where id=10000;-- 返回两个字段 select department, course

134

Page 135: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

into v_department, v_course from classes where room_id=99997;END;

注:可以在 where 后加 where rownum<2 来实现只取一行。此时不回出现上面的提示。5. 使用 INSERT 语句 insert 语句可以包括 一个 select 语句,但要求选择列表要与插入列表相匹配。-- 选自在先代码 insert.sqlDECLARE

V_studentID students.id%TYPE;BEGIN -- 返回一新的 id 号 SELECT student_sequence.NEXTVAL INTO v_StudentID from dual;-- 插入一新行到表中 INSERT INTO students(id,first_name,last_name) VALUES( v_studentsID,’Timothy’, ‘Taller’ );-- 插入第二行到表中 INSERT INTO students( id, first_name, last_name ) VALUES ( student_sequence.NEXTVAL,’Patrick’, ‘Poll’ );END;

6. 使用UPDATE 语句 Update 语句可以包括 一个 select 语句,但要求选择列表要与插入列表相匹配。如果在WHERE 后加 CURRENT OF cursor_name 则表示更新当前光标所在的行。-- 节自在线代码 update.sql DECLARE

V_Mjor students.major%TYPEV_creditincrease NUMBER :=3 ;

BEGIN V_Major := ‘History’; UPDATE students SET current_credits = current_credits + v_creditincrease

WHERE major = v_Major;END;

7.使用DELETE 语句如果在WHERE 后加 CURRENT OF cursor_name 则表示删除当前光标所在的行。 -- 节自在线代码 delete.sqlDECLARE

135

Page 136: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

V_studentcutoff NUMBER;BEGIN V_studentcutoff := 10;DELETE FROM students WHERE current_credits = 0 AND major = ‘Economics’;END;

§22.2 伪列

1.CURRVAL 和 NEXTVAL

可以用 sequence.CURRVAL 得到当前的序列的值,而用 sequence.NEXTVAL 得到序列的下一个值。2.LEVEL

用于对表执行层次树遍历的 SELECT 语句中。详见原版资料《ORACLE SERVER SQL REFERENCE》。3.ROWID rowid 返回一个字符串,ORACLE 7 和 ORACLE8 格式有所不同:ORACLE 7 :BBBBBBBB.RRRR.FFFFBBBBBBBB 是文件的块号;RRRR 块中的行号;FFFF是文件的绝对号。ORACLE8: OOOOOO.FFF.BBBBBB.RRROOOOOO 代表数据对象号;FFF 代表在表空间中的相对文件号;BBBBBB代表在一个文件中的块号;RRR代表块中的位置段(行)号。4. ROWNUM

使用 rownum 可以限制查询的行数。如:select first_name,last_name from students where rownum<3;

136

Page 137: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§22.3 GRANT、REVOKE 和权限

虽然不能直接在 PL/SQL 中使用 GRANT和 REVOKE语句,但他们对 PL/SQL程序的处理会产生影响。因而应在使用 PL/SQL来访问对象(如表)前,必须保证这些对象对于操作者来说应是有权访问的。

§22.3.1 对象和系统权限

对象权限 说明 数据模式,对象ALTER 被授权者可以对对象使用 alter 语句 表,序列DELETE 允许被授权者使用 DELETE 语句 表,视图EXECUTE 允许被授权者执行内置 PL/SQL对象 过程,函数,包INDEX 允许被授权者使用 create index 对表建索引 表INSERT 允许被授权者对对象使用 INSERT 语句 表,视图REFERENCES 允许被授权者创建一个表约束 表SELECT 允许被授权者对对象使用 SELECT 语句 表,视图, 序列,快照UPDATE 允许被授权者对对象使用UPDATE 语句 表,视图

§22.3.2 GRANT和REVOKE命令语法Oracle 提供 GRANT和 REVOKE 命令来实现将权限授予用户或从用户中撤消某些权限。1.GRANT语法如下:GRANT privilege ON object TO grantee [ WITH GRANT OPTION ];

Privilege 为权限Object 为对象的名字Grantee 被授权者的名字WITH GRANT OPTION 加此关键字,表示该用户可以将对象再授权给另外的用户。

2.REVOKE命令的语法如下:

137

Page 138: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

REVOKE privilege ON object FROM grantee [ CASCADE CONSTRAINT ];

Privilege 为权限Object 为对象的名字Grantee 被授权者的名字CASCADE CONSTRAINT 表示撤消与当前对象有关的其它权限。

§22.4 事务控制

事务(transaction)是一系列作为一个单元被成功或不成功执行的 SQL语句。例如银行的事务:从一个帐号上汇出款到另一帐号上去(汇入):

UPDATE accounts SET balance = balance – transaction_amount WHERE account_no= from_acct;

UPDATE accounts SET balance = balance + transaction_amount WHERE account_no = to_acct;

如果第一条语句成功,而第二条语句失败,则产生款已汇出而对方没有收到的不一致的结果,我们可以将两条语句合并为一个事务来避免这种情况发生。这两条语句要不就一块成功,要不就一块失败(用 commit, rollback )。

§22.4.1 COMMIT 和 ROLLBACK

当向数据库发出 commit 语句,那该事务就被终结了,并且:。 事务完成的所有工作永久化;。其它事务可以看到此事务所作的修改;。事务所需要执行的所有加锁(lock)处理被释放。当向数据库发出 rollback 语句,那该事务就被终结了,并且:。事务完成的所有工作被取消(undo);。事务所需要执行的所有加锁(lock)处理被释放。

138

Page 139: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§22.4.2 保留点 SAVEPOINT

rollback 会撤消整个事务,使用 savepoint 可以做到部分撤消事务。BEGIN INSERT INTO temp_table ( char_col ) values(‘insert one’); SAVEPOINT A; INSERT INTO temp_table ( char_col ) values(‘insert two’); SAVEPOINT B; INSERT INTO temp_table ( char_col ) values(‘insert three’); SAVEPOINT C; /* 可在此给出 rollback to B 之类的语句 */ COMMIT;END;

139

Page 140: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§22.5 在 PL/SQL中使用 SQL函数 ORACLE 系统给出许多内置的函数,这些函数可以在 PL/SQL 中用 SQL 语句来使用。这些内置函数分类如下:

错误报告(error reporting )数字(number )字符(character )数据类型转换(datatype conversion )日期(date )对象引用(object reference )各种函数(miscellaneous )

表13-4 内置函数

Error  Number  Character  Conversion  Date Obj Ref  Misc 

SQLCODE SQLERRM

ABS ACOS ASIN ATAN ATAN2 CEIL COS COSH EXP FLOOR LN LOG MOD POWER ROUND SIGN SIN SINH SQRT TAN TANH TRUNC

ASCII CHR CONCAT INITCAP INSTR INSTRB LENGTH LENGTHB LOWER LPAD LTRIM NLS_INITCAP NLS_LOWER NLS_UPPER NLSSORT REPLACE RPAD RTRIM SOUNDEX SUBSTR SUBSTRB

CHARTOROWID CONVERT HEXTORAW RAWTOHEX ROWIDTOCHAR TO_CHAR TO_DATE TO_MULTI_BYTE TO_NUMBER TO_SINGLE_BYTE

ADD_MONTHS

LAST_DAY MONTHS_BETWEEN NEW_TIME NEXT_DAY ROUND SYSDATE TRUNC

DEREF REF VALUE

BFILENAME DECODE DUMP EMPTY_BLOB EMPTY_CLOB GREATEST LEAST NLS_CHARSET_DECL_LEN NLS_CHARSET_ID NLS_CHARSET_NAME NVL SYS_CONTEXT SYS_GUID UID USER USERENV VSIZE

140

Page 141: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Error  Number  Character  Conversion  Date Obj Ref  Misc 

TRANSLATE TRIM UPPER

141

Page 142: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§22.5.1 错误处理函数

错误处理函数 sqlcode 和 sqlerrm是 Oracle专门为处理内部错误而提供的函数。详细见“错误处理”章节。

§22.5.2 数字函数

数字函数大部分都是中学时所学的数学函数,它们都很简单,这里仅介绍两个不太被注意的函数,即 CEIL及 TRUNC。1.CEIL函数:大于或等于 value的最小整数,语法如下:CEIL(value)

Var1:= CEIL (147.2754);

2. TRUNC函数:按照 precision 截取 value,语法如下:TRUNC( value, precision )

Int_val := TRUNC(124.16666,2)结果为 124.16

142

Page 143: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第二十三章 PL/SQL程序的测试和调试

任何高手程序员都不能保证程序在第一次就正确无误,要确保提交给用户的程序运行达到要求,必须对程序进行彻底的测试。

§23.1 问题诊断 由于错误总是多种多样的,因而调试和测试程序对于程序员来说是一种挑战。

§23.1.1 调试指南

调试要点如下:1.找到发生错误的地方2.确定发生了什么3.将程序简化为简单的测试情形4. 建立测试环境

§23.1.2 显示在编译产生的错误

通常情况下,由 PL/SQL解释所产生的错误除了在 SQL>下显示外,还将所产生的错误信息插入到 USER_ERRORS 数据字典中,因此,我们可以用下面命令来检查某个存储过程是否在编译时产生过错误:SQL>select to_char(line|| ‘/’ || to_char( position ) line_pos, Text FROM USER_ERRORS

143

Page 144: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

WHERE name=’chp13-7’ ;

§23.2 插入测试表 由于 oracle pl/sql不能象高级语言那样可以交互式地工作,所以调试最简单的方法是在程序运行时将局部变量的取值插入到一个临时表中,当程序结束时可查询该表以确定变量的值以确定运行时的情况。

§23.3 DBMS_OUTPUT的使用 PL/SQL 本身没有提 供 任 何 输入功能,但 PL/SQL 2.0 以后的版本提 供了内装包

DBMS_OUTPUT 输出功能,在 PL/SQL 2.3 还提供 UTL_FILE包用于对操作系统文件执行读出和写入操作。DBMS_OUTPUT包属于 sys 帐户,但在创建时已将 EXECUTE 权授予 PUBLIC,所以任何用户都可以直接使用而不加 sys模式。2. DBMS_OUTPUT中的过程

DBMS_OUTPUT包中的 PUT 例程是:PUT, PUT_LINE, NEW_LINEDBMS_OUTPUT包中的GET 例程是:GET_LINE,GET_LINES, ENABLE及 DISABLE.

例-- 节选自在线代码 output.sql

REM output.sqlREM Version 1.0, last updated 5/15/97REM This script demonstrates DBMS_OUTPUT.PUT_LINE and DBMS_OUTPUT.GET_LINES,REM as described in Chapter 14 of _Oracle8 PL/SQL Programming_ by Scott Urman.

DECLARE /* Demonstrates using PUT_LINE and GET_LINE. */ v_Data DBMS_OUTPUT.CHARARR;

144

Page 145: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

v_NumLines NUMBER;BEGIN -- Enable the buffer first.

DBMS_OUTPUT.ENABLE(1000000);

-- Put some data in the buffer first, so GET_LINES will -- retrieve something.

DBMS_OUTPUT.PUT_LINE('Line One'); DBMS_OUTPUT.PUT_LINE('Line Two'); DBMS_OUTPUT.PUT_LINE('Line Three');

-- Set the maximum number of lines which we want to retrieve. /* v_NumLines := 3;

Get the contents of the buffer back. Note that v_Data is declared of type DBMS_OUTPUT.CHARARR, so that it matches the declaration of DBMS_OUTPUT.GET_LINES. DBMS_OUTPUT.GET_LINES(v_Data, v_NumLines);

FOR v_Counter IN 1..v_NumLines LOOP INSERT INTO temp_table (char_col) VALUES (v_Data(v_Counter)); END LOOP;*/END;/

buffer_size 是内部缓冲区的初始大小,缺省为 20,000 字节,最大为 1,000,000 字节。

2.使用 DBMS_OUTPUT

用 SET SERVEROUTPUT ON SIZE buffer_size; 指缓冲区的大小,即:SET SERVEROUTPUT ON SIZE 1000000;

另外每一行的大小也受到限制,如行的长度为<= 255 字节。否则得到:ORA-20000:ORU-10027:buffer overflow,limit of <buf_limit> bytes.ORA-20000:ORU-10028:line length overflow, limit of 255 bytes per line.

145

Page 146: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§23.4 PL/SQL调试器 可以用 ORACLE 公司的 Procedure Builder 或 Platinum 公司的 SQL_station Debugger 工具进行调试。

§23.4.1 Procedure Builder调试器 Procedure Builder 是一个 PL/SQL 开发环 境,它是 Developer/2000 的一部分。使用Procedure Builder,开发者可以在客户端采用设置断点,单步跟踪等对程序进行调试。

§23.4.2 SQL-Station调试器

SQL-Station 与 Procedure Builder 调试器类似,也提供一个集成化的 PL/SQL开发环境,它带有一个编辑器和调试器,SQL-Station直接提供在服务器端进行调试。

§23.5 程序设计方法 一个优秀的程序员应该在任何环境下(无论机器多快)无论用什么工具都要考虑程序风格和良好的习惯以及效率问题。

§23.5.1 模块化程序设计 模块化程序设计(modular programming ) 就是将复杂的大程序分隔成不同的部分,即模块,每个模块完成一个特定的功能,然后,你可以顺序开发和测试每个模块并将它们组装到最终的程序中。

146

Page 147: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§23.5.2 自顶向下设计 自顶向下设计(Top-down design)和模块化设计正好相反,它首先先开发程序的基本外壳,然后实现细节。

§23.5.3 数据抽象

数据抽象(data abstraction ) 是另一种程序设计技巧,即可以对一个特定的算法隐去一些实施细节,而仅仅将接口展现给它。

147

Page 148: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第二十四章 性能及其它问题

到任何时候,编程人员都应该考虑性能问题,那种认为现在的机器已经很快了,只要考虑程序的正确性就够了的观点是非常错误。为了编写一个正确的并且高性能的程序并不容易。在 PL/SQL 里,起码要考虑以下一些问题:

§24.1共享池这里的共享池指的是Oracle的 SHARED POOL 。它是系统全局区(SGA)的一部分区域,

该区域专门用于存放 SQL语句的。设置合适的共享池大小是提高性能的关键。关于初始化参数文件 INITsid.ORA的设置详细见《Oracle8i数据库高级管理》--赵元杰著。

§24.1.1 共享池工作原理

一般地,共享池存放的是被解释正确之后的 SQL语句,当数据库接到一条 SQL语句时首先查看共享池中是否有与该条语句完全一样的语句,如果完全一样,就不用解释就直接执行。如果语句类似,但稍微有点不同(如多了空格等)。Oracle就认为是不同的语句而重新解释。解释正确后就将该语句放在共享池中。那么,共享池到底能放多少语句呢?,这取决于我们将共享池设置成多大的问题。一般当共享池被太多语句填满后,共享池中的对象会按照一种算法找出最近很少用(LRU)的语句。对那些很少用语句进行作废。即最长时间没有被使用的语句被移出共享池。一方面,Oracle在处理共享池时。新进来的语句如果有足够的共享池来分配的话。系统

不会出现问题。但如果共享池中碎片过多,新进来语句有很长的话。就可能出现:ORA-04031:Unable to allocate x bytes of shared memory

这样的提示表示共享池中没有足够的空间了。1.冲洗共享池当我们被提示 ORA-04031 错误时。可以使用刷新(Flush)办法来清洗共享池。即将那些目前

148

Page 149: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

没有被使用的语句从共享池中清除掉。语法如下:ALTER SYTEM FLUSH SHARED POOL;

只要具有ALTER SYSTEM权限就可以使用这条语句。另外,当实例运行失败后,也可以运行对共享池进行清洗。2.触发器与共享池由于触发器经过解释后的 p-code 不存放在数据字典中,只存放源代码。因而当某个触发器被触发(点火)时,系统是在当时将触发器的源码从字典中调出经过编译后才放在 SQL 共享池中。如果当这些触发器不再被触发(使用)时就会被移出共享池。因而考虑将共享池编得简短是编程人员要考虑的重要因素。另外可考虑将所执行的处理放在包装的子程序中。然后从共享池来调用该包。这样共享池仅包含对于该包的调用,自然代码也小多了。

§24.1.2 估计共享池大小

共享池大小由初始化 INITsid.ORA 文件中的 SHARED_POOL_SIZE参数确定。安装ORACLE 完成后的缺值一般都太小。Oracle系统不会检测你的物理内存的大小而自动修改该参数的值。所以估计共享池的大小就落到DBA的身上。关于更详细的内容还得参见有关 ORACLE系统调整的资料。下面仅给出一点与 PL/SQL

程序有关简单的算法:1.查询内置程序的大小DBA_OBJECT_SIZE数据字典包含了所有 PL/SQL程序对象的大小。可以用下面语句进行查询:

SQL> SELECT name, type, code_size FROM dba_object_size 2 WHERE name IN('DBMS_PIPE','STANDARD','DBMS_OUTPUT') 3 ORDER BY name, type ;

NAME TYPE CODE_SIZE------------------------------ ------------- ----------------DBMS_OUTPUT PACKAGE 858DBMS_OUTPUT PACKAGE BODY 3729DBMS_OUTPUT SYNONYM 0DBMS_PIPE PACKAGE 1525DBMS_PIPE PACKAGE BODY 4483

149

Page 150: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_PIPE SYNONYM 0STANDARD PACKAGE 1773STANDARD PACKAGE BODY 21982

8 rows selected.

2.查询会话内存的大小可以从 v$process 和 v$session 字典中查询到特定数据库会话所使用内存的大小,这样的操作分两步:1)先查询会话的系统标识 SID:

SQL> select sid from v$process p, v$session s 2 where p.addr=s.paddr and s.username='SYSTEM';

SID----------

12

2)针对特定用户,查询其所使用的内存情况:SQL> select value from v$sesstat s, v$statname n

2 where s.statistic#=n.statistic# 3* and n.name='session uga memory max' and sid=12;

VALUE----------

411036

这个结果反映了到目前止的特定会话所使用的内存大小(system用户用了 411,036 字节)。要想完整地反映系统的内容使用情况,应该在系统运行了一段时间后在运行以上查询才比较准确。这个结果值在乘以会话的数目就可得到所需 共享池的大小了。

§24.1.3 将 PL/SQL 驻留在共享池中

当使用 PL/SQL对象时,oracle将其存储在 SGA 区的共享 SQL 区的库缓存内。如果用户已经把程序加载到内存,那么其它用户在执行这个程序时就感到快多了。因此将程序驻留在内存将减少在执行过程中用户的响应时间。要想将大的 PL/SQL对象驻留在内存中,就应该在数据块刚一开始(系统一启动后)将它

150

Page 151: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

们加载到 SGA中。使用 DBMS_SHARED_POOL程序包可以将 PL/SQL对象驻留在内存中。步骤如下:

对 PL/SQL程序包重新编译;使用DBMS_SHARED_POOL.KEEP 来将程序驻留在内存中。如:sql>alter package APPOWNER.ADD_CLIENT complie;sql>execute DBMS_SHARED_POOL.KEEP(‘APPOWNER.ADD_CLIENT’,’P’);

这里’P’为 程序包,如果是’C’ 则表示指示器。为了通过高速缓存管理标准的 Least recently used 算法把驻留的对象从 SGA中移走,使

用DBMS_SHARED_POOL.UNKEEP程序来完成,如:$sql>execute DBMS_SHARED_POOL.UNKEEP(‘APPOWNER.ADD_CLIENT’);

选择要驻留的程序包每个数据库有两个程序包:1)数据库核心用的程序包(sys拥有);2)特殊应用程

序的专用程序包。下面给出SYS拥有的程序包:

要驻留的程序包普通的应用程序              高级复制附加的程序包DIUTIL DBMS_DEFERSTANDARD DBMS_REPUTILDIANA DBMS_SNAPSHOTDBMS_SYS_SQL DBMS_REFRESHDBMS_SQL DBMS_DEFER_INTERNAL_SYSDBMS_UTILITY REP$WHAT_AM_IDBMS_DESCRIBEDBMS_JOBDBMS_STANDARDDBMS_OUTPUTPIDL

    应首先驻留最大的程序包,为了确定次序,可从 DBA_OBJECT_SIZE 字典中查出各个程序包的大小:select owner, name, typesource_size + code_size + parsed_size + error_size total_bytesfrom dba_object_size where type=’PACKAGE_BODY’ order by total_bytes desc;

151

Page 152: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§24.2 SQL 语句调整

Oracle为了执行每条 SQL语句,首先对该语句确定执行方案(execution plan)。执行方案是 Oracle系统实际执行 SQL语句的方法,比如确定要访问哪个索引和表,是否需要排序等。1.确定执行方案有几种方法可以确定执行方案,这里介绍使用 EXPLAIN PLAN语句来查询方案的办法。1)EXPLAIN PLAN

EXPLAIN PLAN SQL语句可以将一条给定的 SQL语句确定其执行方案,并将执行方案插入到一个数据库表中。EXPLAIN PLAN语句的格式为:EXPLAIN PLAN [SET STATEMENT_ID=’statement_info’][INTO plan_table] FOR sql-statement;

其中:sql_statement 是要解释的 SQL语句。Plan_table 输出表。2)建立输出表

在发出 EXPLAIN PLAN前,需要先建立 PLAN_TABLE 表。该表的脚本一般在:$ORACLE_HOME/rdbms/admin 目录下。要建立 PLAN_TABLE 表,需要运行该目录的UTLXPLAN.SQL脚本。该表的结构如下:CREATE TABLE PLAN_TABLE (

STATEMENT_ID VARCHAR2(30),

TIMESTAMP DATE,

REMARKS VARCHAR2(80),

OPERATION VARCHAR2(30),

OPTIONS VARCHAR2(30),

OBJECT_NODE VARCHAR2(128),

OBJECT_OWNER VARCHAR2(30),

OBJECT_NAME VARCHAR2(30),

OBJECT_INSTANCE NUMERIC,

OBJECT_TYPE VARCHAR2(30),

OPTIMIZER VARCHAR2(255),

SEARCH_COLUMNS NUMBER,

152

Page 153: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ID NUMERIC,

PARENT_ID NUMERIC,

POSITION NUMERIC,

COST NUMERIC,

CARDINALITY NUMERIC,

BYTES NUMERIC,

OTHER_TAG VARCHAR2(255),

PARTITION_START VARCHAR2(255),

PARTITION_STOP VARCHAR2(255),

PARTITION_ID NUMERIC,

OTHER LONG,

DISTRIBUTION VARCHAR2(30));

3)使用 EXPLAIN PLAN分析执行方案

比如建立了下面的 EMP_COMP 表:CREATE TABLE emp_comp PARTITION BY RANGE(hiredate) SUBPARTITION BY

HASH(deptno)

SUBPARTITIONS 3

(

PARTITION emp_p1 VALUES LESS THAN (TO_DATE(’1-JAN-1991’,’DD-MON-YYYY’)),

PARTITION emp_p2 VALUES LESS THAN (TO_DATE(’1-JAN-1993’,’DD-MON-YYYY’)),

PARTITION emp_p3 VALUES LESS THAN (TO_DATE(’1-JAN-1995’,’DD-MON-YYYY’)),

PARTITION emp_p4 VALUES LESS THAN (TO_DATE(’1-JAN-1997’,’DD-MON-YYYY’)),

PARTITION emp_p5 VALUES LESS THAN (TO_DATE(’1-JAN-1999’,’DD-MON-YYYY’))

)

AS SELECT * FROM emp;

我们可以发出EXPLAIN PLAN命令:EXPLAIN PLAN FOR SELECT * FROM emp_comp;

Plan Table

--------------------------------------------------------------------------------

| Operation | Name | Rows | Bytes| Cost | Pstart | Pstop |

--------------------------------------------------------------------------------

| SELECT STATEMENT | | 105 | 8K | 1 | | |

| PARTITION RANGE ALL| | | | | 1 | 5 |

| PARTITION HASH ALL | | | | | 1 | 3 |

| TABLE ACCESS FULL |EMP_COMP| 105 | 8K | 1 | 1 | 15 |

--------------------------------------------------------------------------------

7 rows selected.

153

Page 154: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

我们再发出EXPLAIN PLAN命令:EXPLAIN PLAN FOR SELECT * FROM emp_comp

WHERE hiredate = TO_DATE(’15-FEB-1997’, ’DD-MON-YYYY’);

方案的结果显示如下:

Plan Table

--------------------------------------------------------------------------------

| Operation | Name | Rows | Bytes| Cost | Pstart| Pstop |

--------------------------------------------------------------------------------

| SELECT STATEMENT | | 1 | 96 | 1 | | |

| PARTITION HASH ALL | | | | | 1 | 3 |

| TABLE ACCESS FULL |EMP_COMP| 1 | 96 | 1 | 13 | 15 |

--------------------------------------------------------------------------------

6 rows selected.

关于 语句的分析,请参考 《Oracle应用系统优化与性能调整》。关于 plan_table 表的字段说明请参考 《Oracle8 I Designing and Tuning for Performance》的USING EXPLAIN PLAN 章节。

§24.3 网络问题

当 SQL语句被分析并发送给 Oracle系统后,该语句的构成就决定了执行方案和最终的性能 。SQL语句通常是由用户端进程发给数据库系统中影子进程。即使用户和影子进程是同一台机器上,SQL语句或 PL/SQL 块也必须在用户和影子进程间传送。所以,就花费大量的时间在网络上进行传送。为了减少网络通信流量,程序设计人员就应考虑应用程序的调整问题(application tuning)。可以有下面的办法进行调整: 使用客户端的 PL/SQL,避免不必要的重新分析(reparsing); 如果是 PRO*或 OCI编程,可使用数组接口(array interface)。

154

Page 155: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§24.4 PL/SQL wrap(转换器)

当我们在进行应用系统的源码调试时,可以对过程,函数,包进行修改,也可以从user_source数据字典中读出源码。也可以用其他工具(如 Procedure Builder)以及其它客户端工具来阅读源码,然而,这样的情况有时是不能满足需要的,比如有的算法需要对用户保密等。在 PL/SQL 2.2版后提供了一个 PL/SQL WRAPPER 实用程序,该实用程序将 PL/SQL源码进行编码,使之成为客户不能阅读的十六进制格式。但数据库可以对打包的过程进行解码并将它存储在数据库中。

§24.4.1 运行 wrap实用程序

wrapper 是一个操作系统可执行的文件。它的命令是 wrap。命令格式为:WRAP INAME=input_file [ ONAME=output_name]

这里的 input_file 是包含一条 CREATE OR REPLACE 语句的名字。该文件可以是任何扩展名的文件,缺省为.sql 。输出文件的扩展类型为 .plb 。如:WRAP INAME=register.sql

WRAP INAME=register

WRAP INAME=register.sql ONAME=register.plb

§24.4.2 输入和输出文件

1. 输入文件输入文件即明文的源代码文件,缺省类型为.SQL 文件,但注释除外。如:

CREATE [OR REPLACE]PROCEDURECREATE [OR REPLACE]PACKAGECREATE [OR REPLACE]PACKAGE BODY

155

Page 156: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE [OR REPLACE]FUNCTION

2. 输出文件输出文件一般除了保留前面的 CREATE OR REPLACE XXXX WRAPPED 外,其余部分全部转换成十六进制的符号。并且文件类型为.PLB。PLB 文件也象原来的.SQL 文件可以装载到ORACLE系统中。当经过转换后再装入Oracle中,在DBA_SOURCE(或 USER_SOURCE)看到就是经过变换了的源码。此外,这些源码比起原来的.SQL 文件来要大得多。

§24.5 DBMS_OUTPUT的使用 PL/SQL 本身没有提 供 任 何 输入功能,但 PL/SQL 2.0 以后的版本提 供了内装包

DBMS_OUTPUT 输出功能,在 PL/SQL 2.3 还提供 UTL_FILE包用于对操作系统文件执行读出和写入操作。

DBMS_OUTPUT包属于 sys 帐户,但在创建时已将 EXECUTE 权授予 PUBLIC,所以任何用户都可以直接使用而不加 sys模式。3. DBMS_OUTPUT中的过程

DBMS_OUTPUT包中的 PUT 例程是:PUT, PUT_LINE, NEW_LINEDBMS_OUTPUT包中的GET 例程是:GET_LINE,GET_LINES, ENABLE及DISABLE.

例-- 节选自在线代码 output.sql

REM output.sqlREM Version 1.0, last updated 5/15/97REM This script demonstrates DBMS_OUTPUT.PUT_LINE and DBMS_OUTPUT.GET_LINES,REM as described in Chapter 14 of _Oracle8 PL/SQL Programming_ by Scott Urman.

DECLARE /* Demonstrates using PUT_LINE and GET_LINE. */ v_Data DBMS_OUTPUT.CHARARR; v_NumLines NUMBER;BEGIN -- Enable the buffer first. DBMS_OUTPUT.ENABLE(1000000);

156

Page 157: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

-- Put some data in the buffer first, so GET_LINES will -- retrieve something.

DBMS_OUTPUT.PUT_LINE('Line One'); DBMS_OUTPUT.PUT_LINE('Line Two'); DBMS_OUTPUT.PUT_LINE('Line Three');

-- Set the maximum number of lines which we want to retrieve. v_NumLines := 3;

/* Get the contents of the buffer back. Note that v_Data is declared of type DBMS_OUTPUT.CHARARR, so that it matches the declaration of DBMS_OUTPUT.GET_LINES. */ DBMS_OUTPUT.GET_LINES(v_Data, v_NumLines);

/* Loop through the returned buffer, and insert the contents into temp_table. */ FOR v_Counter IN 1..v_NumLines LOOP INSERT INTO temp_table (char_col) VALUES (v_Data(v_Counter)); END LOOP;END;/

buffer_size 是内部缓冲区的初始大小,缺省为 20,000 字节,最大为 1,000,000 字节。

2.使用 DBMS_OUTPUT

用 SET SERVEROUTPUT ON SIZE buffer_size; 指缓冲区的大小,另外每一行的大小也受到限制,如行的长度为<= 255 字节。否则得到:ORA-20000:ORU-10027:buffer overflow,limit of <buf_limit> bytes.ORA-20000:ORU-10028:line length overflow, limit of 255 bytes per line.

157

Page 158: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第二十五章 对象类型

对象是Oracle首先提出的概念,到Oracle8I 后进行一步得到了完善。对象类型是Oracle用于描述实体的一项技术。它给用户一种更灵活的方法,它可以定义自己需要的类型。

§25.1 对象类型定义对象类型描述了与特殊类型种类的对象关联的属性和方法。对象类型与定义包有些相似。

都有头说明和主体的说明。下面给出创建类型说明语法。

§25.1.1 定义对象类型头

定义对象类型头的语法如下:CREATE [OR REPLACE] TYPE type_name[AUTHID {CURRENT_USER | DEFINER}] {IS | AS} OBJECT (attribute_name datatype[, attribute_name datatype]...[{MAP | ORDER} MEMBER function_spec,][{MEMBER | STATIC} {subprogram_spec | call_spec}[, {MEMBER | STATIC} {subprogram_spec | call_spec}]...]);

§25.1.2 定义对象类型体

定义对象类型体的语法如下: [CREATE [OR REPLACE] TYPE BODY type_name {IS | AS}{ {MAP | ORDER} MEMBER function_body;| {MEMBER | STATIC} {subprogram_body | call_spec};}

158

Page 159: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

[{MEMBER | STATIC} {subprogram_body | call_spec};]...END;]

§25.1.3 定义对象类型例子例:建立对象类型rational:

CREATE TYPE Rational AS OBJECT (num INTEGER,den INTEGER,MAP MEMBER FUNCTION convert RETURN REAL,MEMBER PROCEDURE normalize,MEMBER FUNCTION reciprocal RETURN Rational,MEMBER FUNCTION plus (x Rational) RETURN Rational,MEMBER FUNCTION less (x Rational) RETURN Rational,MEMBER FUNCTION times (x Rational) RETURN Rational,MEMBER FUNCTION divby (x Rational) RETURN Rational,PRAGMA RESTRICT_REFERENCES (DEFAULT, RNDS,WNDS,RNPS,WNPS));

下面开始建立对象类型的主体:CREATE TYPE BODY Rational ASMAP MEMBER FUNCTION convert RETURN REAL IS-- 转换有理数到实数BEGINRETURN num / den;END convert;MEMBER PROCEDURE normalize IS

g INTEGER;BEGINg := gcd(num, den);num := num / g;den := den / g;END normalize;MEMBER FUNCTION reciprocal RETURN Rational IS

BEGINRETURN Rational(den, num); -- 调用构造器END reciprocal;

159

Page 160: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

MEMBER FUNCTION plus (x Rational) RETURN Rational IS-- 返回 SELF + x 的总和r Rational;BEGINr := Rational(num * x.den + x.num * den, den * x.den);r.normalize;RETURN r;END plus;MEMBER FUNCTION less (x Rational) RETURN Rational IS-- 返回 SELF – x 的差r Rational;BEGINr := Rational(num * x.den - x.num * den, den * x.den);r.normalize;RETURN r;END less;MEMBER FUNCTION times (x Rational) RETURN Rational IS-- 返回 SELF * x 的乘积r Rational;

BEGINr := Rational(num * x.num, den * x.den);r.normalize;RETURN r;END times;MEMBER FUNCTION divby (x Rational) RETURN Rational IS--返回 SELF / x 的商r Rational;BEGINr := Rational(num * x.den, den * x.num);r.normalize;RETURN r;END divby;END;

§25.1.4 初始化对象类型如果没有给对象 定 义进行初始 化,它被自动置成 null。所以在定 义 完成后,需要用constructor函数来进行初始化。DECLARE

160

Page 161: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

r Rational; -- r becomes atomically nullBEGINr := Rational(2,3); -- r becomes 2/3

§25.1.5 使用对象类型

建立下面对象,然后开始使用建立过的对象:CREATE TYPE Person AS OBJECT (first_name VARCHAR2(15),last_name VARCHAR2(15),birthday DATE,home_address Address,phone_number VARCHAR2(15))/CREATE TABLE persons OF Person/

BEGININSERT INTO employees -- another object table of type PersonSELECT * FROM persons p WHERE p.last_name LIKE ’%Smith’;

1.Select :

BEGININSERT INTO employeesSELECT VALUE(p) FROM persons pWHERE p.last_name LIKE ’%Smith’;

可以用value 来 返回 persoon 对象:DECLAREp1 Person;p2 Person;...BEGINSELECT VALUE(p) INTO p1 FROM persons pWHERE p.last_name = ’Kroll’;p2 := p1;

161

Page 162: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

...END;

2.INSERT:

BEGININSERT INTO personsVALUES (Person(’Albert’, ’Brooker’, ...));

DECLAREp1_ref REF Person;p2_ref REF Person;...BEGININSERT INTO persons pVALUES (Person(’Paul’, ’Chang’, ...))RETURNING REF(p) INTO p1_ref;INSERT INTO persons pVALUES (Person(’Ana’, ’Thorne’, ...))RETURNING REF(p) INTO p2_ref;

INSERT INTO departmentVALUES (’Payroll’, Person(’Alan’, ’Tsai’, ...), ’Los Angeles’)/

3.UPDATE:

BEGINUPDATE persons p SET p.home_address = ’341 Oakdene Ave’WHERE p.last_name = ’Brody’;...UPDATE persons p SET p = Person(’Beth’, ’Steinberg’, ...)WHERE p.last_name = ’Steinway’;...END;

4.Delete

BEGINDELETE FROM persons pWHERE p.home_address = ’108 Palm Dr’;...END;

162

Page 163: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§25.2 对象类型修改可以用 ALTER TYPE 命令对已建立的对象进行重新编译:ALTER TYPE 语法:ALTER TYPE schema.type_name{ COMPILE { SPECIFICATION | BODY } |REPLACE AS | AS TABLE | AS OBJECT }{ VARRAY (size) | VARYING ARRAY (size) }{ OF datatype}{ REF object_type_name}{ MAP | ORDER MEMBER function_specification }{ PRAGMA RESTRICT_REFERENCESfunction_specification restriction}

变量:schema: 建立类型的数据库用户名type_name: 希望改变的对象名size: VARRAY 大小的上限datatype: 任意类型,如 CHAR, DATE, NUMBER等object_type_name: 对象类型引用的名字function_specification:成员函数名restriction: 限制类型,如 WNDS, WNPS, RNDS, RNPS

例子:ALTER TYPE loan_obj AS OBJECT(customer_name CHAR(20),loan_amount NUMBER(5),MEMBER FUNCTION get_amount RETURN NUMBER,MEMBER FUNCTION get_loan_approved RETURN NUMBER,pragma RESTRICT_REFERENCES (get_amount, WNDS));

163

Page 164: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§25.3 对象类型删除

DROP TYPE语法:DROP TYPE [schema.] type_name [FORCE]

例子:DROP TYPE customer_obj;DROP TYPE loan_obj FORCE;

DROP TYPE BODY语法:DROP TYPE BODY [schema.] type_name例子:DROP TYPE BODY customer_obj;DROP TYPE BODY loan_obj;

164

Page 165: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第二十六章 动态 PL/SQL简介

在前面介绍的内容中都不能在 PL/SQL 程序使用 DDL 语句,这章介绍通过 DBMS_SQL 包可以动态地使用DDL语句。

§26.1 概述 一般在 PL/SQL程序设计中,可以直接使用的 SQL语句是DML语句和事务控制语句。另外的 DDL 语句、会 话和系统控制语句不能在 PL/SQL 中直接使用。在这里,我们通过DBMS_SQL包可以(在 PL/SQL 2.1 或更高的版本上)使用 DDL语句。实际上 DBMS_SQL 将通常执行 SQL和 PL/SQL的处理给外部化了并把它们置于你的控制之下。

§26.1.1 静态 SQL和动态 SQL

静态 SQL 语句:PL/SQL 程序中在编译时 SQL语句是明确的。 动态 SQL语句:PL/SQL程序中在编译时 SQL语句是不明确的,编译程序对动态语句部分不进行处理。只在程序运行时动态创建并进行语法分析和执行。

可以通过使用DBMS_SQL包(PL/SQL 2.1及以上版本)来实现动态。 也可以通过本地动态 SQL方法来实现动态。

§26.1.2 用DBMS_SQL 包实现动态在 PL/SQL 2.1及以上版本,可以使用DBMS_SQL包来实现动态。DBMS_SQL包执行的步骤如下:1)将 SQL语句或 PL/SQL语句块放到一个字符串中;2)使用DBMS_SQL.PARSE分析该字串;3)使用DBMS_SQL.BIND_VARIABLE 联编输入变量;

165

Page 166: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

4)如 果 该 语 句 不 是 查 询 语 句 , 使 用 DBMS_SQL.EXECUTE 和 / 或DBMS_SQL.VARIABLE_VALUE 执行它。如果是查询语句继续执行 5);

5)如果该语句是查询语句,使用DBMS_SQL.DEFINE_COLUMN 定义输出变量;6)使用DBMS_SQL.EXECUTE, DBMS_SQL.FETCH_ROWS, DBMS_SQL.COLUMN_VALUE,以及 DBMS_SQL.VARIABLE_VALUE 执行查询语句并提取结果。

例REM 文件名:recrtemp.sqlREM 这个存储过程使用DBMS_SQL 包重新创建 temp_tableREM 作者:Scott Urman.

CREATE OR REPLACE PROCEDURE RecreateTempTable ( /* 删除 temp_table 表再重建. 调用方法: RecreateTempTable('(num_col NUMBER, char_col VARCHAR2(2000))'); */ p_Description IN VARCHAR2) IS

v_Cursor NUMBER; v_CreateString VARCHAR2(100); v_DropString VARCHAR2(100); v_NumRows INTEGER;BEGIN /* 打开光标. */ v_Cursor := DBMS_SQL.OPEN_CURSOR;

/* 先删除表. */ v_DropString := 'DROP TABLE temp_table';

/* 分析和执行 'DROP TABLE' 命令. 可能表不存在而出现 ORA-942 错误. */ BEGIN -- DBMS_SQL.NATIVE is a constant defined in the package header. -- Oracle8是 dbms_sql.native --DBMS_SQL.PARSE(v_Cursor, v_DropString, dbms_sql.native);

DBMS_SQL.PARSE(v_Cursor, v_DropString, dbms_sql.native); v_NumRows := DBMS_SQL.EXECUTE(v_Cursor); EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE;

166

Page 167: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END IF; END; /* 先建立表,需要CREATE TABLE 字符串然后分析和执行. */ v_CreateString := 'CREATE TABLE temp_table ' || p_Description; DBMS_SQL.PARSE(v_Cursor, v_CreateString, dbms_sql.native); v_NumRows := DBMS_SQL.EXECUTE(v_Cursor);

/* 关闭光标, 工作已经完成。 */ DBMS_SQL.CLOSE_CURSOR(v_Cursor);EXCEPTION WHEN OTHERS THEN

/* 先关闭光标,然后再启动错误以传播信息*/ DBMS_SQL.CLOSE_CURSOR(v_Cursor); RAISE;END RecreateTempTable;/

警告:为了运行本程句,你必须被 授予 CREATE TABLE 和DROP TABLE 系统权限。

§26.1.3 用本地动态 SQL实现动态在 Oracle8I 或更高的版本中,可以使用 EXECUTE IMMEDATE语句来处理非查询语句和PL/SQL 块的光标。

§26.2 使用DBMS_SQL进行动态编程DBMS_SQL包可以实现动态编程,即在 PL/SQL程序中使用DDL语句和会话语句等。

§26.2.1 执行DML、DDL及Alter session语句在 PL/SQL程序中,执行DML 、DDL及 alter session 语句需要下面步骤:1)打开光标(open cursor)2)分析该语句(parse)

167

Page 168: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

3) 联编输入变量(bind variable)4) 执行该语句(execute)5)关闭该光标(close cursor)

1.打开光标 打开光标的语法如下: OPEN_CURSOR RETURN INTEGER;

2. 分析语句将语句发给服务器分析,如有错误则返回提示。语法如下:

PROCEDURE PARSE ( c IN INTEGER, Statement IN VARCHAR2,

Language_flag IN INTEGER);

其中:c integer 分析语句用的光标 id 号statement varchar2 要分析的 SQL 语句language_flag integer 决定语句的处理方式,可能为:DBMS_SQL.V6 DBMS_SQL.NATIVE, DBMS_SQL.NATIVE

3. 联编输入变量 联编将语句中的占位符和实际的 PL/SQl 变量关联起来。下面是用于联编不同类型变量的过程:1)用于联编 number 变量的过程: PROCEDURE BIND_VARIABLE ( c IN INTEGER, Name IN VARCHAR2, Value IN NUMBER ) ;

2)用于联编 varchar2 变量的过程:

168

Page 169: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

PROCEDURE BIND_VARIABLE ( c IN INTEGER, Name IN VARCHAR2, Value IN VARCHAR2 ) ;

PROCEDURE BIND_VARIABLE ( c IN INTEGER, Name IN VARCHAR2, Value IN VARCHAR2, Out_value_size IN INTEGER );

3)用于联编 date变量的过程: PROCEDURE BIND_VARIABLE ( c IN INTEGER, Name IN VARCHAR2, Value IN DATE ) ;

4)用于联编 char 变量的过程: PROCEDURE BIND_VARIABLE ( c IN INTEGER, Name IN VARCHAR2, Value IN CHAR ) ;

PROCEDURE BIND_VARIABLE ( c IN INTEGER, Name IN VARCHAR2, Value IN CHAR , Out_value_size IN INTEGER );

5)用于联编 RAW 变量的过程: PROCEDURE BIND_VARIABLE ( c IN INTEGER, Name IN VARCHAR2, Value IN RAW ) ;

PROCEDURE BIND_VARIABLE ( c IN INTEGER, Name IN VARCHAR2, Value IN RAW, Out_value_size IN INTEGER );

6)用于联编MLSLABLE 变量的过程: PROCEDURE BIND_VARIABLE ( c IN INTEGER,

169

Page 170: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Name IN VARCHAR2, Value IN MLSLABLE ) ;

7)用于联编 ROWID 变量的过程: PROCEDURE BIND_VARIABLE ( c IN INTEGER, Name IN VARCHAR2, Value IN ROWID ) ;

4. 执行语句用 EXECUTE 命令可以执行语句,执行后返回已经处理的行数。注意,EXECUTE 执行的仅是合法的语句,对于 DDL语句,EXECUTE 执行的空操作(no_op)。这些 DDL语句只在PARSE 命令时被执行。EXECUTE 函数的语法如下: FUNCTION EXECUTE ( c IN INTEGER ) RETURN INTEGER;

C integer 是要执行的光标的 ID 号Return integer 已经处理过语句的行数

5. 关闭光标关闭光标用 CLOSE_CURSOR 命令来实现。其语法如下:PROCEDURE CLOSE_CURSOR( c IN OUT INTEGER ) ;

§26.2.2 示例REM updclass.sqlREM 这是一个用 DBMS_SQL 来执行 DML 语句的例子CREATE OR REPLACE PROCEDURE UpdateClasses( /* 使用DBMS_SQL 更新一个教室表 */

p_Department IN classes.department%TYPE, p_NewCredits IN classes.num_credits%TYPE, p_RowsUpdated OUT INTEGER) AS

v_CursorID INTEGER;

170

Page 171: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

v_UpdateStmt VARCHAR2(100);BEGIN -- 为处理打开光标 v_CursorID := DBMS_SQL.OPEN_CURSOR;

-- 确定 SQL 字串. v_UpdateStmt := 'UPDATE classes SET num_credits = :nc WHERE department = :dept';

-- 分析语句. DBMS_SQL.PARSE(v_CursorID, v_UpdateStmt, DBMS_SQL.NATIVE);

-- 绑定变量 p_NewCredits 到占为符 :nc. DBMS_SQL.BIND_VARIABLE(v_CursorID, ':nc', p_NewCredits); -- 绑定变量 p_Department 到占为符:dept. DBMS_SQL.BIND_VARIABLE(v_CursorID, ':dept', p_Department);

-- 执行语句. p_RowsUpdated := DBMS_SQL.EXECUTE(v_CursorID);

--关闭光标. DBMS_SQL.CLOSE_CURSOR(v_CursorID);EXCEPTION WHEN OTHERS THEN --关闭光标,然后激活错误. DBMS_SQL.CLOSE_CURSOR(v_CursorID); RAISE;END UpdateClasses;/

§26.2.3 执行DDL 语句在 PL/SQL程序中,与执行DML 语句不同之处:1)因为在DDL语句中联编变量是非法的,所以分析后不需 BIND_VARIABLE2)DDL语句实际上是在调用 PARSE时执行的,因而 EXECUTE 也不必要(不起作用)。例:REM recrtmp2.sql

171

Page 172: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

REM RecreateTempTable 说明使用 DBMS_SQL 执行 DDL 命令的例子REM 作者:Scott Urman.

CREATE OR REPLACE PROCEDURE RecreateTempTable ( /* 删除 temp_table 表在重建它. */

p_Description IN VARCHAR2) IS

v_Cursor NUMBER; v_CreateString VARCHAR2(100); v_DropString VARCHAR2(100);BEGIN /* 打开光标. */ v_Cursor := DBMS_SQL.OPEN_CURSOR;

/* 先删除表. */ v_DropString := 'DROP TABLE temp_table';

/* 分析 'DROP TABLE' 命令, 然后执行. 可能提示 ORA-942 error in case the table doesn't yet exist. */ BEGIN -- DBMS_SQL.NATIVE 是一个常数. DBMS_SQL.PARSE(v_Cursor, v_DropString, DBMS_SQL.NATIVE); EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END; /* 重新建表,需要 CREATE TABLE 字符串,然后分析执行 */ v_CreateString := 'CREATE TABLE temp_table ' || p_Description; DBMS_SQL.PARSE(v_Cursor, v_CreateString, DBMS_SQL.NATIVE);

/* 关闭光标, 工作完成。 */ DBMS_SQL.CLOSE_CURSOR(v_Cursor);EXCEPTION WHEN OTHERS THEN /* 首先关闭光标, 然后激活错误提示 */

DBMS_SQL.CLOSE_CURSOR(v_Cursor); RAISE;END RecreateTempTable;/

172

Page 173: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§26.2.4 执行 PL/SQL 块在 PL/SQL 程序中,可以在动态中执行 PL/SQL 块。对 PL/SQL 块的执行处理上与对DML 、DDL的处理类似。它的调用步骤如下:

打开光标(OPEN_CURSOR); 对查询语句进行分析(PARSE); 绑定所有的输入/输出变量(BAND_VARIBLE); 执行查询语句(EXECUTE); 检索所有输出变量的值(COLUMN_VALUE); 关闭光标。

1 对 PL/SQL 块语句进行语法分析传到 PARSE中的所有 PL/SQL 块字符(包括 END;),包括绑定变量标识符、输出变量(如果存储过程带OUT参数)进行分析。在块中执行完 VRIABLE_VALUE后,可以检索这些变量的新值。提示:由于语法分析不能识别双减号(- -),建议使用 /* */ 作为注释。2 检索所有输出变量的值在执行结束后,可以使用 VRIABLE_VALUE来检索存放输出结果的变量的值。与查询语句类似,该值是由 EXECUTE语句先存储在缓冲区中,然后使用 VRIABLE_VALUE从缓冲区将它们检索出来。检索只是些被 BIND_VRIABLE中变量才能用VRIABLE_VALUE进行操作。

§26.4 本地动态 SQL

前面提到,有两方式可以使用动态 SQL语句,一种是DBMS_SQL包;另外就是本地动态 SQL。本地动态 SQL是使用 EXECUTE IMMEDIATE语句来实现的。下面给出介绍。

§26.4.1使用 EXECUTE IMMEDIATE语句可以用 EXECUTE IMMEDIATE语句准备(分析)和立即执行一个动态的语句或一个匿名

173

Page 174: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

PL/SQL 块。语法如下:EXECUTE IMMEDIATE dynamic_string[INTO {define_variable[, define_variable]... | record}][USING [IN | OUT | IN OUT] bind_argument[, [IN | OUT | IN OUT] bind_argument]...][{RETURNING | RETURN} INTO bind_argument[, bind_argument]...];

其中:dynamic_string SQL 语句表达式或 PL/SQL 块, define_variable 存储select 列值的变量 record 用户定义的或选择的记录类型%ROWTYPEbind_argument (IN 输入)可传到动态SQL的表达式或PL/SQL块bind_argument 存储返回值的变量或PL/SQL块

例子:下面包括几个动态 SQL:

DECLAREsql_stmt VARCHAR2(200);plsql_block VARCHAR2(500);emp_id NUMBER(4) := 7566;salary NUMBER(7,2);dept_id NUMBER(2) := 50;dept_name VARCHAR2(14) := ’PERSONNEL’;location VARCHAR2(13) := ’DALLAS’;emp_rec emp%ROWTYPE;

BEGINEXECUTE IMMEDIATE ’CREATE TABLE bonus (id NUMBER, amt NUMBER)’;

sql_stmt := ’INSERT INTO dept VALUES (:1, :2, :3)’;

EXECUTE IMMEDIATE sql_stmt USING dept_id, dept_name, location;sql_stmt := ’SELECT * FROM emp WHERE empno = :id’;

EXECUTE IMMEDIATE sql_stmt INTO emp_rec USING emp_id;plsql_block := ’BEGIN emp_pkg.raise_salary(:id, :amt); END;’;

EXECUTE IMMEDIATE plsql_block USING 7788, 500;sql_stmt := ’UPDATE emp SET sal = 2000 WHERE empno = :1RETURNING sal INTO :2’;

EXECUTE IMMEDIATE sql_stmt USING emp_id RETURNING INTO salary;EXECUTE IMMEDIATE ’DELETE FROM dept WHERE deptno = :num’

174

Page 175: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

USING dept_id;

EXECUTE IMMEDIATE ’ALTER SESSION SET SQL_TRACE TRUE’;END;

§26.4.2向后兼容情况当一个动态的 INSERT、UPDATE 或 DELETE语句有一个 RETURNING 子句时,输出绑定变量可以放进到RETURNING INTO 子句中或者使用该子句。在新的应用中,可以使用 RETURNING INTO 子句;而在旧的应用中,你可继续使用USING子句。下面的语句都是合法的:DECLAREsql_stmt VARCHAR2(200);my_empno NUMBER(4) := 7902;my_ename VARCHAR2(10);my_job VARCHAR2(9);my_sal NUMBER(7,2) := 3250.00;BEGINsql_stmt := ’UPDATE emp SET sal = :1 WHERE empno = :2RETURNING ename, job INTO :3, :4’;

/* Bind returned values via USING clause. */EXECUTE IMMEDIATE sql_stmtUSING my_sal, my_empno, OUT my_ename, OUT my_job;

/* Bind returned values via RETURNING INTO clause. */EXECUTE IMMEDIATE sql_stmtUSING my_sal, my_empno RETURNING INTO my_ename, my_job;...END;

175

Page 176: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§26.4.3指定参数模式使用USING子句,你可以不用为输入绑定变量指定参数,因为这个模式的缺省是IN。使用RETURNING INTO子句,你不能为输出绑定变量指定参数模式,因为该模式是OUT。例如:DECLARE

sql_stmt VARCHAR2(200);dept_id NUMBER(2) := 30;old_loc VARCHAR2(13);

BEGINsql_stmt :=’DELETE FROM dept WHERE deptno = :1 RETURNING loc INTO :2’;EXECUTE IMMEDIATE sql_stmt USING dept_id RETURNING INTO old_loc;...END;

在适当时,你可以以参数形式为绑定变量指定 OUT 或 IN 模式。例如,假定你希望调用下面独立的过程:CREATE PROCEDURE create_dept (deptno IN OUT NUMBER,dname IN VARCHAR2,loc IN VARCHAR2) ASBEGINdeptno := deptno_seq.NEXTVAL;INSERT INTO dept VALUES (deptno, dname, loc);END;

但是,从一个动态的PL/SQL块来调用过程时,你必须为绑定变量指定IN OUT模式。如:DECLAREplsql_block VARCHAR2(500);

new_deptno NUMBER(2);new_dname VARCHAR2(14) := ’ADVERTISING’;new_loc VARCHAR2(13) := ’NEW YORK’;BEGINplsql_block := ’BEGIN create_dept(:a, :b, :c); END;’;EXECUTE IMMEDIATE plsql_blockUSING IN OUT new_deptno, new_dname, new_loc;IF new_deptno > 90 THEN ...END;

176

Page 177: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第二十七章 LOB和DBMS_LOB包简介

Oracle7以后的版本都支持大型对象,Oracle8/8I支持的大型对象有:LOB类型 说明CLOB 字符型类型大对象NCLOB 多字节国家字符数据,可存放变长的字符。BLOB 无结构的二进制数据。BFILE 外部二进制数据,数据文件存放操作系统目录下。到 Oracle8I以后,Oracle 提供了更多的关于 LOB处理的包,随着硬盘容量的迅速扩大和数据库存储技术的完善以及许多应用对 LOB的需求的增加,希望能在应用中存放 LOB类型数据(如图象、声音等)的要求已经提到日程上。下面简单介绍关于 LOB数据的使用方法。

§27.1 LOB类型一般使用在Oracle8/8I、Oracle9I系统中,仍支持 LONG、LONG RAW等大对象类型,但是,在不同的版本中,所支持的 LOB的大小有所不同。要使用 LOB类型,要注意它有下面的特性:

LONG 、LONG RAW 最大长度 4GB 可以通过Oracle8I OCI 或 PL/SQL包来处理 LOB LOB可以作为绑定变量来使用

§27.1.1 LOB类型存储一般来说,LONG,LONG RAW类型数据都常常存放在数据库的表中,但 LOB很少存放在数据库的表中,而是在数据库的原始表中存放指示 LOB存储的位置。1.LOB 类型:LOB是用来存放二进制数据的类型,它与 RAW 或 LONG RAW类型一样。数据库不解释该

177

Page 178: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

类型中存放数据的真正含义,只是通过接口来对这些数据进行检索或修改。2.CLOB和NCLOB 类型:CLOB用来存放大的字符类型,而NCLOB 则是用来存放国家字符集的类型。这两个实际就是用双字节统一字符集的数据。3.BFILE 类型:为了访问操作系统下的文件,Oracle 允许定义 BFILE类型数据。为了使Oracle能知道外部文件所在目录和文件名字,还需要建立相应的目录:CREATE DIRECTORY dir_name AS os_path;

CREATE DIRECTORY utils AS ‘/home/utils’ ;

已经创建的目录可以从 DBA_DIRECTORIES数据字典中查到。如果取消目录可以用DROP DIRECTORY dir_name;来实现。一般来说,每个会话可以使用的外部文件的打开数与 SESSION_MAX_OPEN_FILES参数有关。

§27.1.2 临时 LOB类型在Oracle8I 里,一般的 LOB 声明都具有永久的属性,也就是说 LOB类型的数据可以永久地存放在数据库表里。此外,Oracle8I还提供了临时的 LOB。它是通过定义指针来实现。

当创建表为临时的 LOB 表结构时,该表内的 LOB只是会话期间存在,当会话结束后,临时 LOB就被取消。临时 LOB使用要注意下面情况:

如果输入参数为 NULL,在 DBMS_LOB中的所有函数返回 NULL;如果以 NULL作为 LOB 指针,则所有DBMS_LOB引发例外。

如果字符集的 ID匹配(CLOB参数、VARCHAR2 缓冲区和模式),则基于 CLOB运算不作检查。

数据存储资源可以由DBA通过建立不同的临时表空间来控制。DBA可以为不同的用户定义不同的表空间。

178

Page 179: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

为了与永久的 LOB一致,临时 LOB也可以跟语义值并符合 ANSI标准。例:DECLAREa blob;b blob;BEGIN

dbms_lob.createtemporary(b, TRUE);-- the following assignment results in a deep copya := b;END;

§27.1.3 LOB类型的接口Oracle8I 提供了下面 6种接口:接口 Oracle/Oracle8i 说明DBMS_LOB Oracle8 通过 PL/SQL包来访问 LOB。OCI Oracle8 通过 Pro*C/C++来处理 LOB数据Pro*C/C++ Oracle8i 允许在 Pro*C/C++中嵌入访问 LOB的命令。Pro*COBOL Oracle8i 允许在 Pro*COBOL中嵌入访问 LOB的命令。OLE(OO4O) Oracle8i OO4O 提供在VB中访问 LOB。JDBC Oracle8i JDBC API 允许从 Java 程序中对 LOB进行操作。

§27.2 一般 LOB表与数据加载LOB类型是特殊的类型,它不象数据和字符那样容易,一般要使用数据库提供的包等来实现数据的操作。

§27.2.1 建立包含 LOB的表Oracle支持 LOB,那么如何才能存放 LOB到表中呢,可以有三种办法:

建立一个带一个或多个 LOB类型的表; 建立一个带对象类型,并且对象类型包含 LOB的表; 建立一个嵌套的表,嵌套包含 LOB类型。

179

Page 180: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

下面仅介绍在创建表结构时带有 LOB类型的情况。

例:创建具有 LOB的表CONNECT system/manager;DROP USER samp CASCADE;DROP DIRECTORY AUDIO_DIR;DROP DIRECTORY FRAME_DIR;DROP DIRECTORY PHOTO_DIR;DROP TYPE InSeg_typ force;DROP TYPE InSeg_tab;DROP TABLE InSeg_table;CREATE USER samp identified by samp;GRANT CONNECT, RESOURCE to samp;CREATE DIRECTORY AUDIO_DIR AS ’/tmp/’;CREATE DIRECTORY FRAME_DIR AS ’/tmp/’;CREATE DIRECTORY PHOTO_DIR AS ’/tmp/’;GRANT READ ON DIRECTORY AUDIO_DIR to samp;GRANT READ ON DIRECTORY FRAME_DIR to samp;GRANT READ ON DIRECTORY PHOTO_DIR to samp;

CONNECT samp/sampCREATE TABLE a_table (blob_col BLOB);CREATE TYPE Voiced_typ AS OBJECT (Originator VARCHAR2(30),Script CLOB,Actor VARCHAR2(30),Take NUMBER,Recording BFILE);

CREATE TABLE VoiceoverLib_tab of Voiced_typ (Script DEFAULT EMPTY_CLOB(),CONSTRAINT TakeLib CHECK (Take IS NOT NULL),Recording DEFAULT NULL);CREATE TYPE InSeg_typ AS OBJECT (Segment NUMBER,Interview_Date DATE,Interviewer VARCHAR2(30),Interviewee VARCHAR2(30),Recording BFILE,Transcript CLOB);CREATE TYPE InSeg_tab AS TABLE of InSeg_typ;

180

Page 181: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE TYPE Map_typ AS OBJECT (Region VARCHAR2(30),NW NUMBER,NE NUMBER,SW NUMBER,SE NUMBER,Drawing BLOB,Aerial BFILE);CREATE TABLE Map_Libtab of Map_typ;CREATE TABLE Voiceover_tab of Voiced_typ (Script DEFAULT EMPTY_CLOB(),CONSTRAINT Take CHECK (Take IS NOT NULL),Recording DEFAULT NULL);

CREATE TABLE Multimedia_tab (Clip_ID NUMBER NOT NULL,Story CLOB default EMPTY_CLOB(),FLSub NCLOB default EMPTY_CLOB(),Photo BFILE default NULL,Frame BLOB default EMPTY_BLOB(),Sound BLOB default EMPTY_BLOB(),Voiced_ref REF Voiced_typ,InSeg_ntab InSeg_tab,Music BFILE default NULL,

Map_obj Map_typ) NESTED TABLE InSeg_ntab STORE AS InSeg_nestedtab;

§27.2.2 用 EMPTY_CLOB或 EMPTY_BLOB插入 LOB

Oracle8提供了DML语句EMPTY_CLOB()和EMPTY_BLOB()可以实现将LOB类型数据加载到表中。但是,这些函数与DBMS_LOB没有关系。/* 列 STORY 和 FLSUB 用 EMPTY_CLOB()来初始化列 FRAME 和SOUND用 EMPTY_BLOB()来初始化列TRANSSCRIPT用 EMPTY_CLOB() 来初始化列 DRAWING 用 EMPTY_BLOB()来初始化*/INSERT INTO Multimedia_tab

181

Page 182: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

VALUES (1, EMPTY_CLOB(), EMPTY_CLOB(), NULL, EMPTY_BLOB(), EMPTY_BLOB(),NULL, InSeg_tab(InSeg_typ(1, NULL, ’Ted Koppell’, ’Jimmy Carter’, NULL,EMPTY_CLOB())), NULL, Map_typ(’Moon Mountain’, 23, 34, 45, 56, EMPTY_BLOB(),NULL));/* 在 Voiceover_tab表的新行中, SCRIPT列要用来初始化 */INSERT INTO Voiceover_tabVALUES (’Abraham Lincoln’, EMPTY_CLOB(), ’James Earl Jones’, 1, NULL);

§27.2.3 一般的 LOB插入可以编写一个简单的过程来实现将LOB加载到多媒体表中:例。CREATE OR REPLACE PROCEDURE insertUseBindVariable_proc(Rownum IN NUMBER, Blob_loc IN BLOB) ISBEGININSERT INTO Multimedia_tab (Clip_ID, Sound) VALUES (Rownum, Blob_loc);END;DECLAREBlob_loc BLOB; BEGIN/* Select the LOB from the row where Clip_ID = 1,Initialize the LOB locator bind variable: */SELECT Sound INTO Blob_locFROM Multimedia_tabWHERE Clip_ID = 1;/* Insert into the row where Clip_ID = 2: */insertUseBindVariable_proc (2, Blob_loc);COMMIT;END;

§27.3 内部 LOB和DBMS_LOB的使用Oracle系统提供的 DBMS_LOB包可以完成对 LOB对象进行内部读写和外部读写操作 。

DBMS_LOB包包括多个程序,如: DBMS_LOB.APPEND 将源 LOB追加到目标 LOB的尾部; DBMS_LOB.INST 返回 LOB中给定模式的位置; DBMS_LOB.COMPARE 比较 LOB是否相等。。 。 。   。 。 。

182

Page 183: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§27.3.1 APPEND过程此过程可以加内部的完整的源 LOB到目标的 LOB中。语法如下:DBMS_LOB.APPEND (dest_lob IN OUT NOCOPY BLOB,src_lob IN BLOB);DBMS_LOB.APPEND (dest_lob IN OUT NOCOPY CLOB CHARACTER SET ANY_CS,src_lob IN CLOB CHARACTER SET dest_lob%CHARSET);

例子:CREATE OR REPLACE PROCEDURE Example_1a ISdest_lob, src_lob BLOB;BEGIN-- 得到 LOB 位置-- 用FOR UPDATE锁住行SELECT b_lob INTO dest_lobFROM lob_tableWHERE key_value = 12 FOR UPDATE;SELECT b_lob INTO src_lobFROM lob_tableWHERE key_value = 21;DBMS_LOB.APPEND(dest_lob, src_lob);COMMIT;EXCEPTIONWHEN some_exceptionTHEN handle_exception;END;CREATE OR REPLACE PROCEDURE Example_1b ISdest_lob, src_lob BLOB;BEGIN

-- 得到 LOB 位置-- 用FOR UPDATE锁行SELECT b_lob INTO dest_lobFROM lob_tableWHERE key_value = 12 FOR UPDATE;SELECT b_lob INTO src_lob

183

Page 184: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

FROM lob_tableWHERE key_value = 12;DBMS_LOB.APPEND(dest_lob, src_lob);COMMIT;EXCEPTIONWHEN some_exceptionTHEN handle_exception;END;

§27.3.2 CLOSE过程此过程关闭掉先前打开的内部或外部LOB,语法如下:DBMS_LOB.CLOSE (lob_loc IN OUT NOCOPY BLOB);DBMS_LOB.CLOSE (lob_loc IN OUT NOCOPY CLOB CHARACTER SET ANY_CS);DBMS_LOB.CLOSE (

file_loc IN OUT NOCOPY BFILE);

§27.3.3 COMPARE函数这个函数比较两个整体的LOB或部分的LOB。可以只比较相同数据类型部分。对于BFILE,要求该文件必须用FILEOPEN成功打开过。比较返回0表示完全匹配,否则如果是非0,则表示不完全匹配。对于固定宽度n-字节CLOB,则COMPARE以(4294967295/n)或Max(length(clob1), length(clob2))范围大小来匹配字符。语法如下:DBMS_LOB.COMPARE (

lob_1 IN BLOB,lob_2 IN BLOB,

amount IN INTEGER := 4294967295,offset_1 IN INTEGER := 1,offset_2 IN INTEGER := 1)RETURN INTEGER;

184

Page 185: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_LOB.COMPARE (lob_1 IN CLOB CHARACTER SET ANY_CS,lob_2 IN CLOB CHARACTER SET lob_1%CHARSET,amount IN INTEGER := 4294967295,offset_1 IN INTEGER := 1,

offset_2 IN INTEGER := 1)RETURN INTEGER;DBMS_LOB.COMPARE (lob_1 IN BFILE,lob_2 IN BFILE,amount IN INTEGER,offset_1 IN INTEGER := 1,offset_2 IN INTEGER := 1)RETURN INTEGER;

lob_1 LOB 比较的第一目标指示lob_2 LOB 比较的第二目标指示amount 比较的字节数(BLOBs) 或字符 (对 CLOBs) offset_1 LOB中以字节的偏移量offset_2 LOB中以字节的偏移量

返回: 整数:0 ,如果比较成功,否则返回非0 NULL,如果是下面:

– 数量 < 1– 数量 > LOBMAXSIZE

– 偏移_1 或 偏移_2 < 1 偏移_1 或 偏移_2 > LOBMAXSIZE

例子:CREATE OR REPLACE PROCEDURE Example2a IS

lob_1, lob_2 BLOB;retval INTEGER;BEGINSELECT b_col INTO lob_1 FROM lob_tableWHERE key_value = 45;SELECT b_col INTO lob_2 FROM lob_tableWHERE key_value = 54;retval := dbms_lob.compare(lob_1, lob_2, 5600, 33482,128);IF retval = 0 THEN; -- 处理比较代码

185

Page 186: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ELSE; -- 处理非比较代码END IF;END;CREATE OR REPLACE PROCEDURE Example_2b ISfil_1, fil_2 BFILE;retval INTEGER;BEGINSELECT f_lob INTO fil_1 FROM lob_table WHERE key_value = 45;SELECT f_lob INTO fil_2 FROM lob_table WHERE key_value = 54;dbms_lob.fileopen(fil_1, dbms_lob.file_readonly);dbms_lob.fileopen(fil_2, dbms_lob.file_readonly);retval := dbms_lob.compare(fil_1, fil_2, 5600,3348276, 2765612);

IF (retval = 0)THEN; -- 处理比较代码ELSE; -- 处理非比较代码END IF;dbms_lob.fileclose(fil_1);dbms_lob.fileclose(fil_2);

END;

§27.3.4 COPY过程COPY过程拷贝所有或部分的源内部LOB到目标的内部LOB上。如果目标LOB指定的偏移量超出源LOB当前数据的尾部,则超出部分用0字节或空字符填充。如果目标LOB指定的偏移量小于源LOB当前数据,则目标LOB的尾部被覆盖。语法如下:DBMS_LOB.COPY (dest_lob IN OUT NOCOPY BLOB,src_lob IN BLOB,amount IN INTEGER,dest_offset IN INTEGER := 1,src_offset IN INTEGER := 1);DBMS_LOB.COPY (dest_lob IN OUT NOCOPY CLOB CHARACTER SET ANY_CS,src_lob IN CLOB CHARACTER SET dest_lob%CHARSET,

186

Page 187: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

amount IN INTEGER,dest_offset IN INTEGER := 1,src_offset IN INTEGER := 1);

其中:dest_offset 置入目标LOB字节数或字符数。src_offset 源LOB的字节或字符数的偏移量。dest_lob 目标LOB的定位指针。src_lob 源LOB的定位指针。Amount 要复制的字节或字符数。例1.用PL/SQL拷贝部分LOB的过程:

CREATE OR REPLACE PROCEDURE copyLOB_proc ISDest_loc BLOB;Src_loc BLOB;Amount NUMBER;Dest_pos NUMBER;Src_pos NUMBER;BEGINSELECT Sound INTO Dest_loc FROM Multimedia_tabWHERE Clip_ID = 2 FOR UPDATE;/* 查询 LOB,并放入 src_lob中: */SELECT Sound INTO Src_loc FROM Multimedia_tabWHERE Clip_ID = 1;/* 打开 LOB : */DBMS_LOB.OPEN(Dest_loc, DBMS_LOB.LOB_READWRITE);DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY);/* 从源 LOB 拷贝到目标LOB位置: */DBMS_LOB.COPY(Dest_loc, Src_loc, Amount, Dest_pos, Src_pos);/* 如果已经打开LOB,则强制关闭 LOB: */DBMS_LOB.CLOSE(Dest_loc);DBMS_LOB.CLOSE(Src_loc);COMMIT;EXCEPTION

WHEN OTHERS THENDBMS_OUTPUT.PUT_LINE(’Operation failed’);END;

例2.用OCI(C语言)拷贝部分LOB的过程:

/* 选择定位 */sb4 select_lock_sound_locator_2(Lob_loc, dest_type, errhp, svchp, stmthp)OCILobLocator *Lob_loc;

187

Page 188: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ub1 dest_type; OCIError *errhp;OCISvcCtx *svchp;OCIStmt *stmthp;{char sqlstmt[150];OCIDefine *defnp1;if (dest_type == TRUE){strcpy (sqlstmt,(char *)"SELECT Sound FROM Multimedia_tabWHERE Clip_ID=2 FOR UPDATE");printf (" select destination sound locator\n");}else{strcpy(sqlstmt, (char *)"SELECT Sound FROM Multimedia_tab WHERE Clip_ID=1");printf (" select source sound locator\n");

}checkerr (errhp, OCIStmtPrepare(stmthp, errhp, (text *)sqlstmt,(ub4)strlen((char *)sqlstmt),(ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));checkerr (errhp, OCIDefineByPos(stmthp, &defnp1, errhp, (ub4) 1,(dvoid *)&Lob_loc, (sb4)0,(ub2) SQLT_BLOB,(dvoid *) 0,(ub2 *) 0, (ub2 *) 0, (ub4) OCI_DEFAULT));/* 执行 select 并返回一行记录 */checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,(CONST OCISnapshot*) 0, (OCISnapshot*) 0,(ub4) OCI_DEFAULT));return 0;}

§27.3.5 ERASE过程ERASE过程是用来删除LOB的全部或部分数据,被删除的LOB是以空格(CLOB)或0(BLOB)填充。ERASE过程的语法如下:PROCEDURE ERASE(lob_loc IN OUT BLOB,

188

Page 189: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

amount IN OUT INTEGER, offset IN INTEGER := 1);

lob_loc 要删除的LOB定位指针。Amount offset + amount 大于LOB值的长度,则该LOB全部被删除,此时amount 返回的实际删除字节数。Offset 偏移量,即删除的开始位置。例.删除部分LOB/* 本程序是删除部分LOB的包: */CREATE OR REPLACE PROCEDURE eraseLOB_proc ISLob_loc BLOB;Amount INTEGER := 3000;BEGIN/* 查询 LOB, 得到 LOB 位置: */SELECT Sound INTO lob_loc FROM Multimedia_tabWHERE Clip_ID = 1FOR UPDATE;/* 打开 LOB : */DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE);/* 删除数据: */DBMS_LOB.ERASE(Lob_loc, Amount, 2000);/* 如果已经打开LOB,则强行关闭LOB */DBMS_LOB.CLOSE (Lob_loc);COMMIT;/* 异常处理: */EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE(’Operation failed’);END;

§27.3.6 GETCHUNKSIZE函数可以用GETCHUNKSIZE 函数来得到要处理的 LOB的块的长度。语法如下:FUNCTION GETCHUNKSIZE ( lob_loc IN BLOB )RETURN INTEGER;

FUNCTION GETCHUNKSIZE ( lob_loc IN CLOB CHARACTER any_cs)RETURN INTEGER;

189

Page 190: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例。从LOB读数据:CREATE OR REPLACE PROCEDURE readLOB_proc ISLob_loc BLOB;Buffer RAW(32767);Amount BINARY_INTEGER := 32767;Position INTEGER := 1000;Chunksize INTEGER;BEGIN/* 查询 LOB: */SELECT Frame INTO Lob_locFROM Multimedia_tabWHERE Clip_ID = 1;/* 对LOB列找出 chunksize: */Chunksize := DBMS_LOB.GETCHUNKSIZE(Lob_loc);IF (Chunksize < 32767) THENAmount := (32767 / Chunksize) * Chunksize;END IF;/* 打开 LOB : */DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY);/* 从 LOB 读数据: */DBMS_LOB.READ (Lob_loc, Amount, Position, Buffer);

/* 关闭LOB: */DBMS_LOB.CLOSE (Lob_loc);END;

§27.3.7 GETLENGTH函数函数GETLENGTH可以返回 LOB的当前长度。语法如下:FUNCTION GETLENGTH ( lob_loc IN BLOB )RETURN INTEGER;

FUNCTION GETLENGTH ( lob_loc IN CLOB CHARACTER any_cs)RETURN INTEGER;例。从LOB得到长度:CREATE OR REPLACE PROCEDURE getLengthLOB_proc ISLob_loc NCLOB;

190

Page 191: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Length INTEGER;BEGIN/* 查询 LOB: */SELECT FLSub INTO Lob_loc FROM Multimedia_tabWHERE Clip_ID = 2;/* 打开 LOB: */DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY);/* 得到 LOB 长度: */length := DBMS_LOB.GETLENGTH(Lob_loc);IF length IS NULL THENDBMS_OUTPUT.PUT_LINE(’LOB is null.’);ELSEDBMS_OUTPUT.PUT_LINE(’The length is ’|| length);END IF;/* 关闭 LOB: */DBMS_LOB.CLOSE (Lob_loc);END;

§27.3.8 INSTR函数INSTR用于确定 LOB的第 n 个模式值出现的位置。语法如下:FUNCTION INSTR ( lob_loc IN BLOB , Pattern IN RAW, Offset IN INTEGER := 1, Nth IN INTEGER := 1 );FUNCTION INSTR ( lob_loc IN BFILE , Pattern IN RAW,

Offset IN INTEGER := 1, Nth IN INTEGER := 1 );

例子:CREATE OR REPLACE PROCEDURE instringTempLOB_proc IS

Lob_loc CLOB;Temp_clob CLOB;Pattern VARCHAR2(30) := ’children’; Position INTEGER := 0;Offset INTEGER := 1;Occurrence INTEGER := 1;

BEGIN

191

Page 192: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

/* 建立临时 LOB 和拷贝 CLOB 到该临时区: */DBMS_LOB.CREATETEMPORARY(Temp_clob,TRUE);SELECT Story INTO Lob_locFROM Multimedia_tabWHERE Clip_ID = 1;DBMS_LOB.OPEN(Temp_clob,DBMS_LOB.LOB_READWRITE);

DBMS_LOB.OPEN(Lob_loc,DBMS_LOB.LOB_READONLY);/* 拷贝 CLOB 到临时 CLOB: */DBMS_LOB.COPY(Temp_clob,Lob_loc,DBMS_LOB.GETLENGTH(Lob_loc),1,1);/* 查找模式 CLOB: */Position := DBMS_LOB.INSTR(Temp_clob, Pattern, Offset, Occurrence);IF Position = 0 THENDBMS_OUTPUT.PUT_LINE(’Pattern not found’);ELSEDBMS_OUTPUT.PUT_LINE(’The pattern occurs at ’|| position);END IF;DBMS_LOB.CLOSE(Lob_loc);DBMS_LOB.CLOSE(Temp_clob);/* 释放临时 LOB: */DBMS_LOB.FREETEMPORARY(Temp_clob);END;

§27.3.9 READ过程READ过程返回给定的偏移量开始的 LOB的部分数据。如果在操作中遇到了 LOB的结

尾处,则 amount 返回值为 0 。READ过程的语法如下:PROCEDURE READ ( lob_loc IN BLOB, Amount IN OUT BINARY_INTEGER, Offset IN INTEGER, Buffer OUT RAW );

PROCEDURE READ ( lob_loc IN CLOB CHARARCTER SET ANY_CS, Amount IN OUT BINARY_INTEGER, Offset IN INTEGER, Buffer OUT VARCHAR2 );

PROCEDURE READ ( lob_loc IN BFILE, Amount IN OUT BINARY_INTEGER, Offset IN INTEGER, Buffer OUT RAW );

192

Page 193: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

其中:lob_loc LOB 位置。Amount 要读的字节或字符数。Offset 读操作使用的 lob_loc 中的字节或字符数。Buffer 接收输出缓冲区的大小。例子:CREATE OR REPLACE PROCEDURE checkOutLOB_proc ISLob_loc CLOB;Buffer VARCHAR2(32767);Amount BINARY_INTEGER := 32767;Position INTEGER := 2147483647;BEGIN/* 查询 LOB */SELECT Intab.Transcript INTO Lob_locFROM TABLE(SELECT Mtab.InSeg_ntab FROM Multimedia_tab MtabWHERE Mtab.Clip_ID = 1) IntabWHERE Intab.Segment = 1;/* 打开LOB */DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY);LOOPDBMS_LOB.READ (Lob_loc, Amount, Position, Buffer);/* 处理缓冲区 */Position := Position + Amount;END LOOP;/* 关闭LOB */DBMS_LOB.CLOSE (Lob_loc);

§27.3.10 SUBSTR函数SUBSTR 函数返回给定的 LOB的部分数据。SUNSTR 函数的语法如下:

PROCEDURE SUBSTR ( lob_loc IN BLOB, Amount IN INTEGER := 32767, Offset IN INTEGER := 1 )RETURN RAW;

PROCEDURE SUBSTR ( lob_loc IN CLOB CHARACTER SET ANY_CS, Amount IN INTEGER := 32767, Offset IN INTEGER := 1 );

193

Page 194: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

RETURN VARCHAR2;

例.读LOB的一部分:CREATE OR REPLACE PROCEDURE substringLOB_proc ISLob_loc BLOB;Amount BINARY_INTEGER := 32767;Position INTEGER := 1024;Buffer RAW(32767);BEGIN/* 查询 LOB: */SELECT Sound INTO Lob_loc FROM Multimedia_tabWHERE Clip_ID = 1;/* 打开 LOB : */DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY);Buffer := DBMS_LOB.SUBSTR(Lob_loc, Amount, Position);/* 处理数据,强制关闭 LOB */DBMS_LOB.CLOSE (Lob_loc);END;/* 下面语句: 255 要读的总数,1是开始偏移量 */

SELECT DBMS_LOB.SUBSTR(Sound, 255, 1) FROM Multimedia_tab WHERE Clip_ID = 1;

§27.3.11 WRITE过程WRITE过程用于将数据写到 LOB中。它的执行结果可将 LOB的某段数据覆盖。如果指

定的偏移量超过目标 LOB的长度,则将插入空格或 0 字节来代替。WRITE过程的语法如下:PROCEDURE WRITE ( lob_loc IN OUT BLOB, Amount IN BINARY_INTEGER , Offset IN INTEGER, Buffer IN RAW );

PROCEDURE WRITE ( lob_loc IN OUT CLOB CHARACTER SET ANY_CS, Amount IN BINARY_INTEGER , Offset IN INTEGER, Buffer IN VARCHAR2 );其中:lob_loc 要写入的LOB数据。Amount 写入的字节数或字符数(应该大于或等于buffer的长度).

194

Page 195: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Offset 从1开始的偏移量(字节数或字符数)。Buffer 写目标LOB的数据。例子.检查LOB:CREATE OR REPLACE PROCEDURE checkInLOB_proc ISLob_loc CLOB;Buffer VARCHAR2(32767);Amount BINARY_INTEGER := 32767;Position INTEGER := 2147483647;i INTEGER;BEGIN/* 查询 LOB: */SELECT Intab.Transcript INTO Lob_locFROM TABLE(SELECT Mtab.InSeg_ntab FROM Multimedia_tab MtabWHERE Clip_ID = 2) IntabWHERE Intab.Segment = 1FOR UPDATE;/* 打开 LOB : */DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE)FOR i IN 1..3 LOOP/* 用数据填缓冲区以便可写 */DBMS_LOB.WRITE (Lob_loc, Amount, Position, Buffer);Position := Position + Amount;END LOOP;/* 关闭 LOB : */DBMS_LOB.CLOSE (Lob_loc);EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE(’Operation failed’);END;

§27.3.12 WRITEAPPEND过程WRITEAPPEND过程用于将数据写到 LOB的结尾处。语法如下:

PROCEDURE WRITEAPPEND ( lob_loc IN OUT BLOB, Amount IN BINARY_INTEGER , Buffer IN RAW );

PROCEDURE WRITE ( lob_loc IN OUT CLOB CHARACTER SET ANY_CS,

195

Page 196: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Amount IN BINARY_INTEGER , Buffer IN VARCHAR2 );其中:lob_loc 要写入的LOB数据。Amount 写入的字节数或字符数(应该大于或等于buffer的长度).Buffer 写目标LOB的数据。

例子.写附加数据到LOBCREATE OR REPLACE PROCEDURE lobWriteAppend_proc ISLob_loc BLOB;Buffer RAW(32767);Amount Binary_integer := 32767;BEGINSELECT Frame INTO Lob_loc FROM Multimedia_tab where Clip_ID = 1 FOR UPDATE;/* 用数据填充缓冲区... ,打开LOB */DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE);/* 从缓冲区将数据加到LOB的尾部 */DBMS_LOB.WRITEAPPEND(Lob_loc, Amount, Buffer);/* 关闭 LOB: */DBMS_LOB.CLOSE(Lob_loc);END;

§27.4临时 LOB

与前介绍的永久的 LOB不同,临时的 LOB就是指将数据建立在用户临时表空间内,这些数据仅在运行期内存在。临时 LOB的操作可以是 PL/SQL语言,也可以是OCI、PRO*C等。下面介绍 PL/SQL的一些例子。

§27.4.1 建立临时 LOB

可以用 CREATETEMPORARY 过程创建和初始化并返回 LOB的定位指针。PROCEDURE CREATETEMPORARY ( lob_loc IN OUT BLOB,

196

Page 197: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

cache IN BOOLEAN , dur IN PLS_INTEGER :=DBMS_LOB.SESSION

);

PROCEDURE CREATETEMPORARY ( lob_loc IN OUT CLOB CHARACTER SET ANY_CS,, cache IN BOOLEAN , dur IN PLS_INTEGER :=DBMS_LOB.SESSION

);

其中:lob_loc 指向临时LOB的定位指针。Cache TRUE,则LOB数据读入缓冲区。Dur 可以是call、transaction或session。例子。 创建一临时LOB:DECLAREDest_loc BLOB;Src_loc BLOB;Amount INTEGER := 4000;

BEGINSELECT Frame INTO Src_loc FROM Multimedia_tab WHERE Clip_ID = 1;/* 建立临时 LOB: */DBMS_LOB.CREATETEMPORARY(Dest_loc,TRUE);/* 拷贝正确框架Src_loc 到建立临时 LOB: */DBMS_LOB.COPY(Dest_loc,Src_loc,DBMS_LOB.GETLENGTH(Src_loc),1,1);DBMS_LOB.FREETEMPORARY(Dest_loc);END;

§27.4.2 查看临时 LOB

可以用DBMS_LOB.ISTEMPORARY 函数来返回 LOB是否是临时的。语法如下:DBMS_LOB.ISTEMPORARY (lob_loc IN BLOB)RETURN INTEGER;DBMS_LOB.ISTEMPORARY (lob_loc IN CLOB CHARACTER SET ANY_CS)RETURN INTEGER;

其中:

197

Page 198: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

lob_loc LOB的位置。返回的是布尔值。

例.看LOB是否是临时CREATE or REPLACE PROCEDURE freeTempLob_proc(Lob_loc IN OUT BLOB) ISBEGIN/* 释放临时 LOB 指针 *//* 第1个检查是确定指针是否是临时LOB */IF DBMS_LOB.ISTEMPORARY(Lob_loc) = 1 THEN/* 释放临时 LOB 指针 */DBMS_LOB.FREETEMPORARY(Lob_loc);DBMS_OUTPUT.PUT_LINE(’ temporary LOB was freed’);ELSE/* 显示错误: */DBMS_OUTPUT.PUT_LINE(’Locator passed in was not a temporary LOB locator’);END IF;END;

§27.4.3 释放临时 LOB

例子:DECLAREDest_loc BLOB;Src_loc BFILE := BFILENAME(’AUDIO_DIR’, ’Washington_audio’);Amount INTEGER := 4000;

BEGIN

DBMS_LOB.CREATETEMPORARY(Dest_loc,TRUE);

/* 强制打开 BFILE */DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY);/* 打开 LOB */DBMS_LOB.OPEN(Dest_loc,DBMS_LOB.LOB_READWRITE);DBMS_LOB.LOADFROMFILE(Dest_loc, Src_loc, Amount);/* 强制关闭 LOB */DBMS_LOB.CLOSE(Src_loc);DBMS_LOB.CLOSE(Dest_loc);/* 释放LOB */DBMS_LOB.FREETEMPORARY(Dest_loc);

198

Page 199: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END;

§27.4.4 从 BFILE中加载临时 LOB

DBMS_LOB.FREETEMPORARY (lob_loc IN OUT NOCOPY BLOB);DBMS_LOB.FREETEMPORARY (lob_loc IN OUT NOCOPY CLOB CHARACTER SET ANY_CS);其中: lob_loc 是指针。CREATE or REPLACE PROCEDURE freeTempLob_proc(Lob_loc IN OUT BLOB) ISBEGINDBMS_LOB.CREATETEMPORARY(Lob_loc,TRUE);/* 在这里使用临时 LOB 指针 ,然后释放 *//* 释放临时 LOB 指针: */DBMS_LOB.FREETEMPORARY(Lob_loc);DBMS_OUTPUT.PUT_LINE(’Temporary LOB was freed’);END;

§27.4.5 查看临时 LOB是否打开可以用DBMS_LOB.ISOPEN函数来得到临时LOB是否已经打开,语法如下:DBMS_LOB.ISOPEN (lob_loc IN BLOB)RETURN INTEGER;

DBMS_LOB.ISOPEN (lob_loc IN CLOB CHARACTER SET ANY_CS)RETURN INTEGER;

DBMS_LOB.ISOPEN (file_loc IN BFILE)RETURN INTEGER;其中:lob_loc LOB指针。File_loc 文件指针。

199

Page 200: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子。CREATE OR REPLACE PROCEDURE seeTempLOBIsOpen_proc(Lob_loc IN OUT BLOB,Retval OUT INTEGER) ISBEGIN/* 建立临时 LOB: */DBMS_LOB.CREATETEMPORARY(Lob_loc,TRUE);/* See If the LOB is open: */Retval := DBMS_LOB.ISOPEN(Lob_loc);/* 释放临时 LOB: */DBMS_LOB.FREETEMPORARY(Lob_loc);

END;

§27.4.6 显示临时 LOB数据可以用DBMS_LOB.LOADFROMFILE过程来显示LOB数据,它的语法如下:DBMS_LOB.LOADFROMFILE (dest_lob IN OUT NOCOPY BLOB,src_file IN BFILE,amount IN INTEGER,dest_offset IN INTEGER := 1,src_offset IN INTEGER := 1);

DBMS_LOB.LOADFROMFILE(dest_lob IN OUT NOCOPY CLOB CHARACTER SET ANY_CS,

src_file IN BFILE,amount IN INTEGER,

dest_offset IN INTEGER := 1,src_offset IN INTEGER := 1);

其中:dest_lob 要加载的目标LOB 指针。src_file 加载的源BFILE指针。amount 加载的 BFILE的字节数。dest_offset 目标 LOB 的字节或字符数(开始: 1)。src_offset 从开始起的源BFILE 字节数。

例子。DECLARE

200

Page 201: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Dest_loc BLOB;Src_loc BFILE := BFILENAME(’AUDIO_DIR’, ’Washington_audio’);Amount INTEGER := 128;Bbuf RAW(128);Position INTEGER :=1;BEGINDBMS_LOB.CREATETEMPORARY(Dest_loc,TRUE);/* 强行打开 FILE : */DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY);/* 打开 LOB : */DBMS_LOB.OPEN(Dest_loc,DBMS_LOB.LOB_READWRITE);DBMS_LOB.LOADFROMFILE(Dest_loc,Src_loc,Amount);LOOPDBMS_LOB.READ (Dest_loc, Amount, Position, Bbuf);/* 显示缓冲区内容 */DBMS_OUTPUT.PUT_LINE(’Result :’|| utl_raw.cast_to_varchar2(Bbuf));Position := Position + Amount;END LOOP;EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE(’End of data loaded into temp LOB’);DBMS_LOB.CLOSE(Dest_loc);DBMS_LOB.FREETEMPORARY(Dest_loc);/* 关闭文件: */DBMS_LOB.CLOSE(Src_loc);END;

§27.4.7 从临时 LOB读数据DBMS_LOB.READ过程用于读临时LOB的数据,它的语法如下:DBMS_LOB.READ (lob_loc IN BLOB,amount IN OUT NOCOPY BINARY_INTEGER,offset IN INTEGER,buffer OUT RAW);

DBMS_LOB.READ (lob_loc IN CLOB CHARACTER SET ANY_CS,amount IN OUT NOCOPY BINARY_INTEGER,offset IN INTEGER,buffer OUT VARCHAR2 CHARACTER SET lob_loc%CHARSET);

201

Page 202: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_LOB.READ (lob_loc IN BFILE,amount IN OUT NOCOPY BINARY_INTEGER,offset IN INTEGER,buffer OUT RAW);

其中:lob_loc 要读的LOB 指针。amount 要读的字节数 (for BLOBs) 字符数(for CLOBs) 。offset 偏移字节数 (for BLOBs) 字符数(for CLOBs) 。buffer 输出缓冲区大小。DECLAREDest_loc BLOB;Src_loc BFILE := BFILENAME(’AUDIO_DIR’, ’Washington_audio’);Amount INTEGER := 4000;Bbuf RAW(32767);Position INTEGER :=1;BEGINDBMS_LOB.CREATETEMPORARY(Dest_loc,TRUE);/* 强行打开 FILE : */DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY);/* 打开 LOB : */

DBMS_LOB.LOADFROMFILE(Dest_loc, Src_loc, Amount);DBMS_LOB.READ (Dest_loc, Amount, Position, Bbuf);/* 强行关闭 LOB : */DBMS_LOB.CLOSE(Src_loc);

§27.4.8 从临时 LOB读部分数据可以用 SUBSTR过程来实现对临时 LOB的模式操作。其语法见前面。/* 假定用户在AUDIO_DIR别名上有文件 ’Washington_audio’ */CREATE or REPLACE PROCEDURE substringTempLOB_proc ISDest_loc BLOB;Src_loc BFILE := BFILENAME(’AUDIO_DIR’, ’Washington_audio’);Amount INTEGER := 32767;Bbuf RAW(32767);Position INTEGER :=128;BEGIN

202

Page 203: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_LOB.CREATETEMPORARY(Dest_loc,TRUE);/* 强行打开 FILE文件: */DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY);/* 选择打开 LOB */DBMS_LOB.OPEN(Dest_loc,DBMS_LOB.LOB_READWRITE);DBMS_LOB.LOADFROMFILE(Dest_loc, Src_loc, Amount);Bbuf := DBMS_LOB.SUBSTR(Dest_loc, Amount, Position);/* 强行关闭 LOB : */DBMS_LOB.CLOSE(Src_loc);DBMS_LOB.CLOSE(Dest_loc);

END;

§27.4.9 比较两个临时 LOB数据DBMS_LOB.CREATETEMPORARY过程用来比较两个 LOB的数据,看下面例子。

CREATE OR REPLACE PROCEDURE compareTwoTmpPerLOBs_proc ISLob_loc1 BLOB;Lob_loc2 BLOB;Temp_loc BLOB;Amount INTEGER := 32767;Retval INTEGER;BEGIN/* 选择 LOB: */SELECT Frame INTO Lob_loc1 FROM Multimedia_tabWHERE Clip_ID = 1;SELECT Frame INTO Lob_loc2 FROM Multimedia_tabWHERE Clip_ID = 2;/* 拷贝框架到临时 LOB 并覆盖不同的部分 *//* 比较前要做的工作 */DBMS_LOB.CREATETEMPORARY(Temp_loc, TRUE);DBMS_LOB.OPEN(Temp_loc, DBMS_LOB.LOB_READWRITE);DBMS_LOB.OPEN(Lob_loc1, DBMS_LOB.LOB_READONLY);DBMS_LOB.OPEN(Lob_loc2, DBMS_LOB.LOB_READONLY);/* 拷贝固定 LOB 到临时 LOB: */DBMS_LOB.COPY(Temp_loc,Lob_loc2,DBMS_LOB.GETLENGTH(Lob_loc2),1,1);/* 在比较前,转换临时 LOB */retval := DBMS_LOB.COMPARE(Lob_loc1, Temp_loc, Amount, 1, 1);IF retval = 0 THENDBMS_OUTPUT.PUT_LINE(’Processing for equal frames’);ELSE

203

Page 204: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_OUTPUT.PUT_LINE(’Processing for non-equal frames’);END IF;DBMS_LOB.CLOSE(Temp_loc);DBMS_LOB.CLOSE(Lob_loc1);DBMS_LOB.CLOSE(Lob_loc2);/* 释放临时 LOB */DBMS_LOB.FREETEMPORARY(Temp_loc);END;

§27.4.10 查看临时 LOB模式的存在CREATE OR REPLACE PROCEDURE instringTempLOB_proc ISLob_loc CLOB;Temp_clob CLOB;Pattern VARCHAR2(30) := ’children’; Position INTEGER := 0;Offset INTEGER := 1;Occurrence INTEGER := 1;BEGIN/* 建立临时 LOB 和拷贝 CLOB */DBMS_LOB.CREATETEMPORARY(Temp_clob,TRUE);SELECT Story INTO Lob_locFROM Multimedia_tabWHERE Clip_ID = 1;DBMS_LOB.OPEN(Temp_clob,DBMS_LOB.LOB_READWRITE);DBMS_LOB.OPEN(Lob_loc,DBMS_LOB.LOB_READONLY);/* 拷贝CLOB到临时 CLOB: */DBMS_LOB.COPY(Temp_clob,Lob_loc,DBMS_LOB.GETLENGTH(Lob_loc),1,1);/* 在临时CLOB找模式 */Position := DBMS_LOB.INSTR(Temp_clob, Pattern, Offset, Occurrence);IF Position = 0 THENDBMS_OUTPUT.PUT_LINE(’Pattern not found’);

ELSEDBMS_OUTPUT.PUT_LINE(’The pattern occurs at ’|| position);END IF;DBMS_LOB.CLOSE(Lob_loc);DBMS_LOB.CLOSE(Temp_clob);/*释放临时LOB: */DBMS_LOB.FREETEMPORARY(Temp_clob);END;

204

Page 205: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§27.4.11 得到临时 LOB的长度CREATE OR REPLACE PROCEDURE getLengthTempCLOB_proc ISLength INTEGER;tlob CLOB;bufc VARCHAR2(8);Amount NUMBER;pos NUMBER;Src_loc BFILE := BFILENAME(’AUDIO_DIR’, ’Washington_audio’);BEGINDBMS_LOB.CREATETEMPORARY(tlob,TRUE);/* 打开LOB */DBMS_LOB.OPEN(tlob,DBMS_LOB.LOB_READWRITE);

DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY);Amount := 32767;DBMS_LOB.LOADFROMFILE(tlob, Src_loc, Amount);/* 得到LOB长度 */length := DBMS_LOB.GETLENGTH(tlob);IF length = 0 THENDBMS_OUTPUT.PUT_LINE(’LOB is empty.’);ELSEDBMS_OUTPUT.PUT_LINE(’The length is ’ || length);END IF;/* 关闭已经打开的LOB */DBMS_LOB.CLOSE(tlob);DBMS_LOB.CLOSE(Src_loc);/* 释放LOB  */DBMS_LOB.FREETEMPORARY(tlob);END;

§27.4.12 拷贝部分临时 LOB数据/* 注意:存储过程 copyTempLOB_proc 不是DBMS_LOB 包的一部分 */CREATE OR REPLACE PROCEDURE copyTempLOB_proc ISDest_pos NUMBER;Src_pos NUMBER;Dest_loc BLOB;Dest_loc2 BLOB;

205

Page 206: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Src_loc BFILE := BFILENAME(’AUDIO_DIR’, ’Washington_audio’);Amount INTEGER := 32767;BEGINDBMS_LOB.CREATETEMPORARY(Dest_loc2,TRUE);DBMS_LOB.CREATETEMPORARY(Dest_loc,TRUE);/* 强制打开 FILE  */DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY);/* 打开临时 LOB   */DBMS_LOB.OPEN(Dest_loc,DBMS_LOB.LOB_READWRITE);DBMS_LOB.OPEN(Dest_loc2,DBMS_LOB.LOB_READWRITE);DBMS_LOB.LOADFROMFILE(Dest_loc, Src_loc, Amount);/* 设置 目标临时 LOB的 Dest_pos  位置 */

/* 从源拷贝LOB到目标位置*//* 设置希望拷贝的数量 */Amount := 328;Dest_pos := 1000;Src_pos := 1000;

DBMS_LOB.COPY(Dest_loc2,Dest_loc, Amount, Dest_pos, Src_pos);COMMIT;EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE(’Operation failed’);DBMS_LOB.CLOSE(Dest_loc);DBMS_LOB.CLOSE(Dest_loc2);DBMS_LOB.CLOSE(Src_loc);DBMS_LOB.FREETEMPORARY(Dest_loc);DBMS_LOB.FREETEMPORARY(Dest_loc2);END;

§27.4.13 为临时 LOB拷贝位置

/* 注意:存储过程 copyTempLOBLocator_proc 不是DBMS_LOB 包的一部分 */

CREATE OR REPLACE PROCEDURE copyTempLOBLocator_proc(Lob_loc1 IN OUT CLOB, Lob_loc2 IN OUT CLOB) ISbufp VARCHAR2(4);Amount NUMBER := 32767;Src_loc BFILE := BFILENAME(’AUDIO_DIR’, ’Washington_audio’);

206

Page 207: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

BEGINDBMS_LOB.CREATETEMPORARY(Lob_loc1,TRUE);DBMS_LOB.CREATETEMPORARY(Lob_loc2,TRUE);

/* 强行打开 */DBMS_LOB.OPEN(Src_loc,DBMS_LOB.LOB_READONLY);/* 打开LOB */DBMS_LOB.OPEN(Lob_loc1,DBMS_LOB.LOB_READWRITE);DBMS_LOB.OPEN(Lob_loc2,DBMS_LOB.LOB_READWRITE);DBMS_LOB.LOADFROMFILE(Lob_loc1,Src_loc,Amount);/* 分配 Lob_loc1给Lob_loc2 以建立一个拷贝值 */

Lob_loc2 := Lob_loc1;

/* 强行关闭 LOB */DBMS_LOB.CLOSE (Src_loc);DBMS_LOB.CLOSE (Lob_loc1);DBMS_LOB.CLOSE (Lob_loc2);DBMS_LOB.FREETEMPORARY(Lob_loc1);DBMS_LOB.FREETEMPORARY(Lob_loc2);END;

§27.4.14 加临时 LOB到另外的 LOB

/* 注意:存储过程 appendTempLOB_proc 不是DBMS_LOB 包的一部分 */CREATE OR REPLACE PROCEDURE appendTempLOB_proc ISDest_loc2 CLOB;Dest_loc CLOB;Amount NUMBER;Src_loc BFILE := BFILENAME(’AUDIO_DIR’, ’Washington_audio’);BEGINDBMS_LOB.CREATETEMPORARY(Dest_loc,TRUE);DBMS_LOB.CREATETEMPORARY(Dest_loc2,TRUE);DBMS_LOB.OPEN(Dest_loc,DBMS_LOB.LOB_READWRITE);DBMS_LOB.OPEN(Dest_loc2,DBMS_LOB.LOB_READWRITE);DBMS_LOB.OPEN(Src_loc,DBMS_LOB.LOB_READWRITE);Amount := 32767;DBMS_LOB.LOADFROMFILE(Dest_loc, Src_loc, Amount);DBMS_LOB.LOADFROMFILE(Dest_loc2, Src_loc, Amount);DBMS_LOB.APPEND(Dest_loc, Dest_loc2);

207

Page 208: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_LOB.CLOSE(Dest_loc);DBMS_LOB.CLOSE(Dest_loc2);DBMS_LOB.CLOSE(Src_loc);DBMS_LOB.FREETEMPORARY(Dest_loc);DBMS_LOB.FREETEMPORARY(Dest_loc2);END;

§27.4.15 写追加到临时 LOB

/* 注意:存储过程writeAppendTempLOB_proc不是DBMS_LOB 包的一部分 */CREATE OR REPLACE PROCEDURE writeAppendTempLOB_proc ISLob_loc BLOB;Buffer RAW(32767);Src_loc BFILE := BFILENAME(’AUDIO_DIR’, ’Washington_audio’);Amount Binary_integer := 32767;Position Binary_integer := 128;BEGINDBMS_LOB.CREATETEMPORARY(Lob_loc,TRUE);/* 打开 LOB */DBMS_LOB.OPEN(Lob_loc,DBMS_LOB.LOB_READWRITE);/* 强行打开 FILE  */DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY);/* 用 数据填缓冲区 */DBMS_LOB.LOADFROMFILE (Lob_loc,Src_loc, Amount);/* 从缓冲区加数据到LOB的尾部 */DBMS_LOB.WRITEAPPEND(Lob_loc, Amount, Buffer);DBMS_LOB.CLOSE(Src_loc);DBMS_LOB.CLOSE(Lob_loc);DBMS_LOB.FREETEMPORARY(Lob_loc);END;

§27.4.16 写数据到临时 LOB

/* 注意:存储过程writeDataToTempLOB_proc不是DBMS_LOB 包的一部分 */

208

Page 209: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE or REPLACE PROCEDURE writeDataToTempLOB_proc ISLob_loc CLOB;Buffer VARCHAR2(26);Amount BINARY_INTEGER := 26;Position INTEGER := 1;i INTEGER;BEGINDBMS_LOB.CREATETEMPORARY(Lob_loc,TRUE);

DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE);

/* 用数据填缓冲区以写到 LOB: */Buffer := ’abcdefghijklmnopqrstuvwxyz’;FOR i IN 1..3 LOOPDBMS_LOB.WRITE (Lob_loc, Amount, Position, Buffer);/* 用更多数据填缓冲区以写到 LOB: */Position := Position + Amount;END LOOP;/* 强行关闭 LOB   */DBMS_LOB.CLOSE (Lob_loc);DBMS_LOB.FREETEMPORARY(Lob_loc);END;

§27.4.17 修理临时 LOB数据/* 注意:存储过程 trimTempLOB_proc 不是DBMS_LOB 包的一部分 */

CREATE OR REPLACE PROCEDURE trimTempLOB_proc IS

Lob_loc CLOB;Amount number;Src_loc BFILE := BFILENAME(’AUDIO_DIR’, ’Washington_audio’);TrimAmount number := 100;BEGIN/* 建立临时 LOB: */DBMS_LOB.CREATETEMPORARY(Lob_loc,TRUE);/* 打开 LOB  */DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE);/* 强行打开文件 */DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY);

Amount := 32767;

209

Page 210: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_LOB.LOADFROMFILE(Lob_loc, Src_loc, Amount);DBMS_LOB.TRIM(Lob_loc,TrimAmount);

DBMS_LOB.CLOSE (Lob_loc);DBMS_LOB.CLOSE(Src_loc);DBMS_LOB.FREETEMPORARY(Lob_loc);COMMIT;EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE(’Operation failed’);END;

§27.4.18 删除临时 LOB数据/* 注意:存储过程 eraseTempLOB_proc 不是DBMS_LOB 包的一部分 */

CREATE OR REPLACE PROCEDURE trimTempLOB_proc ISLob_loc CLOB;amt number;Src_loc BFILE := BFILENAME(’AUDIO_DIR’, ’Washington_audio’);Amount INTEGER := 32767;BEGIN/* 建立临时 LOB: */DBMS_LOB.CREATETEMPORARY(Lob_loc,TRUE);/* 打开LOB   */DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READWRITE);

Amount := 32767;DBMS_LOB.LOADFROMFILE(Lob_loc, Src_loc, Amount);/* 删除 LOB 数据*/amt := 3000;DBMS_LOB.ERASE(Lob_loc, amt, 2);

DBMS_LOB.CLOSE (Lob_loc);DBMS_LOB.CLOSE(Src_loc);DBMS_LOB.FREETEMPORARY(Lob_loc);COMMIT;EXCEPTIONWHEN OTHERS THEN

DBMS_OUTPUT.PUT_LINE(’Operation failed’);END;

210

Page 211: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§27.5外部 LOB (BFILE)

外边 LOB 指的是 BFILE类型,它的使用方式与 CLOB等不同,BFILE类型对象只存放文件的路径和文件名,而不存放具体的文件内容。

§27.5.1 BFILE目录指定

可以用CREATE DIRECTORY命令来实现建立目录,如:在UNIX 环境:CREATE DIRECTORY "Mary_Dir" AS '/usr/home/mary';

在NT环境:CREATE DIRECTORY "big_cap_dir" AS "g:\data\source";CREATE DIRECTORY "small_cap_dir" AS "G:\DATA\SOURCE";

§27.5.2 建立包括 BFILE列的表在建立前,要登录到 system帐户并执行下面的脚本:

CONNECT system/manager;DROP USER samp CASCADE;DROP DIRECTORY AUDIO_DIR;DROP DIRECTORY FRAME_DIR;DROP DIRECTORY PHOTO_DIR;CREATE USER samp identified by samp;GRANT CONNECT, RESOURCE to samp;CREATE DIRECTORY AUDIO_DIR AS ’/tmp/’;CREATE DIRECTORY FRAME_DIR AS ’/tmp/’;CREATE DIRECTORY PHOTO_DIR AS ’/tmp/’;GRANT READ ON DIRECTORY AUDIO_DIR to samp;GRANT READ ON DIRECTORY FRAME_DIR to samp;GRANT READ ON DIRECTORY PHOTO_DIR to samp;CREATE TABLE VoiceoverLib_tab of Voiced_typ( Script DEFAULT EMPTY_CLOB(),

211

Page 212: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CONSTRAINT TakeLib CHECK (Take IS NOT NULL),Recording DEFAULT NULL);

连接到新建的帐户,执行建立带LOB的表结构命令:CONNECT samp/sampCREATE TABLE a_table (blob_col BLOB);CREATE TYPE Voiced_typ AS OBJECT( Originator VARCHAR2(30),

Script CLOB,Actor VARCHAR2(30),Take NUMBER,Recording BFILE );CREATE TYPE InSeg_typ AS OBJECT( Segment NUMBER,Interview_Date DATE,Interviewer VARCHAR2(30),Interviewee VARCHAR2(30),Recording BFILE,Transcript CLOB );CREATE TYPE InSeg_tab AS TABLE of InSeg_typ;CREATE TYPE Map_typ AS OBJECT( Region VARCHAR2(30),NW NUMBER,NE NUMBER,SW NUMBER,SE NUMBER,Drawing BLOB,Aerial BFILE);CREATE TABLE Map_Libtab of Map_typ;CREATE TABLE Voiceover_tab of Voiced_typ( Script DEFAULT EMPTY_CLOB(),CONSTRAINT Take CHECK (Take IS NOT NULL),Recording DEFAULT NULL);

可直接用DDL语句建立表:CREATE TABLE Multimedia_tab

( Clip_ID NUMBER NOT NULL,Story CLOB default EMPTY_CLOB(),FLSub NCLOB default EMPTY_CLOB(),Photo BFILE default NULL,

212

Page 213: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Frame BLOB default EMPTY_BLOB(),Sound BLOB default EMPTY_BLOB(),Voiced_ref REF Voiced_typ,InSeg_ntab InSeg_tab,Music BFILE default NULL,Map_obj Map_typ) NESTED TABLE InSeg_ntab STORE AS InSeg_nestedtab;

§27.5.3 用 BFILENAME()插入数据/* 注:这与插入内部的LOB一样,但采用BFILENAME()函数来实现初始化一个BFULE列 */INSERT INTO Multimedia_tab VALUES (1, EMPTY_CLOB(), EMPTY_CLOB(),FILENAME(’PHOTO_DIR’, ’LINCOLN_PHOTO’),EMPTY_BLOB(), EMPTY_BLOB(),VOICED_TYP(’Abraham Lincoln’, EMPTY_CLOB(),’James Earl Jones’, 1, NULL),NULL, BFILENAME(’AUDIO_DIR’,’LINCOLN_AUDIO’),MAP_TYP(’Gettysburg’, 23, 34, 45, 56,EMPTY_BLOB(), NULL));

§27.5.4 从另外表选择 BFILE插入数据INSERT INTO Voiceover_tab(SELECT * from VoiceoverLib_tabWHERE Take = 12345);

§27.5.5 用初始化 BFILE位置来插入数据 BFILE行DECLARE/* 初始化 BFILE 位置 */Lob_loc BFILE := BFILENAME(’PHOTO_DIR’, ’Washington_photo’);BEGININSERT INTO Multimedia_tab (Clip_ID, Photo) VALUES (3, Lob_loc);COMMIT;END;

213

Page 214: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§27.5.6 动态加载数据 BFILE的表

例1:

控制文件:LOAD DATAINFILE sample9.datINTO TABLE Multimedia_tabFIELDS TERMINATED BY ’,’(Clip_ID INTEGER EXTERNAL(5),FileName FILLER CHAR(30),Photo BFILE(CONSTANT "DETECTIVE_PHOTO", FileName))

数据文件:007, JamesBond.jpeg,008, SherlockHolmes.jpeg,009, MissMarple.jpeg,

例2.文件名和目录是动态。

控制文件:

LOAD DATAINFILE sample10.datINTO TABLE Multimedia_tabreplaceFIELDS TERMINATED BY ','

(Clip_ID INTEGER EXTERNAL(5),Photo BFILE (DirName, FileName),FileName FILLER CHAR(30),DirName FILLER CHAR(30))

数据文件:

007,JamesBond.jpeg,DETECTIVE_PHOTO,008,SherlockHolmes.jpeg,DETECTIVE_PHOTO,009,MissMarple.jpeg,PHOTO_DIR,

214

Page 215: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§27.5.7 用 BFILE数据来加载 LOB数据/* 注:本存储过程loadLOBFromBFILE_proc不是 DBMS_LOB包的一部分 */

CREATE OR REPLACE PROCEDURE loadLOBFromBFILE_proc ISDest_loc BLOB;Src_loc BFILE := BFILENAME(’FRAME_DIR’, ’Washington_frame’);Amount INTEGER := 4000;BEGINSELECT Frame INTO Dest_loc FROM Multimedia_tabWHERE Clip_ID = 3FOR UPDATE;/* 强行打开 LOB */DBMS_LOB.OPEN(Src_loc, DBMS_LOB.LOB_READONLY);/* 打开 LOB */DBMS_LOB.OPEN(Dest_loc, DBMS_LOB.LOB_READWRITE);DBMS_LOB.LOADFROMFILE(Dest_loc, Src_loc, Amount);/* 强行关闭 LOB */DBMS_LOB.CLOSE(Dest_loc);DBMS_LOB.CLOSE(Src_loc);COMMIT;END;

§27.5.8 用 FILEOPEN打开 BFILE

/* 注:本存储过程openBFILE_procOne不是 DBMS_LOB包的一部分 */CREATE OR REPLACE PROCEDURE openBFILE_procOne ISLob_loc BFILE := BFILENAME(’PHOTO_DIR’, ’Lincoln_photo’);BEGIN/* 打开 BFILE */DBMS_LOB.FILEOPEN (Lob_loc, DBMS_LOB.FILE_READONLY);/* ... 做某些处理 */DBMS_LOB.FILECLOSE(Lob_loc);END;

215

Page 216: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§27.5.9 用OPEN打开 BFILE

/* 注:本存储过程openBFILE_procTwo不是 DBMS_LOB包的一部分 */CREATE OR REPLACE PROCEDURE openBFILE_procTwo ISLob_loc BFILE := BFILENAME(’PHOTO_DIR’, ’Lincoln_photo’);BEGIN/* 打开BFILE: */DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY);/* ... 进行其他处理*/DBMS_LOB.CLOSE(Lob_loc);END;

§27.5.10 用 FILEISOPEN看 BFILE是否打开/* 注:本存储过程seeIfOpenBFILE_procOne不是 DBMS_LOB包的一部分 */

CREATE OR REPLACE PROCEDURE seeIfOpenBFILE_procOne ISLob_loc BFILE;RetVal INTEGER;BEGIN/* 选择 LOB,初始化BFILE位置 */SELECT Music INTO Lob_loc FROM Multimedia_tabWHERE Clip_ID = 3;RetVal := DBMS_LOB.FILEISOPEN(Lob_loc);IF (RetVal = 1)THEN

§27.5.11 用 ISOPEN看 BFILE是否打开/* 注:本存储过程seeIfOpenBFILE_procTwo不是 DBMS_LOB包的一部分 */CREATE OR REPLACE PROCEDURE seeIfOpenBFILE_procTwo ISLob_loc BFILE;RetVal INTEGER;

BEGIN

216

Page 217: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

/* 选择 LOB,初始化BFILE位置 */SELECT Music INTO Lob_loc FROM Multimedia_tabWHERE Clip_ID = 3;RetVal := DBMS_LOB.ISOPEN(Lob_loc);IF (RetVal = 1)THEN

DBMS_OUTPUT.PUT_LINE(’File is open’);ELSEDBMS_OUTPUT.PUT_LINE(’File is not open’);END IF;EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE(’Operation failed’);END;

§27.5.12 显示 BFILE

/* 注:本存储过程displayBFILE_proc不是 DBMS_LOB包的一部分 */

CREATE OR REPLACE PROCEDURE displayBFILE_proc ISLob_loc BFILE;Buffer RAW(1024);Amount BINARY_INTEGER := 1024;Position INTEGER := 1;BEGIN/* 查询 LOB */SELECT Music INTO Lob_locFROM Multimedia_tab WHERE Clip_ID = 1;/* 打开 BFILE */DBMS_LOB.OPEN (Lob_loc, DBMS_LOB.LOB_READONLY);LOOPDBMS_LOB.READ (Lob_loc, Amount, Position, Buffer);/* 显示缓冲区内容 */DBMS_OUTPUT.PUT_LINE(utl_raw.cast_to_varchar2(Buffer));Position := Position + Amount;END LOOP;/* 关闭 BFILE */DBMS_LOB.CLOSE (Lob_loc);EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE(’End of data’);

217

Page 218: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END;

§27.5.13 从 BFILE中读数据/* 注:本存储过程readBFILE_proc不是 DBMS_LOB包的一部分 */

CREATE OR REPLACE PROCEDURE readBFILE_proc ISLob_loc BFILE := BFILENAME(’PHOTO_DIR’, ’Jefferson_photo’);Amount INTEGER := 32767;Position INTEGER := 1;Buffer RAW(32767);BEGIN/* 查询 LOB */SELECT Photo INTO Lob_loc FROM Multimedia_tabWHERE Clip_ID = 3;/* 打开BFIL */DBMS_LOB.OPEN(Lob_loc, DBMS_LOB.LOB_READONLY);/* 读数据 */DBMS_LOB.READ(Lob_loc, Amount, Position, Buffer);/* 关闭 BFILE */DBMS_LOB.CLOSE(Lob_loc);END;

§27.5.14 读部分 BFILE

/* 注:本存储过程substringBFILE_proc不是 DBMS_LOB包的一部分 */

CREATE OR REPLACE PROCEDURE substringBFILE_proc ISLob_loc BFILE;Position INTEGER := 1;Buffer RAW(32767);BEGIN/* 查询 LOB */SELECT Mtab.Voiced_ref.Recording INTO Lob_loc FROM Multimedia_tab MtabWHERE Mtab.Clip_ID = 3;/* 打开BFILE */DBMS_LOB.OPEN(Lob_loc, DBMS_LOB.LOB_READONLY);Buffer := DBMS_LOB.SUBSTR(Lob_loc, 255, Position);

218

Page 219: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

/* 关闭 BFILE */DBMS_LOB.CLOSE(Lob_loc);END;

§27.5.15 比较 BFILE

/* 注:本存储过程instringBFILE_proc不是 DBMS_LOB包的一部分 */CREATE OR REPLACE PROCEDURE instringBFILE_proc ISLob_loc BFILE;Pattern RAW(32767);Position INTEGER;BEGIN/* 查询LOB */SELECT Intab.Recording INTO Lob_locFROM THE(SELECT Mtab.InSeg_ntab FROM Multimedia_tab MtabWHERE Clip_ID = 3) IntabWHERE Segment = 1;/* 打开 BFILE */DBMS_LOB.OPEN(Lob_loc, DBMS_LOB.LOB_READONLY);/* 初始化模式,从BFILE中找出第2个出现的模式 */Position := DBMS_LOB.INSTR(Lob_loc, Pattern, 1, 2);/* 关闭 BFILE */DBMS_LOB.CLOSE(Lob_loc);END;

§27.5.16 判断 BFILE是否存在模式

/* 注:本存储过程compareBFILEs_proc 不是 DBMS_LOB包的一部分 */

CREATE OR REPLACE PROCEDURE compareBFILEs_proc IS/* Initialize the BFILE locator: */Lob_loc1 BFILE := BFILENAME(’PHOTO_DIR’, ’RooseveltFDR_photo’);Lob_loc2 BFILE;Retval INTEGER;BEGIN/* 选择 LOB */SELECT Photo INTO Lob_loc2 FROM Multimedia_tab

219

Page 220: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

WHERE Clip_ID = 3;/* 打开 BFILE */DBMS_LOB.OPEN(Lob_loc1, DBMS_LOB.LOB_READONLY);DBMS_LOB.OPEN(Lob_loc2, DBMS_LOB.LOB_READONLY);Retval := DBMS_LOB.COMPARE(Lob_loc2, Lob_loc1, DBMS_LOB.LOBMAXSIZE, 1, 1);/* 关闭BFILE */DBMS_LOB.CLOSE(Lob_loc1);DBMS_LOB.CLOSE(Lob_loc2);END;

§27.5.17 判断 BFILE是否存在

/* 注:本存储过程seeIfExistsBFILE_proc不是 DBMS_LOB包的一部分 */CREATE OR REPLACE PROCEDURE seeIfExistsBFILE_proc ISLob_loc BFILE;BEGIN/* 查询 LOB: */SELECT Intab.Recording INTO Lob_locFROM THE(SELECT Mtab.InSeg_ntab FROM Multimedia_tab MtabWHERE Mtab.Clip_ID = 3) IntabWHERE Intab.Segment = 1;/* 检查 BFILE 存在 */IF (DBMS_LOB.FILEEXISTS(Lob_loc) != 0)THENDBMS_OUTPUT.PUT_LINE(’Processing given that the BFILE exists’);ELSEDBMS_OUTPUT.PUT_LINE(’Processing given that the BFILE does not exist’);END IF;EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE(’Operation failed’);END;

§27.5.18 得到 BFILE长度/* 注:本存储过程getLengthBFILE_proc不是 DBMS_LOB包的一部分 */CREATE OR REPLACE PROCEDURE getLengthBFILE_proc IS

220

Page 221: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Lob_loc BFILE;Length INTEGER;BEGIN/* 选择LOB来初始化 BFILE 位置 */SELECT Mtab.Voiced_ref.Recording INTO Lob_loc FROM Multimedia_tab MtabWHERE Mtab.Clip_ID = 3;/* 打开 BFILE: */DBMS_LOB.OPEN(Lob_loc, DBMS_LOB.LOB_READONLY);/* 得到LOB: */Length := DBMS_LOB.GETLENGTH(Lob_loc);IF Length IS NULL THENDBMS_OUTPUT.PUT_LINE(’BFILE is null.’);ELSEDBMS_OUTPUT.PUT_LINE(’The length is ’ || length);END IF;/* 关闭 BFILE: */DBMS_LOB.CLOSE(Lob_loc);END;

§27.5.19 拷贝 BFILE的 LOB位置/* 注:本存储过程BFILEAssign_proc不是 DBMS_LOB包的一部分 */CREATE OR REPLACE PROCEDURE BFILEAssign_proc ISLob_loc1 BFILE;Lob_loc2 BFILE;BEGINSELECT Photo INTO Lob_loc1 FROM Multimedia_tab WHERE Clip_ID = 3 FOR UPDATE;/* 分配 Lob_loc1 给 Lob_loc2 使它们能引用相同的操作系统文件 */Lob_loc2 := Lob_loc1;/* 现在可以从Lob_loc1 或Lob_loc2来读 bfile */END;

§27.5.20 得到目录别名和文件名字

CREATE OR REPLACE PROCEDURE getNameBFILE_proc IS

221

Page 222: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Lob_loc BFILE;DirAlias_name VARCHAR2(30);File_name VARCHAR2(40);BEGINSELECT Music INTO Lob_loc FROM Multimedia_tab WHERE Clip_ID = 3;DBMS_LOB.FILEGETNAME(Lob_loc, DirAlias_name, File_name);/* 在目录和别名上进行一些基本处理 */END;

§27.5.21 用初始化BFILE位置更新BFILE

/* 注:本存储过程updateUseBindVariable_proc不是 DBMS_LOB包的一部分 */

CREATE OR REPLACE PROCEDURE updateUseBindVariable_proc (Lob_loc BFILE) ISBEGINUPDATE Multimedia_tab SET Photo = Lob_loc WHERE Clip_ID = 3;END;DECLARELob_loc BFILE;BEGINSELECT Photo INTO Lob_locFROM Multimedia_tabWHERE Clip_ID = 1;updateUseBindVariable_proc (Lob_loc);COMMIT;END;

§27.5.22 用 FILECLOSE关闭 BFILE

/* 注:本存储过程closeBFILE_procOne不是 DBMS_LOB包的一部分 */CREATE OR REPLACE PROCEDURE closeBFILE_procOne ISLob_loc BFILE := BFILENAME(’PHOTO_DIR’, ’Lincoln_photo’);BEGINDBMS_LOB.FILEOPEN(Lob_loc, DBMS_LOB.FILE_READONLY);/*…做相应处理 */DBMS_LOB.FILECLOSE(Lob_loc);END;

222

Page 223: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§27.5.23 用CLOSE关闭 BFILE

/* 注:本存储过程closeBFILE_procTwo不是 DBMS_LOB包的一部分 */

CREATE OR REPLACE PROCEDURE closeBFILE_procTwo ISLob_loc BFILE := BFILENAME(’PHOTO_DIR’, ’Lincoln_photo’);BEGINDBMS_LOB.OPEN(Lob_loc, DBMS_LOB.LOB_READONLY);/* ...进行相应处理. */DBMS_LOB.CLOSE(Lob_loc);END;

§27.5.24 用CLOSEALL关闭所有 BFILE

/* 注:本存储过程closeAllOpenFilesBFILE_proc不是 DBMS_LOB包的一部分 */CREATE OR REPLACE PROCEDURE closeAllOpenFilesBFILE_proc ISBEGIN/* 关闭所有 BFILE文件 */DBMS_LOB.FILECLOSEALL;END;

§27.5.25 用DELETE等删除 BFILE数据DELETEDELETE FROM Multimedia_tabWHERE Clip_ID = 3;DROPDROP TABLE Multimedia_tab;TRUNCATETRUNCATE TABLE Multimedia_tab;

223

Page 224: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§27.6 使用 SQL*loader加载 LOB

下面给出用SQL*Loader加载LOB的一些例子,供大家参考。

§27.6.1 加载图象和文本文件下面给出 Pankaj Garg编写的加载图象和文本数据的程序。/* 作者:Pankaj Garg,Virginia数据库分析员 *//* 下面例子加载的图象可以达 20k,文本文件可达 4000 字符 *//* 根据情况,你可以改变参数   *//* 对于图象:            */ create table Image (imagefile_no number(4), imagefile long raw);

/* 对于文本文件:            */ create table Text(textfile_no number(4), textfile long);

/* 加载图象的控制文件 image.ctl如下:  */

load data

infile 'Imagefile.gif' "fix 20000"

append into table Image

(ImageFile_no constant 101,

imagefile raw(20000))

/* 加载文本文件的控制文件 text.ctl 如下:  */

load data infile 'Textfile.txt' "fix 4000" append into table Text fields (textfile_no constant 101, textfile char(4000))

用下面命令加载图象文件:

224

Page 225: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

sqlload control=image.ctl username/password

§27.6.2 加载文本文件例1.用定界来加载 LOB数据控制文件LOAD DATAINFILE ’sample1.dat’ "str ’<endrec>\n’"INTO TABLE Multimedia_tabFIELDS TERMINATED BY ’,’(Clip_ID CHAR(3),Story CHAR(507) ENCLOSED BY ’<startlob>’ AND ’<endlob>’)数据文件sample1.dat007, <startlob> Once upon a time,The end. <endlob>|008, <startlob> Once upon another time ....The end. <endlob>|

例2.用记录符来加载数据控制文件LOAD DATAINFILE ’sample2.dat’ "str ’<endrec>\n’"INTO TABLE Multimedia_tabFIELDS TERMINATED BY ’,’(Clip_ID INTEGER EXTERNAL (3),Story VARCHARC (3, 500))

数据文件sample2.dat007,041 Once upon a time... .... The end. <endrec>008,000 <endrec>

例3.加载一个LOB文件控制文件LOAD DATAINFILE ’sample3.dat’INTO TABLE Multimedia_tab

225

Page 226: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

REPLACEFIELDS TERMINATED BY ’,’(Clip_ID INTEGER EXTERNAL(5),ext_FileName FILLER CHAR(40),Story LOBFILE(ext_FileName) TERMINATED BY EOF)

数据文件sample3.dat007,FirstStory.txt,008,/tmp/SecondStory.txt,

第2个数据文件FirstStory.txtOnce upon a time ...The end.

第2个数据文件SecondStory.txtOnce upon another time ....The end.

例4.加载预定大小控制文件LOAD DATA

INFILE ’sample4.dat’INTO TABLE Multimedia_tabFIELDS TERMINATED BY ’,’(Clip_ID INTEGER EXTERNAL(5),Story LOBFILE (CONSTANT ’FirstStory1.txt’) CHAR(32))数据文件sample4.dat007,008,第2个数据文件FirstStory1.txtOnce upon the time ...The end,

Upon another time ...The end,

226

Page 227: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

第二十八章 PL/SQL编程技巧

本章给出作者在工作常用到的一些 PL/SQL编程方法,有些是作者亲自编写的程序,有些是从其它渠道得到和修改而成。希望能对 PL/SQL编程有所帮助。

§28.1用触发器实现日期格式的自动设置

前面给出了如何设置NLS_DATE_FORMAT 环境参数来实现日期格式的设置。许多学员都问我,在设置了 NLS_DATE_FORMAT后如果退出实例再登录后,NLS_DATE_FORMAT的格式就又回到默认的格式。那么如何按照自己所习惯的格式进行设置而不影响其他用户的习惯呢?我们可以编写一个触发器来实现动态的设置。例:用户 zhao 喜欢格 式为“ yyyy/mm/dd”;用户 scott 喜欢“ yyyy.mm.dd”,则可以用AFTER LOGON(登录后触发)来编写程序,使得当用户登录成功后,日期格式就变为自己喜欢的格式。/* 作者:Krishna Sarabu,修改:赵元杰 */Create Or Replace Trigger Set_nlsAFTER LOGONON DATABASEdeclare c1 integer; r1 integer;BEGIN IF SYS_CONTEXT('userenv','session_user') = 'ZHAO' THEN

C1 := dbms_sql.open_cursor();dbms_sql.parse(c1, 'ALTER session set nls_date_format='||chr(39)||'YYYY/MM/DD'||chr(39),

dbms_sql.NATIVE);r1 := dbms_sql.execute(c1);dbms_sql.close_cursor(c1);

ELSIF SYS_CONTEXT('userenv','session_user') = 'SCOTT' THENC1 := dbms_sql.open_cursor();dbms_sql.parse(c1,'alter session set nls_date_format='||chr(39)||'YYYY.MM.DD'||chr(39),

dbms_sql.NATIVE);

227

Page 228: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

r1 :=dbms_sql.execute(c1);dbms_sql.close_cursor(c1);

END IF;END;/

这样后,只要是用户 zhao 或 scott 登录到 Oracle,都会引起 NLS_DATE_FORMAT的改变,请看下面的查询结果:连接到: Oracle8i Enterprise Edition Release 8.1.7.0.0 - ProductionWith the Partitioning optionJServer Release 8.1.7.0.0 - Production

SQL> show userUSER 为"ZHAO"

SQL> select sysdate from dual;

SYSDATE----------2002/02/08

再登录到 scott用户,结果为:连接到: Oracle8i Enterprise Edition Release 8.1.7.0.0 - ProductionWith the Partitioning optionJServer Release 8.1.7.0.0 - Production

SQL> show userUSER 为"SCOTT"SQL> select sysdate from dual;

SYSDATE----------2002.02.08

需要注意的是,这个触发器是在开始登录成功后(AFTER LOGON)的第一个用户有效,如果你不退出本次会话而用 connect 连接到另外的用户的话,则不会触发该触发器。

228

Page 229: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§28.2如何避免 TOO_MANY_ROWS错误许多使用 PL/SQL编写程序的程序人员都会遇到 TOO_MANY_ROWS这样的错误提示。这是因为在 PL/SQL中,每次查询只允许一条记录取出放到变量中,如果被查询的条件满足一条以上的话,就会出现这样的错 误。但如果查 询时没有满足条件的记 录,则也会出现no_data_found 错误。解决这两个问题的办法如下:假设要查询的 EMP 表有下面结果:SQL> select * from emp;

ENAME SAL DEPTNO TEL -------------------- ---------- ---------- --------------------------------赵元杰 9000 10 1360 136 5681 张三 8888 10 123456 李四 7000 10 654321

已选择 3行。例 1. 没有声明例外的 PL/SQL代码,先设置 set serveroutput on 以保证能显示信息。declare v_sal number(9,2); v_ename varchar2(20); begin begin select ename, sal into v_ename, v_sal from emp where sal >= 8888 ; dbms_output.put_line(’姓名:’|| v_ename ||’,工资:’||to_char(v_sal) );

end; begin select ename, sal into v_ename, v_sal from emp where sal = 9000 ; dbms_output.put_line(’姓名:’|| v_ename ||’,工资:’||to_char(v_sal) );

end;end;

/

从上面的查询条件来看,由于 sal>=8888有两条记录被满足,并且程序中没有声明例外处理情况,所以出现错误后第二条语句也就不执行了。执行显示信息如下:SQL> declare 2 v_sal number(9,2);

229

Page 230: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

3 v_ename varchar2(20); 4 begin 5 begin 6 select ename, sal into v_ename, v_sal from emp 7 where sal >= 8888 ; 8 dbms_output.put_line('姓名:'|| v_ename ||',工资:'||to_char(v_sal) ); 9 end; 10 begin 11 select ename, sal into v_ename, v_sal from emp 12 where sal = 9000 ; 13 dbms_output.put_line('姓名:'|| v_ename ||',工资:'||to_char(v_sal) ); 14 end; 15 end; 16 /declare*ERROR 位于第 1 行:ORA-01422: 实际返回的行数超出请求的行数ORA-06512: 在 line 6

例 2. 在上面代码的每个 begin…end之间加上例外处理(Exception)后,代码脚本如下,在运行前,先设置 set serveroutput on 以保证能显示信息。declare v_sal number(9,2); v_ename varchar2(20); begin begin select ename, sal into v_ename, v_sal from emp where sal >= 8888 ; dbms_output.put_line(’姓名:’|| v_ename ||’,工资:’||to_char(v_sal) ); exception when no_data_found then dbms_output.put_line(‘sal >= 8888出现 no_data_found ‘); when too_many_rows then

dbms_output.put_line(‘sal >= 8888出现 too_many_rows’);end;

begin select ename, sal into v_ename, v_sal from emp where sal = 9000 ; dbms_output.put_line(’姓名:’|| v_ename ||’,工资:’||to_char(v_sal) ); exception when no_data_found then

230

Page 231: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

dbms_output.put_line(‘sal = 9000出现 no_data_found ‘); when too_many_rows then

dbms_output.put_line(‘sal = 9000出现 too_many_rows’);end;end;

/

上面的代码执行显示如下:SQL> declare 2 v_sal number(9,2); 3 v_ename varchar2(20); 4 begin 5 begin 6 select ename, sal into v_ename, v_sal from emp 7 where sal >= 8888 ; 8 dbms_output.put_line('姓名:'|| v_ename ||',工资:'||to_char(v_sal) ); 9 exception 10 when no_data_found then 11 dbms_output.put_line('sal >= 8888出现 no_data_found '); 12 when too_many_rows then 13 dbms_output.put_line('sal >= 8888出现 too_many_rows'); 14 end; 15 begin 16 select ename, sal into v_ename, v_sal from emp 17 where sal = 9000 ; 18 dbms_output.put_line('姓名:'|| v_ename ||',工资:'||to_char(v_sal) ); 19 exception 20 when no_data_found then 21 dbms_output.put_line('sal = 9000出现 no-data_found '); 22 when too_many_rows then 23 dbms_output.put_line('sal = 9000出现 too_many_rows'); 24 end; 25 end; 26 /sal >= 8888出现 too_many_rows姓名:赵元杰,工资:9000

PL/SQL 过程已成功完成。SQL>

从显示的信息来看,虽然第一个语句出现错误,但是在显示出错信息“sal >= 8888出现 too_many_rows”之后,接着执行下一个语句,并且显示出了结果。

231

Page 232: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

§28.3如何解决 TOO_MANY_ROWS问题如果我们在写程序时,并不知道要查询的表满足条件是否是多于 1 条以上记录,总担心出现“TOO_MANY_ROWS”错误提示。为了解决这个问题,建议无论所查询的表的记录有多少,都要采用光标来处理。可将上例 2 该成为下面的完整例子:例 1:使用光标实现查询多条记录。declare v_sal number(9,2); v_ename varchar2(20); CURSOR c1 is select ename, sal from emp where sal >= 8888 ; Begin Open c1; Fetch c1 into v_ename, v_sal ;

WHILE c1%FOUND LOOP dbms_output.put_line(’姓名:’|| v_ename ||’,工资:’||to_char(v_sal) ); Fetch c1 into v_ename, v_sal ;

END LOOP;end;

/

执行的结果如下:SQL> declare 2 v_sal number(9,2); 3 v_ename varchar2(20); 4 CURSOR c1 is select ename, sal from emp where sal >= 8888 ; 5 Begin 6 Open c1; 7 Fetch c1 into v_ename, v_sal ; 8 WHILE c1%FOUND LOOP 9 dbms_output.put_line('姓名:'|| v_ename ||',工资:'||to_char(v_sal) ); 10 Fetch c1 into v_ename, v_sal ; 11 END LOOP; 12 end; 13 /姓名:赵元杰,工资:9000姓名:张三, 工资:8888

232

Page 233: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

PL/SQL 过程已成功完成。此外,还可以采用循环来实现查询多条记录。

§28.4如何在 PL/SQL中使用数组在 PL/SQL中,要想使用数组来存放数据,不能象高级语言那样将变量声明成数组类型,而是使用 PL/SQL中规定的类型来实现。即要创建表描述类型和表说明变量类型,用下面语句定义表类型:TYPE(类型名) IS TABLE OF ( 数据类型 )INDEX BY BINARY_INTEGER;

看下面例子:

DECLARE /* 创建表描述类型 */TYPE t_ename is TABLE OF emp.ename%TYPEINDEX BY BINARY_INTEGER;TYPE t_sal is TABLE OF emp.sal%TYPEINDEX BY BINARY_INTEGER;/* 创建变量描述类型 */v_ename t_ename;v_sal t_sal ;Begin /* 将结果存到数组变量中 */select ename,sal into v_ename(1) ,v_sal(1) from emp where sal=9000;

select ename,sal into v_ename(2) ,v_sal(2) from emp where sal=8888;

dbms_output.put_line( v_ename(1) ||’:’||to_char(v_sal(1)) );dbms_output.put_line( v_ename(2) ||’:’||to_char(v_sal(2)));end;/

执行的结果显示如下:

233

Page 234: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

赵元杰:9000张三:8888

PL/SQL 过程已成功完成

§28.5如何使用触发器完成数据复制Oracle的企业版支持分布环境,如果我们的环境已经建立了分布的话,只要用 CREATE DATABASE LINK语句创建相应的数据库的连接,就可以使用 AFTER INSERT 来实现将一个源基表的记录插入到远程数据库中。CREATE OR REPLACE TRIGGER emp_insAFTER INSERT ON emp FOR EACH ROWBEGIN INSERT INTO remote_emp@dblink_emp2Values(:new.deptno, :new.ename, :new.sal …);END;

同样,如果源基表进行删除,则也可以写一个AFTER DELETE 触发器:CREATE OR REPLACE TRIGGER emp_delAFTER DELETE ON emp FOR EACH ROWBEGIN DELETE FROM remote_emp@dblink_emp2WHERE deptno = :old.deptno;END;

§28.6在 PL/SQL中实现 Truncate

前面介绍过,在 SQL>下可以用 TRUNCATE 命令来快速删除一个表的所有记录,但是一般在 PL/SQL程序中,不能直接使用 TRUNCATE 命令。许多程序员感叹,要是能在 PL/SQL中能使用 TRUNCATE那该多方便。下面是笔者所进行的一点例子,供 PL/SQL编程爱好者参考:主要分两步:1.先创建一个存储过程,比如代码如下:CREATE or replace procedure truncate_tab(table_name in varchar2) as Cursor_name Integer;Begin

234

Page 235: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Cursor_name := DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(Cursor_name,'Truncate table '||table_name||' drop storage', dbms_sql.native); DBMS_SQL.CLOSE_CURSOR(Cursor_name);Exception When Others then DBMS_SQL.CLOSE_CURSOR(Cursor_name); RAISE;End truncate_tab;/

2.在 SQL>下运行上面代码的提示如下:SQL> CREATE or replace procedure truncate_tab(table_name in varchar2) as 2 CursorId Integer; 3 Begin 4 Cursor_name := DBMS_SQL.OPEN_CURSOR; 5 DBMS_SQL.PARSE(Cursor_name,'Truncate table '||table_name||' drop storage', dbms_sql.native); 6 DBMS_SQL.CLOSE_CURSOR(Cursor_name); 7 Exception 8 When Others then DBMS_SQL.CLOSE_CURSOR(Cursor_name); 9 RAISE; 10 End truncate_tab; 11 /

过程已创建。SQL> select * from abc;

RQ NAME---------- --------------------

02-2月 -02 zhaoyuan已选择 1 行。上面查询已经知道 表 ABC有一条记录,现在执行 truncate_tab 来删除表 ABC的所有记录:3.执行 TRUNCATE_TAB过程来删除表中记录:SQL> exec truncate_tab('ABC');

PL/SQL 过程已成功完成。

235

Page 236: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SQL> select * from abc;

未选定行SQL>

§28.7如何导出存储过程、触发器的代码

REM 选自 export.sqlREM 作者: Scott UrmanREM 中外注释:赵元杰CREATE OR REPLACE PACKAGE Export AS

/* 导出一个对象。参数使用如下: * p_Schema: 指定对象的所有者 * p_ObjType: 指定对象的类型,可以是 'PACKAGE', 'PACKAGE BODY', * 'PROCEDURE', 'FUNCTION', 或 'TRIGGER'. If NULL, * 如果类型为空,则表示选择所有的类型。 * p_BothTypes: 如果为 TRUE,并当 p_ObjType = 'PACKAGE'时,则导出包头和包体。 * p_FileDir: 要导出存放的目录. * p_FileName: 导出的文件名. * p_Mode: 模式 ( 'A'—追加 或 'W'—写 ) */

PROCEDURE OneObj(p_Schema IN VARCHAR2, p_ObjName IN VARCHAR2, p_ObjType IN VARCHAR2 DEFAULT NULL, p_BothTypes IN BOOLEAN DEFAULT TRUE, p_FileDir IN VARCHAR2, p_FileName IN VARCHAR2, p_Mode IN VARCHAR2); /* 导出一个对象。参数使用如下: * p_Schema: 指定对象的所有者 * p_ObjType: 指定对象的类型,可以是 'PACKAGE', 'PACKAGE BODY', * 'PROCEDURE', 'FUNCTION', 或 'TRIGGER'. If NULL, * 如果类型为空,则表示选择所有的类型。 * p_BothTypes: 如果为 TRUE,并当 p_ObjType = 'PACKAGE'时,则导出包头和包体。 * p_FileDir: 要导出存放的目录.

236

Page 237: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

* p_FileName: 导出的文件名. * p_Mode: 模式 ( 'A'—追加 或 'W'—写 ) */

PROCEDURE AllObjs(p_Schema IN VARCHAR2, p_ObjType IN VARCHAR2 DEFAULT NULL, p_FileDir IN VARCHAR2, p_FileName IN VARCHAR2, p_Mode IN VARCHAR2);END Export;/

CREATE OR REPLACE PACKAGE BODY Export AS /* 这个存储过程挂在包里.它实现输出一个对象处理。输出的对象由 p_Schema, p_ObjName, and p_ObjType 指定。需要确保文件已经以'W'或 'A'方式打开. */

PROCEDURE OutputObj(p_FileHandle IN OUT UTL_FILE.FILE_TYPE, p_Schema IN VARCHAR2, p_ObjName IN VARCHAR2, p_ObjType IN VARCHAR2) IS

/* 这里的变量用于返回触发器的文本,因为所有触发器都是以 LONG类型进行存放,所以要用DBMS_SQL来提取 */

v_SQLStmt VARCHAR2(200) := 'SELECT description, trigger_body FROM all_triggers WHERE owner = :v_owner AND trigger_name = :v_name'; v_Cursor INTEGER; v_NumRows INTEGER; v_Dummy INTEGER; v_Description all_triggers.description%TYPE; v_BodyChunk VARCHAR2(100); v_ChunkSize NUMBER := 100; v_CurPos NUMBER := 0;

v_ReturnedLength NUMBER := 0;

/* 这里的变量用于返回其他类型对象的文本,不用DBMS_SQL来提取,因为在ALL_SOURCE中都是以行来存放。 */

v_TextLine all_source.text%TYPE; CURSOR c_ObjCur IS

237

Page 238: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SELECT text FROM all_source WHERE owner = p_Schema AND name = p_ObjName AND type = p_ObjType ORDER BY line;

BEGIN -- 首先,要写 'CREATE OR REPLACE ' 到打开的文件中. UTL_FILE.PUT(p_FileHandle, 'CREATE OR REPLACE '); IF (p_ObjType = 'TRIGGER') THEN BEGIN -- 输出对象的类型 (TRIGGER in this case) 到打开的文件中. UTL_FILE.PUT(p_FileHandle, 'TRIGGER '); -- 打开光标和分析语句. v_Cursor := DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(v_Cursor, v_SQLStmt, DBMS_SQL.NATIVE); -- 绑定变量到占位符. DBMS_SQL.BIND_VARIABLE(v_Cursor, ':v_owner', p_Schema); DBMS_SQL.BIND_VARIABLE(v_Cursor, ':v_name', p_Objname); -- 绑定输出变量,为触发器包体定义 DEFINE_COLUMN_LONG

DBMS_SQL.DEFINE_COLUMN(v_Cursor, 1, v_Description, 2000); DBMS_SQL.DEFINE_COLUMN_LONG(v_Cursor, 2); -- 执行语句返回触发器行,不用循环是由于每个触发器只有一行 v_Dummy := DBMS_SQL.EXECUTE(v_Cursor); v_NumRows := DBMS_SQL.FETCH_ROWS(v_Cursor); -- 返回触发器的描述并写到文件中。 -- 这里用 UTL_FILE.PUT 而不用 UTL_FILE.PUT_LINE, -- 详细请参考“文件的 I/O”章节—赵元杰 DBMS_SQL.COLUMN_VALUE(v_Cursor, 1, v_Description); UTL_FILE.PUT(p_FileHandle, v_Description); -- 循环直到返回所有的触发器的主体部分 LOOP

238

Page 239: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DBMS_SQL.COLUMN_VALUE_LONG(v_Cursor, 2, v_ChunkSize, v_CurPos, v_BodyChunk, v_ReturnedLength); IF v_ReturnedLength < v_ChunkSize THEN -- 我们刚返回最后一个大块,由于NULL是一个特殊的字符, -- 它以一个新行来存放.所以需要将它删除掉。 v_BodyChunk := SUBSTR(v_BodyChunk, 1, LENGTH(v_BodyChunk) - 1); -- Output the trimmed chunk, and exit the loop. UTL_FILE.PUT(p_FileHandle, v_BodyChunk); EXIT; ELSE -- 从 LONG 返回一个大的块并写到文件中,然后更新下次循环的位置 UTL_FILE.PUT(p_FileHandle, v_BodyChunk); v_CurPos := v_CurPos + v_ReturnedLength; END IF; END LOOP; -- 已经处理完成,要关闭光标. DBMS_SQL.CLOSE_CURSOR(v_Cursor); EXCEPTION WHEN OTHERS THEN -- 先关闭第 1个光标,然后触发例外处理 DBMS_SQL.CLOSE_CURSOR(v_Cursor); RAISE; END; ELSE -- 到这里,还没有真正输出触发器,所以要通过 all_source来循环输出每行。If we -- 第 1行是对象的类型和名字并加 'IS' 或 'AS'. OPEN c_ObjCur; LOOP FETCH c_ObjCur INTO v_TextLine; EXIT WHEN c_ObjCur%NOTFOUND; -- 每行包含新行字符,所以要用UTL_FILE.PUT 而不用 UTL_FILE.PUT_LINE.

UTL_FILE.PUT(p_FileHandle, v_TextLine); END LOOP; CLOSE c_ObjCur; END IF;

-- 最后输出一个 '/'.

239

Page 240: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

UTL_FILE.PUT_LINE(p_FileHandle, '/'); END OutputObj; PROCEDURE OneObj(p_Schema IN VARCHAR2, p_ObjName IN VARCHAR2, p_ObjType IN VARCHAR2 DEFAULT NULL, p_BothTypes IN BOOLEAN DEFAULT TRUE, p_FileDir IN VARCHAR2, p_FileName IN VARCHAR2, p_Mode IN VARCHAR2) IS v_FileHandle UTL_FILE.FILE_TYPE; v_ObjType all_objects.object_type%TYPE; BEGIN -- Validate the input parameters. IF p_BothTypes AND (p_ObjType != 'PACKAGE') THEN RAISE_APPLICATION_ERROR(-20000, 'Export.OneObj: BothTypes set but type != PACKAGE'); ELSIF p_ObjType IS NOT NULL AND p_ObjType NOT IN ('PACKAGE', 'PACKAGE BODY', 'PROCEDURE', 'FUNCTION', 'TRIGGER') THEN RAISE_APPLICATION_ERROR(-20001, 'Export.OneObj: Illegal value ' || p_ObjType || ' for object type'); ELSIF p_FileDir IS NULL OR p_FileName IS NULL or p_Mode IS NULL THEN RAISE_APPLICATION_ERROR(-20002, 'Export.OneObj: Directory, Filename and Mode must be non-NULL'); ELSIF p_Mode NOT IN ('A', 'a', 'W', 'w') THEN RAISE_APPLICATION_ERROR(-20003, 'Export.OneObj: Mode ' || p_Mode || ' not ''A'' or ''W'''); END IF; -- 确定相应的对象类型和对象的存在. BEGIN IF p_ObjType IS NULL THEN -- 没有指定对象类型(表示所有类型的对象),现在要检查这些对象的存在。 SELECT object_type INTO v_ObjType FROM all_objects WHERE owner = UPPER(p_Schema) AND object_name = UPPER(p_Objname) AND object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY', 'TRIGGER'); ELSIF p_BothTypes THEN -- 检查 package header SELECT object_type

240

Page 241: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

INTO v_ObjType FROM all_objects WHERE owner = UPPER(p_Schema) AND object_name = UPPER(p_Objname) AND object_type = 'PACKAGE'; -- 检查 package body. BEGIN SELECT object_type INTO v_ObjType FROM all_objects WHERE owner = UPPER(p_Schema) AND object_name = UPPER(p_Objname) AND object_type = 'PACKAGE BODY'; EXCEPTION WHEN NO_DATA_FOUND THEN RAISE_APPLICATION_ERROR(-20006, 'Export.ObjObj: BothTypes set but package body ' || p_Schema || '.' || p_Objname || ' not found'); END; ELSE -- 对象类型指定、都不指定的检查存在性. SELECT object_type INTO v_ObjType FROM all_objects WHERE owner = UPPER(p_Schema) AND object_name = UPPER(p_Objname) AND object_type = p_ObjType; END IF; EXCEPTION WHEN NO_DATA_FOUND THEN RAISE_APPLICATION_ERROR(-20004, 'Export.OneObj: Object ' || p_Schema || '.' || p_Objname || ' not found'); WHEN TOO_MANY_ROWS THEN RAISE_APPLICATION_ERROR(-20005, 'Export.OneObj: More than one match for ' || p_Schema || '.' || p_Objname); END;

-- 到这里,表明对象已经存在,所以要打开文件并写到文件中。 v_FileHandle := UTL_FILE.FOPEN(p_FileDir, p_FileName, p_Mode); IF p_Mode IN ('A', 'a') THEN

241

Page 242: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

UTL_FILE.NEW_LINE(v_FileHandle, 2); END IF; -- 输出对象. IF p_ObjType = 'PACKAGE' AND p_BothTypes THEN OutputObj(v_FileHandle, p_Schema, p_ObjName, 'PACKAGE'); UTL_FILE.NEW_LINE(v_FileHandle, 2); OutputObj(v_FileHandle, p_Schema, p_ObjName, 'PACKAGE BODY'); ELSE OutputObj(v_FileHandle, p_Schema, p_ObjName, v_ObjType); END IF;

-- 关闭输出文件. UTL_FILE.FCLOSE(v_FileHandle); EXCEPTION --处理 UTL_FILE 例外并关闭文件 WHEN UTL_FILE.INVALID_PATH THEN UTL_FILE.FCLOSE(v_FileHandle); RAISE_APPLICATION_ERROR(-20010, 'Export.OneObj: Invalid Path'); WHEN UTL_FILE.INVALID_OPERATION THEN UTL_FILE.FCLOSE(v_FileHandle); RAISE_APPLICATION_ERROR(-20010, 'Export.OneObj: Invalid Operation'); WHEN UTL_FILE.INVALID_FILEHANDLE THEN UTL_FILE.FCLOSE(v_FileHandle); RAISE_APPLICATION_ERROR(-20010, 'Export.OneObj: Invalid File Handle'); WHEN UTL_FILE.WRITE_ERROR THEN UTL_FILE.FCLOSE(v_FileHandle); RAISE_APPLICATION_ERROR(-20010, 'Export.OneObj: Write Error'); WHEN UTL_FILE.INTERNAL_ERROR THEN UTL_FILE.FCLOSE(v_FileHandle); RAISE_APPLICATION_ERROR(-20010, 'Export.OneObj: Internal Error'); WHEN OTHERS THEN UTL_FILE.FCLOSE(v_FileHandle); RAISE; END OneObj; PROCEDURE AllObjs(p_Schema IN VARCHAR2, p_ObjType IN VARCHAR2 DEFAULT NULL,

242

Page 243: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

p_FileDir IN VARCHAR2, p_FileName IN VARCHAR2, p_Mode IN VARCHAR2) IS v_FileHandle UTL_FILE.FILE_TYPE; v_ObjName all_objects.object_name%TYPE; v_ObjType all_objects.object_type%TYPE; v_ObjectFound BOOLEAN := FALSE; -- 使用光标变量查询,因为采用两种格式。 TYPE t_AllObjs IS REF CURSOR; c_AllObjsCur t_AllObjs; BEGIN -- 生效输入参数. IF p_ObjType IS NOT NULL AND p_ObjType NOT IN ('PACKAGE', 'PACKAGE BODY', 'PROCEDURE', 'FUNCTION', 'TRIGGER') THEN RAISE_APPLICATION_ERROR(-20001, 'Export.AllObjs: Illegal value ' || p_ObjType || ' for object type'); ELSIF p_FileDir IS NULL OR p_FileName IS NULL or p_Mode IS NULL THEN RAISE_APPLICATION_ERROR(-20002, 'Export.AllObjs: Directory, Filename and Mode must be non-NULL'); ELSIF p_Mode NOT IN ('A', 'a', 'W', 'w') THEN RAISE_APPLICATION_ERROR(-20003, 'Export.AllObjs: Mode ' || p_Mode || ' not ''A'' or ''W'''); END IF;

-- 如果对象类型没有指定,则要打开查询所有对象的光标 -- 如果对象类型已经指定,则要打开对象类型的光标 IF p_ObjType IS NULL THEN OPEN c_AllObjsCur FOR SELECT object_name, object_type FROM all_objects WHERE owner = UPPER(p_Schema) AND object_type in ('PACKAGE', 'PACKAGE BODY', 'PROCEDURE', 'FUNCTION', 'TRIGGER'); ELSE OPEN c_AllObjsCur FOR SELECT object_name, object_type FROM all_objects WHERE owner = UPPER(p_Schema) AND object_type = p_ObjType;

243

Page 244: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END IF; -- 循环超过选择的要求,并且在行间输出 2个空行。 LOOP FETCH c_AllObjsCur INTO v_ObjName, v_ObjType; EXIT WHEN c_AllObjsCur%NOTFOUND;

IF NOT v_ObjectFound THEN -- 如果找到至少一个对象,则以追加(’A’)打开文件并且写 2个空行。 v_ObjectFound := TRUE; v_FileHandle := UTL_FILE.FOPEN(p_FileDir, p_FileName, p_Mode); IF p_Mode IN ('A', 'a') THEN UTL_FILE.NEW_LINE(v_FileHandle, 2); END IF; END IF; OutputObj(v_FileHandle, p_Schema, v_ObjName, v_ObjType); UTL_FILE.NEW_LINE(v_FileHandle, 2); END LOOP; -- 检查对象和关闭光标及文件句柄 CLOSE c_AllObjsCur; IF NOT v_ObjectFound THEN RAISE_APPLICATION_ERROR(-20004, 'Export.AllObjs: No objects found'); END IF; UTL_FILE.FCLOSE(v_FileHandle); EXCEPTION -- 处理 UTL_FILE 例外和关闭文件 WHEN UTL_FILE.INVALID_PATH THEN UTL_FILE.FCLOSE(v_FileHandle); RAISE_APPLICATION_ERROR(-20010, 'Export.AllObjs: Invalid Path'); WHEN UTL_FILE.INVALID_OPERATION THEN UTL_FILE.FCLOSE(v_FileHandle); RAISE_APPLICATION_ERROR(-20010, 'Export.AllObjs: Invalid Operation'); WHEN UTL_FILE.INVALID_FILEHANDLE THEN UTL_FILE.FCLOSE(v_FileHandle); RAISE_APPLICATION_ERROR(-20010,

244

Page 245: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

'Export.AllObjs: Invalid File Handle'); WHEN UTL_FILE.WRITE_ERROR THEN UTL_FILE.FCLOSE(v_FileHandle); RAISE_APPLICATION_ERROR(-20010, 'Export.AllObjs: Write Error'); WHEN OTHERS THEN UTL_FILE.FCLOSE(v_FileHandle); RAISE; END AllObjs;END Export;/

附录A:SQL及 SQL*PLUS 命令参考

命令参考按照字母顺序排列:%FOUND

参见:%ISOPEN, %NOTFOUND,CURSOR, %ROWCOUNT

语法:c1%FOUND 或SQL%FOUNDc1 为PL/SQL 光标名字例子:PL/SQLLOOPFETCH loan_cursor INTO customer_name, loan_amount;IF loan_cursor%FOUND THENapproved_loan := loan_amount * 0.80;

245

Page 246: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ELSEEXIT;END IF;END LOOP;INSERT INTO approved_loan VALUES (customer_name,loan_amount);IF SQL%FOUND THENCOMMIT;ELSEROLLBACK;END IF;

%ISOPEN

参见:%FOUND, %NOTFOUND,CURSOR, %ROWCOUNT

语法:c1%ISOPEN或SQL%ISOPENc1:为 PL/SQL 光标例子:PL/SQLIF loan_cursor%ISOPEN THENFETCH loan_cursor INTO customer_name,loan_amount;ELSEOPEN loan_cursor;END IF;

%NOTFOUND

参见:%ISOPEN, %FOUND,

246

Page 247: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CURSOR, %ROWCOUNT

语法:c1%NOTFOUND或SQL%NOTFOUND

变量:c1:有效的 PL/SQL 光标例子:PL/SQLLOOPFETCH loan_cursor INTO customer_name,loan_amount;EXIT WHEN loan_cursor%NOTFOUNDEND LOOP;INSERT INTO approved_loan VALUES (customer_name,loan_amount);IF SQL%NOTFOUND THENROLLBACK;ELSECOMMIT;END IF;

%ROWCOUNT

参见:%ISOPEN, %FOUND,%NOTFOUND, CURSOR

语法:c1%ROWCOUNT或SQL%ROWCOUNT

变量:c1:有效的 PL/SQL 光标。例子:

247

Page 248: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

PL/SQLDECLARECURSOR c1 IS SELECT customer_name, loan_amount FROM

Loan ORDER BY loan_amount DESC;cust_name VARCHAR2(50);loan_amt NUMBER(5,2);BEGINOPEN c1;LOOPFETCH c1 INTO cust_name, loan_amt;EXIT WHEN (c1%ROWCOUNT > 5) OR(c1%NOTFOUND);INSERT INTO loan_approved VALUES(cust_name, loan_amt);COMMIT;END LOOP;CLOSE c1;END;UPDATE approved_loan SET approved_flag = ‘Y’ WHEREloan_amount < 5000;IF SQL%ROWCOUNT > 10 THENINSERT INTO approvals VALUES (‘STOP MOREAPPROVAL’);END IF;

%ROWTYPE

参见:%TYPE, FETCH

语法: ( [user.]table | cursor )%ROWTYPE

变量:user: 用户名table : 要访问的表或视图名cursor: 任何有效的 PL/SQL 光标例子:DECLARE

248

Page 249: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CURSOR loan_cursor IS SELECT customer_name, loan_amountFROM loan;loan_record loan_cursor%ROWTYPEBEGINOPEN loan_cursor;LOOPFETCH loan_cursor INTO loan_record;EXIT WHEN loan_cursor%NOTFOUND;IF loan_record.loan_amount < 5000 THENUPDATE loanSET loan_approval = ‘Y’WHERE customer_name =loan_record.customer_name;IF SQL%FOUND THENCOMMIT;END IF;END IF;END LOOP;CLOSE loan_cursor;END;

%TYPE

参见:%ROWTYPE, FETCH

语法: ( [user.]table.column | variable )%TYPE

变量:user: 用户名table or view: 要访问的表名或视图名column: 表名或视图的列名variable: 任何有效的PL/SQL 变量例子:PL/SQLnew_balance old_balance%TYPE;customer_name loan.customer_name%TYPE;

249

Page 250: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

(+)

参见:Joining Tables PRIOR, CONNECT BY

语法:WHERE table1.column1 = table2.column1 (+)

例子:SQLSELECT SALES_AGENT, MANAGER FROM SALESMEN, MANAGERWHERE SALESMEN.MANGER = MANGER.MANGER(+);SALES_AGENT MANAGER---------- --------JAMES BOND MSADDAM HUSSAINMICHAEL JORDAN PHIL JACKSON

@ (“at” 号)

参见:@@, CREATE DATABASE LINK

语法:@ filename[.ext] [arg_1,...,arg_N]

例子:SQL@PRINT_LOAN_RPT@PRINT_RESULTS.QRY

@@

参见:@

250

Page 251: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:@@ filename [.ext]

例子:SQL@@PRINT_LOAN_STATUS.QRY@@PRINT_RESULTS.QRY

ABS

参见:SIGN

语法:ABS (n)

变量:n:一个数字变量例子:PL/SQLVar1:= ABS (-1);SQLSELECT ABS (-1) “Absolute Value” FROM DUAL;Absolute Value-------1

ACCEPT

参见:INPUT

语法:ACCEPT variable [format] [default] [PROMPT]

251

Page 252: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:SQLACCEPT loan NUMBER FORMAT ‘99999.99’ DEFAULT ‘0.00’ PROMPT‘Enter weekly salary: ‘ACCEPT last_name CHAR FORMAT ‘35’ PROMPT “Enter customer’s lastname: “

ACOS

参见:ASIN, ATAN, and ATAN2

语法:ACOS (n)

变量:n:-1到1 的数字变量例子:PL/SQLVar1:= ACOS (-1);SQLSELECT ACOS (-1) “Arc Cosine” FROM DUAL;Arc Cosine----------3.1415927

ADD_MONTHS

参见:MONTHS_BETWEEN

语法:ADD_MONTHS (d, n)

变量:

252

Page 253: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

d:有效的日期型变量n:整型变量例子:PL/SQLDate1:= ADD_MONTHS (‘26-JAN-47’, 10);SQLSELECT ADD_MONTHS (‘26-JAN-47’, 10) “Add Months” FROM DUAL;Add Month---------26-NOV-47

ALTER CLUSTER

参见:CREATE CLUSTER,DROP CLUSTER

语法:ALTER CLUSTER [user.]cluster[INITRANS n][MAXTRANS n][PCTFREE n][PCTUSED n][SIZE n [K | M] ][STORAGE n][ALLOCATE EXTENT [SIZE n [K | M] ] ][DATAFILE ‘filename’][INSTANCE n]

变量:user:建立cluster 的用户名n:任意正整数filename:文件名例子:SQLALTER CLUSTER customer PCTFREE 12

253

Page 254: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ALTER DATABASE

参见: CREATE DATABASE,DROP DATABASE

语法:ALTER DATABASE [database][ADD LOGFILE[THREAD n] [GROUP n]file_definition [.file_definition] ... |ADD LOGFILE MEMBERFile [REUSE] [, file [REUSE] ...]TO [GROUP n |(file [, file] ...) |filefile [REUSE] [, file [REUSE] ...]TO [GROUP n |(file [, file] ...) |file) ] .. |DROP LOGFILE{ GROUP n | (file [,file] ... ) | file}[GROUP n | (file [,file] ... ) | file] ... |DROP LOGFILE MEMBER file [, file] |RENAME FILE file to file |NOARCHIVELOG | ARCHIVELOG |MOUNT [EXCLUSIVE | PARALLE] |OPEN [RESETLOGS | NORESETLOGS] |ENABLE [PUBLIC] THREAD n |DISABLE THREAD n |BACKUP CONTROLFILE TO file [REUSE]DATAFILE file [ONLINE | OFFLINE [DROP]] |CREATE DATAFILE file[,file]AS file_definition [.file_definition] ... |RENAME GLOBAL_NAME TO database [.domain] |RECOVER recover_clause |SET [DBMAC [ON | OFF] | DBHIGH = string | DBLOW =string ]

例子:SQLALTER DATABASE NO MOUNT ;

254

Page 255: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ALTER DATABASE ADD LOGFILE GROUP 2 ‘customer.002’ size 2m;

ALTER FUNCTION

参见:CREATE FUNCTION,DROP FUNCTION

语法:ALTER FUNCTION [user.]function COMPILE

变量:user:建立函数的用户名function:数据库中函数名例子:SQLALTER FUNCTION loan_calculation COMPILE;ALTER FUNCTION credit_points COMPILE;

ALTER INDEX

参见:CREATE INDEX, DROP INDEX

语法:ALTER [UNIQUE] INDEX [user.]index[INITRANS n][MAXTRANS n][STORAGE n]

变量:user:建立索引的用户名index:数据库中的索引名例子:SQLALTER INDEX loan_application;

255

Page 256: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ALTER PACKAGE

参见:CREATE PACKAGE,DROP PACKAGE

语法:ALTER PACKAGE [user.]package COMPILE [PACKAGE | BODY]

变量:user:建立包的用户名package:数据库中包名字例子:SQLALTER PACKAGE loan_processing;

ALTER PROCEDURE

参见:CREATE PROCEDURE, DROP PROCEDURE

语法:ALTER PROCEDURE [user.]procedure COMPILE

变量:user:建立包的用户名procedure:数据库中的存储过程名例子:SQLALTER PROCEDURE loan_calculation COMPILE;ALTER PROCEDURE credit_points COMPILE;

256

Page 257: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ALTER PROFILE

参见:CREATE PROFILE, DROP PROFILE

语法:ALTER PROFILE profile LIMIT[ { SESSIONS_PER_USER |CPU_PER_SESSION |CPU_PER_CALL |CONNECT_TIME |IDLE_TIME |LOGICAL_READS_PER_SESSION |LOGICAL_READS_PER_CALL |COMPOSITE_LIMIT } { n | UNLIMITED |DEFAULT } |PRIVATE_SGA { n {K | M} | UNLIMITED |DEFAULT } ]

变量:profile:想要改变的数据库profile名字n:任意整数值例子:SQLALTER PROFILE customer LIMIT SESSION_PER_USER 12 ;ALTER PROFILE customer LIMIT CONNECT_TIME 600 ;

ALTER RESOURCE COST

参见:CREATE PROFILE

语法:ALTER RESOURCE COST[ CPU_PER_SESSION n |CONNECT_TIME n |

257

Page 258: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

LOGICAL_READS_PER_SESSION n |PRIVATE_SGA n]

变量:n:any integer value

例子:SQLALTER PROCEDURE loan_calculation COMPILE;ALTER PROCEDURE credit_points COMPILE;

ALTER ROLE

参见:CREATE ROLE, DROP ROLE

语法:ALTER ROLE role[ NOT IDENTIFIED | IDENTIFIED[ BY PASSWORD | EXTERNALLY ] ]

变量:role:需要改变的数据库中的角色例子:SQLALTER ROLE custom_user;

ALTER ROLLBACK SEGMENT

参见:CREATE ROLLBACK SEGMENT,DROP ROLLBACK SEGMENT

语法:ALTER [PUBLIC] ROLLBACK SEGMENT rollback_segment[STORAGE storage]

258

Page 259: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:SQLALTER PUBLIC ROLLBACK SEGMENT humanresources;ALTER ROLLBACK SEGMENT insurance;

ALTER SEQUENCE

参见:CREATE SEQUENCE, DROP SEQUENCE

语法:ALTER SEQUENCE [user.]sequence[ INCREMENT BY n][ MAXVALUE n | NOMAXVALUE][ MINVALUE n | NOMINVALUE][ CYCLE | NO CYCLE][CACHE n | NO CACHE][ORDER | NO ORDER]

变量:user:建立sequence 的用户名sequence:需要改变的数据库中sequencen:任意整数值例子:SQLALTER SEQUENCE customer_code_seqINCREMENT BY 1;ALTER SEQUENCE loan_application_seqNOMAXVALUE ;

ALTER SESSION

参见:SET ROLE, ALTER SYSTEM

259

Page 260: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:ALTER SESSION[ SET parameterCLOSE DATABASE LINK link |ADVICE [ COMMIT | ROLLBACK | NOTHING ] |[ ENABLE | DISABLE | COMMIT IN PROCEDURE ]

变量:parameter: 可以设置的下列命令: [ SQL_TRACE [TRUE | FALSE][ NLS_LANGUAGE = language ][ NLS_TERRITORY = territory ][ NLS_DATE_FORMAT = format ][ NLS_DATE_FORMAT = language ][ NLS_NUMERIC_CHARACTERS = string][ NLS_ISO_CURRENCY = territory][ NLS_CURRENCY = string][ NLS_SORT = sort][ LABEL = [string | DBHIGH | DBLOW | OSLABEL] ][ MLS_LABEL = format ] |

例子:SQLALTER SESSION ENABLE COMMIT IN PROCEDUREALTER SESSION DISABLE COMMIT IN PROCEDURE

ALTER SNAPSHOT

参见:CREATE SNAPSHOT,DROP SNAPSHOT

语法:ALTER SNAPSHOT [user.] snapshot[PCTFREE n |PCTUSED n |INITRANS n |MAXTRANS n |STORAGE n]

260

Page 261: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

[ REFRESH { FAST | COMPLETE | FORCE}[START WITH start_date] [NEXTnext_date]

变量:user:建立 snapshot的用户名n:任意的正整数值start_date:启动snapshot 进程的开始日期next_date:刷新snapshot的日期snapshot:需要改变的数据库中 snapshot 的名字例子:SQLALTER SNAPSHOT customer.inactive_cust_snapshot[ PCTUSED 12]

ALTER SNAPSHOT LOG

参见:CREATE SNAPSHOT LOG,DROP SNAPSHOT LOG

语法:ALTER SNAPSHOT LOG ON [user.] table[PCTFREE n |PCTUSED n |INITRANS n |MAXTRANS n |STORAGE n]

变量:n:任意正整数值table:需要改变的与snapshot 日志有关的主表

例子:SQLALTER SNAPSHOT LOG ON inventoryPCTUSED 12

261

Page 262: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ALTER SYSTEM

参见:COMMIT, ROLLBACK,SAVEPOINT,SET TRANSACTION

语法:ALTER SYSTEM[ SET { RESOURCE_LIMIT = { TRUE | FALSE } |MTS_SERVERS = nMTS_DSIPATCHERS = ‘protocol.n’SWITCH LOGFILE |{ CHECKPOINT | CHECK DATAFILES } { GLOBAL | LOCAL } |{ ENABLE | DISABLE }{ DISTRIBUTED RECOVERY | RESTRICTED SESSION } |ARCHIVE LOG archive_log_clauseFLUSH SHARE_POOLKILL SESSION ‘sid, serial number’ ]

变量:archive_log_clause:归档日志项sid:希望杀掉( KILL)的会话的sid号serial number:希望杀掉( KILL)的会话的序列号例子:SQLALTER SYSTEM SET RESOURCE_LIMIT = TRUE

ALTER TABLE

参见:CREATE TABLE, DROP TABLE

语法:ALTER TABLE [user.] table{ [ ADD ( { column1 | table_constraint }

262

Page 263: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

[, column2 | table_constraint} ] ... ) ][ MODIFY ( column1, column2) ][ DROP drop_constraint][PCTFREE n][PCTUSED n][INITRANS n][MAXTRANS n][STORAGE n]ALLOCATE EXTENT[ SIZE n [K | M]][DATAFILE file][INSTANCE n][ ENABLE | DISABLE]

变量:user:建立表的用户名 table:希望改变的表名column:列名table_constraint:表的限制,如 NULL, NOT NULL 等n:任意正整数值file:物理数据文件名例子:SQLALTER TABLE customer( ADD ( address VARCHAR2(50));ALTER TABLE customer( MODIFY ( name VARCHAR2(50) NOT NULL);

ALTER TABLESPACE

参见:CREATE TABLESPACE

语法:ALTER TABLESPACE tablespace[ ADD DATAFILE file_definition[,file_definition] |RENAME DATAFILE file [,file] ... TOfile [, file] |

263

Page 264: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DEFAULT STORAGE storage |ONLINE | OFFLINE [NORMAL | IMMEDIATE]|[ BEGIN | END] BACKUP ]

变量:tablespace:希望改变的数据库表空间名file_definition:带大小( K or M)的文件名例子:SQLALTER TABLESPACE customer ADD DATAFILE ‘customer02.dat’ size 10m;

ALTER TRIGGER

参见:CREATE TRIGGER, DROP TRIGGER

语法:ALTER TRIGGER [user.]trigger [ENABLE | DISABLE |COMPILE]

变量:user:建立触发器的用户名trigger:希望改变的数据库中的触发器例子:SQLALTER TRIGGER loan_calculation COMPILE;ALTER TRIGGER credit_points COMPILE;

ALTER TYPE

参见:

264

Page 265: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE TYPE, CREATE TYPE BODY, DROP TYPE

语法:ALTER TYPE schema.type_name{ COMPILE { SPECIFICATION | BODY } |REPLACE AS | AS TABLE | AS OBJECT }{ VARRAY (size) | VARYING ARRAY (size) }{ OF datatype}{ REF object_type_name}{ MAP | ORDER MEMBER function_specification }{ PRAGMA RESTRICT_REFERENCESfunction_specification restriction}

变量:schema:建立类型的数据库用户名type_name:希望改变的对象名size: VARRAY 大小的上限datatype:任意类型,如 CHAR, DATE, NUMBER等object_type_name:对象类型引用的名字function_specification:成员函数名restriction:限制类型,如 WNDS, WNPS, RNDS, RNPS

例子:SQLALTER TYPE loan_obj AS OBJECT(customer_name CHAR(20),loan_amount NUMBER(5),MEMBER FUNCTION get_amount RETURN NUMBER,MEMBER FUNCTION get_loan_approved RETURN NUMBER,pragma RESTRICT_REFERENCES (get_amount, WNDS));

ALTER USER

参见:CREATE USER, DROP USER

语法:ALTER USER user [IDENTIFIED [BY password | EXTERNALLY]][ DEFAULT TABLESPACE tablespace]

265

Page 266: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

[TEMPORARY TABLESPACE tablespace][QUOTA {n [K | M] | UNLIMITED} ON tablespace][,QUOTA {n [K | M] | UNLIMITED} ON tablespace][PROFILE profile][DEFAULT ROLE (role1, role2, ...) | ALL EXCEPT(role1, role2, ...) |NONE]

变量:user:希望改变的数据库用户名tablespace:用户建立的表空间名n:任意正整数值profile:用户要使用的profile名role:用户指定(或不指定)的角色例子:SQLALTER USER customerDEFAULT tablespace cust_tablespaceTEMPORARY tablespace temp;

ALTER VIEW

参见: CREATE VIEW, DROP VIEW

语法:ALTER VIEW [user.]view COMPILE

变量:user:建立视图的用户名view:希望改变的数据库的视图名例子:SQLALTER VIEW loan_calculation COMPILE;ALTER VIEW credit_points COMPILE;

266

Page 267: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ANALYZE

参见:EXPLAIN PLAN, AUDIT

语法:ANALYZE{ INDEX [user.]index{ { COMPUTE | ESTIMATE | DELETE } STATISTICS[ SAMPLE ( n PERCENT | n ROWS } ] |VALIDATE STRUCTURE } |{ TABLE [user.]table | CLUSTER [user.]cluster}{ { COMPUTE | ESTIMATE | DELETE } STATISTICS[ SAMPLE ( n PERCENT | n ROWS } ] |VALIDATE STRUCTURE } [CASCASE] |LIST CHAINED ROWS [INTO [user.]table] }

变量:index:希望分析的索引的名字n:任意正整数值table:希望分析的表名cluster:希望分析的cluster名例子:SQLANALYZE INDEX cust_index ESTIMATE STATISTICS;

APPEND

参见:DEL, EDIT

语法:A[PPEND] text

变量:

267

Page 268: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

text:在 SQL 缓冲区希望增加的字符串例子:SQLA FROM TELECOMAPPEND WHERE SQLCODE = 2

ASCII

参见:CHR

语法:ASCII (‘x’)

变量:x: 用单引号引起的字符串例子:PL/SQLVar1:= ASCII (‘A’);SQLSELECT ASCII (‘Z’) FROM DUAL;ASCII(‘Z’)----------90

ASIN

参见:ACOS, ATAN, ATAN2

语法:ASIN (n)变量:

268

Page 269: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

n: -1 到 1 的数字变量例子:PL/SQLVar1:= ASIN (-1);SQLSELECT ASIN (-1) “Arc Sine” FROM DUAL;Arc Sine----------1.570796

ATAN

参见:ACOS, ASIN, ATAN2

语法:ATAN (n)

变量:n:数字变量例子:PL/SQLVar1:= ATAN (-1);SQLSELECT ATAN (-1) “Arc Tangent” FROM DUAL;Arc Tangent------------.7853982

ATAN2

参见:ACOS, ASIN, ATAN

269

Page 270: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:ATAN2 (x, y)

变量:n:数字变量例子:PL/SQLVar1:= ATAN2 (-1, 1);SQLSELECT ATAN2 (-1, 1) “Arc Tangent2” FROM DUAL;Arc Tangent2-------------.7853982

AUDIT

参见:NO AUDIT, ANALYZE

语法:AUDIT command | ALLON [user.]object | DEFAULT[ BY SESSION | ACCESS ][ WHENEVER [NOT] SUCCESSFUL ]

变量:command:可以审计的命 令: ALTER, AUDIT, COMMENT, DELETE, EXECUTE, GRANT, INDEX, INSERT, LOCK, RENAME, SELECT 及 UPDATE User:建立对象的用户名Object:对象 名,可以是 table, view, synonym, sequence, procedure, function, package, 或 snapshot.

例子:SQLAUDIT INSERT ON customer WHENEVER NOT SUCCESSFUL;

270

Page 271: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

AVG

参见:Group by SUM

语法:AVG ( [DISTINCT | ALL] n)

变量:DISTINCT:如果多个一样只考虑一个的选项,缺省为DISTINCTALL:如果多个一样都考虑一个的选项N:数字变量例子:PL/SQLVar1:= AVG (1, 2, 3);SQLSELECT AVG (DAILY_SALES) “Average Daily Sales” FROM SALES;Average Daily Sales--------------655.12

BFILENAME

参见:LOBs CREATE DIRECTORY

语法:BFILENAME (‘directory’, ‘file’)

变量:directory:服务器中的物理目录名,最长只能30个字符file:服务中物理文件名例子:SQLINSERT INTO lob_table VALUES (BFILENAME (‘lob_directory’,

271

Page 272: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

‘file1.bmp’));

BLOCK

参见:LABEL

语法: [<<label>>]DECLAREobject_declaration_1,...,object_declaration_n[subprogram_declaration_1[,subprogram_declaration_2,...,subprogram_declaration_n]]BEGINstatement_1,...,statement_n[EXCEPTION exception_handler_1 [, exception_handler_2,...,exception_handler_3]]END [label];

变量:label:可选,不需声明的PL/SQL 块object_declaration_1,...,object_declaration_n:声明的对象,可以是:constant_declarationvariable_declarationcursor_declarationcursor_variable_declarationrecord_declarationexception_declarationplsql_table_declaration

subprogram_declaration_1,...,subprogram_declaration_n:子程序,可以是:procedure_declarationfunction_declaration

statement_1,...,statement_n:一系列语句exception_handler_1,...,exception_handler_n:例外处理语句例子:PL/SQLDECLARE

272

Page 273: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

checking_acct_balance NUMBER;BEGINIF checking_acct_balance = 0 THENINSERT INTO checking_acct VALUES (500);DELETE FROM savings_acct VALUES (500);END IF;COMMIT;END;DECLAREtotal_sales NUMBER;bonus NUMBER;salary NUMBER;emp_id NUMBER;BEGINIF total_sales < 1000 THENbonus := salary / total_sales;ELSEbonus := total_sales ;END IF;INSERT INTO employee VALUES (bonus);COMMIT;EXCEPTIONWHEN ZERO_DIVIDE THENINSERT INTO employee VALUES (0);COMMIT;WHEN OTHERS THENROLLBACK;END;.

BTITLE

参见:TTITLE, REPHEADER, REPFOOTER

语法:BTI[TLE] [ printspec [ text | variable] ] | [ OFF | ON]

变量:printspec:输出说明,包括:

273

Page 274: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

COL nS[KIP] [n]TAB nLE[FT]CE[NTER]R[IGHT]BOLDFORMAT textText:标题的字符Variable:包括下列值的变量:SQL.LNO (当前行号)SQL.PNO (当前页号)SQL.RELEASE (当前Oracle版本号)SQL.SQLCODE ( 当前错误代码号)SQL.USER (当前用户)

例子:SQLBTITLE RIGHT ‘MARKETING REPORT’BTITLE OFFBTITLE ON.

CEIL

参见:FLOOR

语法:CEIL (n)

变量:n:数字变量例子:PL/SQLVar1:= CEIL (147.2754);SQLSELECT CEIL (147.2754) “Ceiling” FROM DUAL;Ceiling

274

Page 275: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

---------148

CHANGE

参见:EDIT

语法:C[HANGE] separating_character old [separating_character [new[separating_character]]]

变量:separating_character:可分开的非字母数字字符串old: SQL缓冲区中的旧字符串new: 新的字符串

例子:SQLSQL>lSELECT MARKETING,NAME from empSQL>C /MARKETING/SALES

CHARTOROWID

参见:ROWIDTOCHAR

语法:CHARTOROWID (‘x’)

变量:x:单引号引起的字符 (CHAR 或 VARCHAR2 数据类型)

例子:PL/SQL

275

Page 276: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Var1 := CHARTOROWID (‘ORACLE’)SQLSELECT CHARTOROWID (‘0000000D.1111.0022’) “ROWID_TYPE” FROMDUAL;ROWID_TYPE------------------0000000D.1111.0022

CHR

参见:ASCII

语法:CHR (n)

变量:n: 数字变量例子:PL/SQLVar1 := CHR (120);SQLSELECT CHR (74) || CHR (65) || CHR (86) || CHR (65) “Hot”FROM DUAL;Hot----JAVA

CLEAR

参见:Group By BREAK, COLUMN, COMPUTE

语法:CLEAR option

276

Page 277: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

变量:option:可以是下列之一BUF[FER]COL[UMNS]COMP[UTES]SCR[EEN]SQLTIM[ING]

例子:SQLCLEAR BREAKSCLEAR BUFFERCLEAR SCREENCLEAR SQL

CLOSE

参见:OPEN, OPEN-FOR, FETCH

语法:CLOSE {cursor_name | cursor_variable_name | :host_cursor_variable_name};

变量:cursor_name:希望关闭的光标名cursor_variable_name:希望关闭的与光标有关变量名host_cursor_variable_name:PL/SQL中缩主变量名例子:PL/SQLLOOPFETCH loan_cur INTO loan_rec;EXIT WHEN loan_cur%NOTFOUND;END LOOP;CLOSE loan_cur;

277

Page 278: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

COLUMN

参见:Titles 和Headings

语法:COL[UMN] [{column|expr} [option_1 ... option_n]]

变量:column:希望设置的列名expr:有效的SQL表达式option_1 ... option_N:下列选件之一 :ALI[AS] aliasCLE[AR]FOLD_A[FTER]FOLD_B[EFORE]FOR[MAT] formatHEA[DING] textJUS[TIFY] {L[EFT]|C[ENTER]|C[ENTRE]|R[IGHT]}LIKE {expr|alias}NEWL[INE]NEW_V[ALUE] variableNOPRI[NT]|PRI[NT]NUL[L] textOLD_V[ALUE] variableON|OFFWRA[PPED]|WOR[D_WRAPPED]|TRU[NCATED]

例子:SQLCOLUMN SALARY FORMAT $9,999,999.99COLUMN LAST_NAME FORMAT A35.

COMMENT

参见:REMARK

278

Page 279: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:COMMENT ON [ TABLE table | COLUMN table.column ] IS comment

变量:table:希望加注释的表名column:希望加注释的列名comment:注释内容例子:SQLCOMMENT ON TABLE customer COLUMN cust_name IS this columnis ‘the name of the customer’;

COMMIT

参见:SQL *Plus ROLLBACK, SAVEPOINT, SETTRANSACTION, LOCK TABLE

语法:COMMIT [WORK ] [COMMENT ‘comment_text’]

变量:WORK:可选关键字. COMMENT:可以允许加50个字符的注释例子:SQLCOMMIT;COMMIT WORK;COMMIT WORK ‘Saving loan transaction’

COMPUTE

参见:Group By BREAK

279

Page 280: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:COMP[UTE] [function [LABEL] text OF expression|column|alias ONexpression | column | alias | REPORT | ROW]

变量:function:下列函数之一:AVG, COU[NT], MAX[IMUM], MIN[IMUM], NUM[BER], STD, SUM,VAR[IANCE]Text:the text you will specify for the computed valueExpression:the expression you would like to use to compute the valueColumn:the column(s) you would like to use to compute the valueAlias:the alias for the column(s) you would like to use to compute the value

例子:SQLCOMPUTE MAX LABEL ‘MAXIMUM SALES’ OF SALES ON PRODUCTSCOMPUTE MIN LABEL ‘MINIMUM SALES’ OF SALES ON PRODUCTSCOMPUTER SUM LABEL ‘TOTAL’ OF SALES ON PRODUCTS

CONCAT

参见:CONCATENATE

语法:CONCAT (‘x’, ‘y’)

变量:x: 字符串变量y: 字符串变量例子:PL/SQLVar1 := CONCAT (‘Oracle 8 ‘, ‘is now released’) ;SQLSELECT CONCAT (‘Oracle 8 ‘, ‘is now released’) “Press Release”FROM DUAL;Press Release

280

Page 281: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

------------------------Oracle 8 is now released.

CONCATENATE

参见:CONCAT

语法:||

例子:PL/SQLVar1 := ‘Oracle 8 ‘ || ‘is now released’;SQLSELECT ‘Oracle 8 ‘ || ‘is now released’ “Press Release” FROMDUAL;Press Release------------------------Oracle 8 is now released.

CONNECT BY

语法:SELECT sql_expn FROM [user.]table WHERE where_conditionCONNECT BY [PRIOR] expn = [PRIOR] expnSTART WITH expn = expnORDER BY expn

变量:sql_expn:有效的SQL表达式user:表的主人table: SELECT的表where_condition:SELECT的WHERE条件expn:任意有效的表达式例子:

281

Page 282: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SQLSELECT employee_name, department_name FROM employeeCONNECT BY emp_no = PRIOR department_noORDER BY department_no;.

CONVERT

参见:DECODE

语法:CONVERT (‘x’,’desc_set’ [, ‘source_set’])

变量:x:单引号印起的字符型desc_set:单引号印起的字符集名source_set:单引号印起的原来字符集名,可以选择下面字符集名:通用字符集名 编码字符集名(为了查阅,不翻译)US7ASCII US 7-bit ASCII character setWE8DEC DEC West European 8-bit character setWE8HP HP West European Laserjet 8-bit character setF7DEC DEC French 7-bit character setWE8EBCDIC500 IBM West European EBCDIC Code Page 500WE8PC850 IBM PC Code Page 850WE8ISO8859P1 ISO 8859-1 West European 8-bit character set

例子:SQLSELECT CONVERT (‘strutz’, ‘ WE8HP’, ‘ F7DEC ‘) “Conversion”FROM DUAL;Conversion------Strutz.

282

Page 283: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

COPY

参见:CREATE DATBASE LINK

语法:COPY FROM username[/password] @database_specification TOusername[/password]@database_specification{APPEND|CREATE|INSERT|REPLACE} destination_table[(column_1,..., column_N)] USING query

变量:username:用户名password:口令database specification: 数据库destination_table:目的数据库column_1,...,column_N:目标表的字段query:查询语句例子:SQLCOPY FROM brokerage/sql TO sales/sql APPEND customers (id,name, address) USING select id, name, address frombrokerage.customers;

COS

参见:COSH, SIN, SINH, TAN, TANH

语法:COS (n)

变量:n:数字变量例子:

283

Page 284: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

PL/SQLVar1:= COS (90);SQLSELECT COS (90) “Cosine of 90 degrees” FROM DUAL;Cosine of 90 degrees---------------------.4480736

COSH

参见:COS, SIN, SINH, TAN, TANH

语法:COSH (n)

变量:n:数字变量例子:PL/SQLVar1:= COSH (20);SQLSELECT COSH (20) “Hyperbolic Cosine of 20 deg” FROM DUAL;Hyperbolic Cosine of 20 deg---------------------------242582598

COUNT

参见:Group by SUM

语法:COUNT ( * | [DISTINCT | ALL] expn)

变量:

284

Page 285: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

*:所有列(包括重复)的个数DISTINCT:所有不同列(不重复)的个数ALL:所有列(包括重复)的个数Expn:表达式例子:SQLSELECT COUNT (*) “Total # of Sales” FROM SALES;Total # of Sales--------------12

CREATE CLUSTER

参见:ALTER CLUSTER, DROP CLUSTER

语法:CREATE CLUSTER [user.]cluster( column1 datatype [, column2 datatype, ....] )[INITRANS n][MAXTRANS n][PCTFREE n][PCTUSED n][SIZE n [K | M] ][STORAGE n][TABLESPACE tablespace][INDEX | [HASH IS column] HASHKEYS n]

变量:user:建立cluster的用户cluster:Cluster 名n:任何正整数例子:SQLCREATE CLUSTER customer PCTFREE 12.

285

Page 286: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE CONTROLFILE

参见:CREATE DATABASE

语法:CREATE CONTROLFILE [REUSE] [SET] DATABASE databaseLOGFILE [GROUP n] file [,[GROUP n] file] ( RESETLOG |NORESETLOG)DATAFILE file [,file][ MAXLOGFILES n][ MAXLOGMEMBERS n][ MAXLOGHISTORY n][ MAXDATAFILES n][ MAXINSTANCE n][ ARCHIVELOG | NOARCHIVELOG ]

变量:n:任何正整数file:物理文件名例子:SQLCREATE CONTROLFILE REUSE SET DATABASE ORACLELOGFILE ‘D:\ORAWIN95\DATABASE\LOG1ORCL.ORA’ SIZE200K,DATAFILE ‘D:\ORAWIN95\DATABASE\SYS1ORCL.ORA’ SIZE20M;.

CREATE DATABASE

参见:ALTER DATABASE,CREATE CONTROLFILE

语法:CREATE DATABASE [database] [CONTROLFILE REUSE] LOGFILE

286

Page 287: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

[GROUP n] file [,[GROUP n] file]( RESETLOG | NORESETLOG)DATAFILE file [,file][ MAXLOGFILES n][ MAXLOGMEMBERS n][ MAXLOGHISTORY n][DATAFILE file_definition [,file_definition]][ MAXDATAFILES n][ MAXINSTANCE n][ ARCHIVELOG | NOARCHIVELOG ][EXCLUSIVE]( CHARACTER SET charset)

变量:n:任何正整数file:物理文件名charset:字符集例子:SQLCREATE DATABASE ORACLECONTROLFILE REUSELOGFILE ‘D:\ORAWIN95\DATABASE\LOG1ORCL.ORA’ SIZE 200KREUSE, ‘D:\ORAWIN95\DATABASE\LOG2ORCL.ORA’ SIZE 200KREUSEDATAFILE ‘D:\ORAWIN95\DATABASE\SYS1ORCL.ORA’ SIZE 20MREUSE AUTOEXTEND ONNEXT 10M MAXSIZE 200MCHARACTER SET WE8ISO8859P1;.

CREATE DATABASE LINK

参见:分布应用的 CREATE SYNONYM

语法:CREATE [PUBLIC] DATABASE LINK linkCONNECT TO user IDENTIFIEDBY password USING ‘connect_string’

287

Page 288: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

变量:link:数据库链名user:数据库用户password:有效的口令connect_string:被访问的远程数据库字串例子:SQLCREATE DATABASE LINK international_customers connect to INTL_DBidentified by intl using ‘D:INTERNATIONAL’;SELECT CUSTOMER_NAME FROM CUSTOMER@INTL_DB;.

CREATE PROFILE

参见:User Profiles ALTER PROFILE, ALTERRESOURCE COST, DROPPROFILE

语法:CREATE PROFILE profile LIMIT[ { SESSIONS_PER_USER |CPU_PER_SESSION |CPU_PER_CALL |CONNECT_TIME |IDLE_TIME |LOGICAL_READS_PER_SESSION |LOGICAL_READS_PER_CALL |COMPOSITE_LIMIT } { n | UNLIMITED | DEFAULT } |PRIVATE_SGA { n {K | M} | UNLIMITED | DEFAULT } ]

变量:profile:希望修改的profile文件名n:任何正整数例子:SQLCREATE PROFILE customer LIMIT SESSION_PER_USER 12 ;CREATE PROFILE customer LIMIT CONNECT_TIME 600 ;.

288

Page 289: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE DIRECTORY

参见:LOBs DROP DIRECTORY, BFILENAME

语法:CREATE [OR REPLACE] DIRECTORY directory AS pathname;

变量:directory:建立对象的目录pathname:单引号引起的完整路径例子:SQLCREATE OR REPLACE DIRECTORY bfile_directory AS ‘/bfile’;

CREATE FUNCTION

参见:Functions ALTER FUNCTION,DROP FUNCTION

语法:CREATE [OR REPLACE] FUNCTION [user.]function[ (parameter [IN] datatype [,parameter [IN] datatype] ... ) ]RETURN datatype (IS | AS) block

变量:user:建立函数的用户名function:数据库函数名parameter:传给函数的参数datatype:变量的数据类型block: PL/SQL 程序块例子:

289

Page 290: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SQLCREATE FUNCTION loan_calculation (loan_amount NUMBER,no_of_years NUMBER) RETURN NUMBER ASTotal_loan NUMBER;BEGINTotal_loan := loan_amount * no_of_years;RETURN total_loan ;END loan_calculation ;

CREATE INDEX

参见:ALTER INDEX, DROP INDEX

语法:CREATE INDEX [user.]indexON [user.]table (column [ASC | DESC] [,column[ASC | DESC] ] ... )[CLUSTER [user.]cluster][INITRANS n][MAXTRANS n][PCTFREE n][STORAGE storage][TABLESPACE tablespace][NO SORT]

变量:user:建立索引的用户名index:索引名table:要建索引的表名cluster:要建索引的CLUSTER名n:任何正整数tablespace:存放索引的表空间例子:SQLCREATE INDEX loan_application_indxON loan (loan_id ASC)TABLESPACE temp;CREATE INDEX customer_indx

290

Page 291: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ON loan (cust_id ASC, loan_id ASC)TABLESPACE temp;.

CREATE LIBRARY

参见:CREATE FUNCTION, CREATEPROCEDURE, DROP LIBRARY

语法:CREATE [OR REPLACE] LIBRARY library_name [IS | AS] filename;

变量:library_name:SQL和PL/SQL要调用的外部(3GL)函数及存储过程filename:外部物理文件名例子:SQLCREATE LIBRARY ext_lib IS ‘/lib/file1.sql’;CREATE OR REPLACE LIBRARY ext_lib2 AS ‘/lib/file2.sql’;

CREATE PACKAGE

参见:CREATE PACKAGE BODY,ALTER PACKAGE,DROP PACKAGE

语法:CREATE [OR REPLACE] PACKAGE [user.]package { IS | AS}{ variable_declaration |cursor_specification |exception_declaration |record_declaration |plsql_table_declaration |procedure_specification |function_specification } ;[{ variable_declaration |

291

Page 292: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

cursor_specification |exception_declaration |record_declaration |plsql_table_declaration |procedure_specification |function_specification } ; ] ...END [package]

变量:user:建立 Package的用户名package:建立Package 的名例子:SQLCREATE OR REPLACE PACKAGE loan_approval ASType LoanRecTyp IS RECORD (customer_id INTEGER, loan_amountREAL);CURSOR customer_history (customer_id NUMBER) RETURN LoanRecTyp;PROCEDURE approve_loan( customer_id CHAR,loan_type CHAR,loan_amount CHAR);PROCEDURE cumulative_loan (loan_amount REAL);END loan_approval ;

CREATE PACKAGE BODY

参见:CREATE PACKAGE,ALTER PACKAGE BODY,DROP PACKAGE BODY

语法:CREATE [OR REPLACE] PACKAGE BODY [user.]package { IS |AS}{ variable_declaration |cursor_body |exception_declaration |record_declaration |plsql_table_declaration |

292

Page 293: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

procedure_body |function_body } ;[{ variable_declaration |cursor_body |exception_declaration |record_declaration |plsql_table_declaration |procedure_body |function_body } ; ] ...END [package]

变量:user:建立Package的用户名package:在数据库中的Package的名字例子:SQLCREATE OR REPLACE PACKAGE BODY loan_approval ASCURSOR customer_history (customer_id NUMBER) RETURN LoanRecTypISSELECT customer_id FROM customer ;PROCEDURE approve_loan( customer_id CHAR,loan_type CHAR,loan_amount REAL) ISBEGINIF loan_amount < 10000 THENUPDATE customerSET loan_type = ‘A’WHERE cust_id = customer_id;END IF;END approve_loan;PROCEDURE cumulative_loan (loan_amount REAL) ISBEGINUPDATE total_outstanding SET loan_amt = loan_amt +loan_amount;END cumulative_loan;END approve_loan ;.

293

Page 294: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE PROCEDURE

参见:ALTER PROCEDURE,DROP PROCEDURE

语法:CREATE [OR REPLACE] [user.]procedure[ (parameter [IN] datatype [,parameter [IN] datatype]... ) ](IS | AS) block

变量:user:建立Procedure的用户名procedure:Procedure的名字parameter:传参数给 Procedure的变量名datatype:变量的数据类型block:PL/SQL程序块例子:SQLCREATE PROCEDURE loan_calculation (loan_amount NUMBER,no_of_years NUMBER) ASTotal_loan NUMBER;BEGINTotal_loan:= loan_amount * no_of_years;END loan_calculation ;CREATE OR REPLACE PROCEDURE increment (emp_id INTEGER,increment REAL) IScurrent_pay REAL;missing_pay EXCEPTION;BEGINSELECT salary INTO current_pay FROM employee WHEREempno = emp_id;IF current_pay IS NULL THENRAISE missing_pay;ELSEUPDATE emp SET salary = salary + incrementWHERE empno = emp_id;END IF;EXCEPTION

294

Page 295: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

WHEN missing_pay THENINSERT INTO emp_audit VALUES (emp_id,‘Incomplete Details’);END increment ;

CREATE ROLE

参见:ALTER ROLE,DROP ROLE, GRANT

语法:CREATE ROLE role[ NOT IDENTIFIED | IDENTIFIED[ BY PASSWORD | EXTERNALLY ] ]

变量:role:角色名例子:SQLCREATE ROLE custom_user ;

CREATE ROLLBACK SEGMENT

参见:ALTER ROLLBACK SEGMENT,DROP ROLLBACK SEGMENT

语法:CREATE [PUBLIC] ROLLBACK SEGMENT rollback_segment[TABLESPACE tablespace][STORAGE storage]

变量:rollback_segment回:滚段名tablespace:表空间名

295

Page 296: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:SQLCREATE ROLLBACK SEGMENT RB_HUMANRESOURCE STORAGE (INITIAL 50KNEXT 100K OPTIMAL 150K);

CREATE SCHEMA

参见:CREATE TABLE, DROP SCHEMA

语法:CREATE SCHEMA AUTHORIZATION schema[ CREATE TABLE command |CREATE VIEW command |GRANT command ]

变量:schema:希望建立的模式名例子:SQLCREATE SCHEMA AUTHORIZATION cust_schemaCREATE TABLE customer(CUSTOMER_ID NUMBER(4) NOT NULL,CUSTOMER_NAME VARCHAR2(50) NOT NULL,STREET_ADDRESS VARCHAR2(50) NOT NULL,CITY VARCHAR2(50) NOT NULL,STATE VARCHAR2(2) NOT NULL CHECK (‘FL’, ‘TX’, ‘MD’)CUST_TYPE VARCHAR2(1) NOT NULLLOAN_AMOUNT NUMBER(6) ) |CREATE VIEW loan.view ASSELECT customer_id, customer_name, loan_amount FROM customerWHEREcustomer_type = ‘L’ ;

296

Page 297: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE SEQUENCE

参见:ALTER SEQUENCE,DROP SEQUENCE

语法:CREATE SEQUENCE [user.]sequence[ INCREMENT BY n][ START WITH n][ MAXVALUE n | NOMAXVALUE][ MINVALUE n | NOMINVALUE][ CYCLE | NO CYCLE][CACHE n | NO CACHE][ORDER | NO ORDER]

变量:user:建立sequence的用户名sequence:sequence名n:任何正整数

例子:SQLCREATE SEQUENCE customer_code_seqINCREMENT BY 1START WITH 1;CREATE SEQUENCE loan_application_seqSTART WITH 100INCREMENT WITH 100NOMAXVALUE ;.

CREATE SNAPSHOT

参见:ALTER SNAPSHOT,DROP SNAPSHOT

297

Page 298: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:CREATE SNAPSHOT [user.] snapshot[PCTFREE n |PCTUSED n |INITRANS n |MAXTRANS n |STORAGE n |TABLESPACE tablespace ][CLUSER cluster (column1 [,column2] ...) ][ REFRESH { FAST | COMPLETE | FORCE }[START WITH start_date] [NEXTnext_date] ]AS query

变量:user:建立snapshot的用户名snapshot:snapshot的名字n:任何正整数tablespace:表空间名start_date:开始处理日期next_date:刷新snapshot的日期query:从 SELECT snapshot取数据的语句 例子:SQLCREATE SNAPSHOT customer.inactive_cust_snapshot ASSELECT customer_id, customer_name,customer_addressFROM customer@remote;.

CREATE SNAPSHOT LOG

CREATE SNAPSHOT,ALTER SNAPSHOT LOG,DROP SNAPSHOT LOG

语法:CREATE SNAPSHOT LOG ON [user.] table[PCTFREE n |PCTUSED n |INITRANS n |

298

Page 299: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

MAXTRANS n |STORAGE n |TABLESPACE tablespace ]

变量:user:建立snapshot log的用户名table:希望snapshot log的表名n:any positive integer valuetablespace:the Tablespace on which you would like to create the snapshot

例子:SQLCREATE SNAPSHOT LOGON customer.customer@remoteTABLESPACE temp ;

CREATE SYNONYM

参见:CREATE DATABASE LINK,CREATE TABLE, CREATE VIEW

语法:CREATE [PUBLIC] SYNONYM [user.] synonymFOR [user.] table [@database_link]

变量:user:建立同义词的用户table:建立同义词的表database_link:远程数据库连接名例子:SQLCREATE SYNONYM r_cust FOR CUSTOMER@REMOTE_SITE;

299

Page 300: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE TABLE

参见:ALTER TABLE,DROP TABLE

语法:CREATE TABLE [schema.]table [ ( { column datatype[DEFAULT expr] [WITH ROWID] [SCOPE IS [user.]scope_table_name][column_constrint]... | table_constraint | REF (ref_column_name)WITH ROWID | SCOPE FOR (ref_column_name) IS [user.]scope_table_name }

[ ,{ column datatype[DEFAULT expr] [WITH ROWID] [SCOPE IS [user.]scope_table_name][column_constrint]... | table_constraint | REF (ref_column_name)WITH ROWID | SCOPE FOR (ref_column_name) ISuser.]scope_table_name}]...)][{[ORGANIZATION{HELP |INDEX} |PCTTHRESHOLD|INCLUDEING column_name] [OVERFLOW[physical_sttrbutes_clause|TABLESPACE tablespace]...] |hpysical_attributes_clause|TABLESPACE tablespace |LOB(lob_item[,lob_item...])STORE AS [lob_segname] [(TABLESPACE tablespace |STORAGE storage |CHUNK integer | PCTVERSION integer |CACHE | NOCACHE LOGGING|NOCACHE NOLOGGING |INDEX[lob_index_name] [(TABLESPACE tablespace |STORAGE storage |INITITRANS integer |MAXTRANS integer )...])] |NESTED TABLE nested_item STORE AS storage_table |{LOGGING|NOLOGGING}]... |CLUSTER cluster(column[,column]...)}] [PARALLEL parallel_clause ] [PARTITION BY RANGE (column_list) (PARTITION [partition_name] VALUE LESS THAN (value_list) [physical_attributes-clause |TABLESPACE tablespace |{LOGGING|NOLOGGING}]...

300

Page 301: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

[ENABLE enable_clause|DISABLE disable_clause]... [AS subquery] [CACHE|NOCACHE]

Physical_attributes_clause ::=

[PCTFREE integer | PCTUSED integer |INITRANS integer | MAXTRANS integer |STORAGE storage_clause]

变量:user:建立表的用户名table:表名column:列(字段)名expn: DEFAULT 值 column_constraint:列的完整性限制column_constraint 可以是:

NULL 表示列可以空NOT NULL表示列不能空UNIQUE 列指定为唯一键PRIMARY KEY 列指定为主键FOREIGN KEY 列指定为外部键REFERENCES 表示被引用的是主键ON DELETE CASCASE 当主键表被删除时外部表自动被删除CHECK 指定每行的条件Cluster: 希望建立表的cluster名N: 任意正整数Query: SELECT 子查询例子:SQLCREATE TABLE customer(CUSTOMER_ID NUMBER(4) NOT NULL,CUSTOMER_NAME VARCHAR2(50) NOT NULL,STREET_ADDRESS VARCHAR2(50) NOT NULL,CITY VARCHAR2(50) NOT NULL,STATE VARCHAR2(2) NOT NULL CHECK (‘FL’, ‘TX’, ‘MD’) ;.

301

Page 302: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE TABLESPACE

参见:ALTER TABLESPACE

语法:CREATE TABLESPACE tablespaceDATAFILE file_definition [,file_definition] |[DEFAULT STORAGE storage ][ ONLINE | OFFLINE ]

变量:tablespace:表空间名file_definition:文件大小的定义(以 K 或 M)例子:SQLCREATE TABLESPACE customer(DATAFILE ‘customer02.dat’);

CREATE TRIGGER

参见: ALTER TRIGGER, DROP TRIGGER

语法:CREATE TRIGGER [user.]trigger{BEFORE | AFTER }{DELETE | INSERT | UPDATE [ OF column1 [, column2] ...}[ OR {DELETE | INSERT | UPDATE [ OF column1 [, column2]...} ...] ON [user.]table[ REFERENCING { OLD [AS] old | NEW [AS] new } ][ FOR EACH ROW][WHEN (when_condition) ]block

变量:

302

Page 303: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

user:建立触发器的用户名trigger:触发器名column:触发器的列名table:定义触发器的表名old:引用表中的旧值new:引用表中的新值when_condition:触发器条件block:要执行的 PL/SQL块例子:SQLCREATE OR REPLACE TRIGGER cumulative_loan_updateAFTER INSERT OR UPDATE OF loan_amountON customerFOR EACH ROWWHEN (new. loan_type = ‘A’)BEGINUPDATE total_outstanding SET loan_amt = loan_amt +new.loan_amount;END;.

CREATE TYPE

参见:ALTER TYPE, CREATETYPE BODY, DROP TYPE

语法:CREATE [OR REPLACE] TYPE [schema.]type_name { AS | AS TABLE |AS OBJECT }{ VARRAY (size) | VARYING ARRAY (size) }{ OF datatype}{ REF object_type_name}{ MAP | ORDER MEMBER function_specification }{ PRAGMA RESTRICT_REFERENCES function_specificationrestriction}

变量:schema:建立对象类型的模式名type_name:所建立的类型名size:VARRAY大小限制

303

Page 304: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

datatype:任意类型,如 CHAR, DATE, NUMBERobject_type_name:类型名function_specification:函数名restriction:限制的类型,如WNDS, WNPS, RNDS, RNPS

例子:SQLCREATE TYPE customer_obj AS OBJECT(name CHAR(20),address CHAR(50),age NUMBER(2));CREATE TYPE name_type AS VARRAY(100) OF CHAR(20);CREATE TYPE loan_obj AS OBJECT(customer_name CHAR(20),loan_amount NUMBER(5),MEMBER FUNCTION get_amount RETURN NUMBER,pragma RESTRICT_REFERENCES (get_amount, WNDS));.

CREATE TYPE BODY

参见:CREATE TYPE,DROP TYPE BODY

语法:CREATE [OR REPLACE] TYPE BODY [schema.]type_name { IS | AS }{ MEMBER procedure_declaration |function_declaration{ MAP | ORDER MEMBER function_declaration }END;

变量:schema:建立类型体的模式名type_name:类型名( CREATE TYPE)procedure_declaration: PL/SQL 过程function_declaration: PL/SQL 函数例子:SQLCREATE OR REPLACE TYPE BODY loan_obj IS

304

Page 305: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

MAP MEMBER FUNCTION get_amount RETURN NUMBER ISBEGINRETURN loan_amount ;END;END;

CREATE USER

参见:ALTER USER, DROP USER

语法:CREATE USER user [IDENTIFIED [BY password |EXTERNALLY]][ DEFAULT TABLESPACE tablespace][TEMPORARY TABLESPACE tablespace][QUOTA {n [K | M] | UNLIMITED} ON tablespace][PROFILE profile]

变量:user:用户名tablespace:表空间名n:任意正整数profile:用户所挂接的profile名

例子:SQLCREATE USER supervisor identified by masterDEFAULT tablespace cust_tablespaceTEMPORARY tablespace temp;

CREATE VIEW

参见:ALTER VIEW, DROP VIEW

305

Page 306: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:CREATE [OR REPLACE] [FORCE/NO FORCE] VIEW [user.]view[column_name1, column_name2] AS query[WITH CHECK OPTION [CONSTRAINT constraint];

变量:user:建立视图所在的用户名view:视图名query:SQL SELECT语句constraint:约束名例子:SQLCREATE OR REPLACE VIEW customer.loan.view ASSELECT customer_id, loan_id, loan_amountFROM customerWHERE customer_type = ‘L’;CREATE OR REPLACE VIEW employee.salary_view(EMPNO, ENAME, SALARY) ASSELECT emp_id, emp_name, grade.grade_rangeFROM employee, gradeWHERE employee.grade_id = grade.grade_id;CREATE OR REPLACE VIEW ladies_only ASSELLECT customer_id, name, address, city, state, zipFROM sex_type = ‘F’ WITH CHECK OPTION ;

CURRVAL

参见:CREATE SEQUENCE, NEXTVAL,PSEUDOCOLUMN

语法:CURRVAL

变量:user:建立sequence 所在的用户名sequence:sequence名

306

Page 307: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:SQL*PlusSELECT loan_seq.CURRVAL FROM DUAL;

CURSOR_ALREADY_OPEN

参见:INVALID_CURSOR

语法:EXCEPTIONWHEN CURSOR_ALREADY_OPEN THENstatement_1,...,statement_n

变量:statement_1,...,statement_n:一系列语句例子:PL/SQLBEGINOPEN loan_cur;LOOPFETCH loan_cur INTO loan_rec;EXIT WHEN loan_cur%NOTFOUND;END LOOP;EXCEPTIONWHEN CURSOR_ALREADY_OPEN THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘CURSOR_ALREADY_OPEN’ ;WHEN OTHERS THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘OTHER ERROR’;END;

307

Page 308: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DATATYPE

参见:CREATE TABLE, ALTER TABLE

BFILE 外部大数据类型,最大GB.BLOB 大数据类型,最大GB.CHAR(n) n=1 到 255 CLOB大数据类型,最大4GB.DATE 日期型 从公元前4712 1月1日 到 公元后4712 12月 31日(占7字节),还包括时分秒FLOAT(n) p=1 到 126 二进制数 LONG 大数据类型,最大2GBLONG RAW 大二进制数据类型,最大2GBMLSLABEL标识二进制格式(Trusted Oracle版本)NCHAR(n) n=1 到 2,000 NCLOB大数据类型,最大4GBNUMBER(p,s) p=1到38, s=-84 到 127 NVARCHAR2(n) n=1 到 4,000,见 VARCHAR 和 NVARCHAR2 RAW(n) n=1到 255 原始二进制数ROWID 伪列,十六进制格式VARCHAR(n) n=1到 4,000VARCHAR2(n) n=1到 4,000

DATATYPE —CHAR

参见:VARCHAR2, LONG

语法:CHAR (n)

变量:n:类型大小,缺省为1,最大为 2000。

308

Page 309: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DATATYPE —DATE

参见:MONTHS_BETWEEN,ADD_MONTHS,LAST_DAY, NEXT_DAY

语法:DATE

变量:无

DATATYPE —FLOAT

参见:NUMBER

语法:FLOAT (n)

变量:n:数字,最小为1,最大为126位。DATATYPE —LONG

参见:CHAR, VARCHAR2

语法:LONG

变量:无

309

Page 310: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DATATYPE —LONGRAW

参见:RAW

语法:LONG RAW

变量:无

DATATYPE —MLSLABEL

参见:Table 命名语法:MLSLABEL

变量:无

DATATYPE —NUMBER

参见:FLOAT

语法:NUMBER (p, s)

变量:

310

Page 311: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DATATYPE —RAW

参见:LONGRAW

语法:RAW (n)

变量:n:1到255

DATATYPE —ROWID

参见: DELETE, UPDATE, SELECT, SELECT INTO

语法:ROWID

变量:无DATATYPE —VARCHAR

参见:VARCHAR2

语法:VARCHAR (n)

变量:n: 1 到 4000

311

Page 312: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DATATYPE —VARCHAR2

参见:CHAR, LONG

语法:VARCHAR2 (n)

变量:n::1 到 4000

DECLARE

参见:DECLARE CURSOR, DECLARE,DATABASE, DECLARE TABLE,CREATE PACKAGE

语法:DECLAREobject_declaration_1,...,object_declaration_n;

变量:object_declaration_1,...,object_declaration_n:对象及类型声明例子:PL/SQLDECLAREtotal_sales NUMBER;total_products NUMBER;unit_price CONSTANT NUMBER:= 1.0;

312

Page 313: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DECODE

参见:TRANSLATE

语法:DECODE (n, if1, then1, if2, then2 ...., else)

变量:n:编码值或列值if1:条件1then1:当条件成立后希望代替的值else:如果条件都满足就用else 来代替例子:PL/SQLVar1:= DECODE (Var2, ‘Sybase’, ‘Oracle’, );

SQLSELECT DECODE (‘Microsoft’, ‘Microsoft’, ‘Macrosoft’) “Example“ FROM DUAL;Example---------Macrosoft.

DEFINE

参见:SET

语法:DE[FINE] [variable]|[variable = text]

变量:variable:希望定义的变量名text:1分配给变量的文本

313

Page 314: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:SQLDEFINE last_name = ‘Jordan’DEFINE department_number = 160

DEL

参见:APPEND, CHANGE, EDIT

语法:DEL [n|n m|n *|n LAST|*|* n|* LAST|LAST]

变量:n: 希望删除的缓冲区的行数n m: 希望删除的缓冲区的n行到m行n *: 希望删除的缓冲区的n行到当前行n LAST:希望删除的缓冲区的n行到最末行*: 希望删除的缓冲区的当前行* n: 希望删除的缓冲区的当前行到n行* LAST:希望删除的缓冲区的当前行到最末行LAST: 希望删除的缓冲区的最末行例子:SQLD 1DEL 5 LAST.

DELETE

参见:INSERT, UPDATE, SELECT,SELECT INTO

语法:

314

Page 315: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DELETE [FROM] {table | (sub_query)} [alias][WHERE {search_condition | CURRENT OF cursor_name}];

变量:table:用户有权删除的表名sub_query:一组子查询alias:别名WHERE search_condition:有效的 WHERE 条件句CURRENT OF cursor_name:与光标有关的当前行例子:SQLDELETE FROM employees where employee_id = ‘124561123’;DELETE FROM employees where employee_id in(SELECT employee_idFROM department_headWHERE department_active_flag = ‘N’);.

DEREF

参见:REFTOHEX, MAKE_REF

语法:DEREF (expn)

变量:expn:引用对象的任意表达式例子:SQLCREATE TABLE customer_tab (customer_no NUMBER, loan REFloan_tab);SELECT DEREF (loan) FROM customer_tab;

315

Page 316: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DESCRIBE

参见:CREATE TABLE

语法:DESC[RIBE] [user.]table[@database_link_name] [column]|[user.]object[.subobject]

变量:user:表所有者的用户名table:希望列出的表名database_link_name:指定的表或视图的名字column:列名object:描述的对象subobject: 描述的子对象例子:SQLDESCRIBE loanDESC acct

DROP CLUSTER

参见:CREATE CLUSTER

语法:DROP CLUSTER [user.] cluster [INCLUDING TABLES] [CASCADECONSTRAINTS]

变量:user:已经建立的cluster的用户名cluster:希望从数据库中删除的cluster 名例子:SQL

316

Page 317: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DROP CLUSTER marketing;DROP CLUSTER telecommunications INCLUDING TABLES;DROP CLUSTER branch INCLUDING TABLES CASCADE CONSTRAINTS;

DROP DATABASE LINK

参见:CREATE DATABASE LINK

语法:DROP [PUBLIC] DATABASE LINK database_link

变量:PUBLIC:从数据库中删除的PUBLICdatabase_link:从数据库中删除的公共数据库链例子:SQLDROP PUBLIC DATABASE LINK corporation;DROP DATABASE LINK tracking;

DROP DIRECTORY

参见:CREATE DIRECTORY,BFILENAME

语法:DROP DIRECTORY directory;

变量:directory:希望删除的目录名例子:SQLDROP DIRECTORY bfile_directory;

317

Page 318: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DROP FUNCTION

参见:CREATE FUNCTION,ALTER FUNCTION

语法:DROP FUNCTION [user.]function

变量:user:建立函数的用户名function:希望删除的函数例子:SQLDROP FUNCTION acctrptDROP FUNCTION loan.calint

DROP INDEX

参见:CREATE INDEX, ALTER INDEX

语法:DROP INDEX [user.]index

变量:user:建立索引的用户名index:希望删除的索引名例子:SQLDROP INDEX sales;DROP INDEX resources;

318

Page 319: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DROP LIBRARY

参见:CREATE LIBRARY

语法:DROP LIBRARY library_name;

变量:library_name: 要删除的库名字database.

例子:SQLDROP LIBRARY ext_procs;

DROP PACKAGE

参见:CREATE PACKAGE, ALTER PACKAGE

语法:DROP PACKAGE [body.] [user.] package

变量:body:包体名字user:建立包的用户名package:希望删除的包的名字例子:SQLDROP PACKAGE loan;DROP PACKAGE BODY customers.newacct;

319

Page 320: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DROP PROCEDURE

参见:CREATE PROCEDURE,ALTER PROCEDURE

语法:DROP PROCEDURE [user.] procedure

变量:user:建立存储过程的用户名procedure:数据库中存储过程的用户名例子:SQLDROP PROCEDURE loanrpt;DROP PROCEDURE acct.acctrpt;

DROP PROFILE

参见:CREATE PROFILE,ALTER PROFILE

语法:DROP PROFILE [user.]profile

变量:user:建立Profile的用户名profile:Profile名字例子:SQLDROP PROFILE accountant;DROP PROFILE my_profile;

320

Page 321: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DROP ROLE

参见:CREATE ROLE, SET ROLE, ALTER ROLE

语法:DROP ROLE [user.] role

变量:user:建立角色的用户名role:希望删除的角色名例子:SQLDROP ROLE manager;DROP ROLE officer;

DROP ROLLBACK SEGMENT

参见:CREATE ROLLBACK SEGMENT,ALTER ROLLBACK SEGMENT

语法:DROP ROLLBACK SEGMENT rollback_segment

变量:rollback_segment: 希望删除的回滚段名字例子:SQLDROP ROLLBACK SEGMENT humanresources;DROP ROLLBACK SEGMENT insurance;

321

Page 322: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DROP SEQUENCE

参见:CREATE SEQUENCE, ALTER SEQUENCE

语法:DROP SEQUENCE [user.]sequence

变量:user:建立序列的用户名sequence:希望删除的序列名例子:SQLDROP SEQUENCE customer.new_cust_seq;DROP SEQUENCE seq1;

DROP SNAPSHOT

参见:CREATE SNAPSHOT,ALTER SNAPSHOT

语法:DROP SNAPSHOT [user.] snapshot

变量:user:建立快照的用户名snapshot:希望从数据库删除的快照例子:SQLDROP SNAPSHOT customer.inactive_cust_snapshot;DROP SNAPSHOT snp1;

322

Page 323: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DROP SNAPSHOT LOG

参见:CREATE SNAPSHOT LOG,ALTER SNAPSHOT LOG

语法:DROP SNAPSHOT LOG ON [user.] table

变量:user:建立快照日志的用户名table:希望删除的与快照日志有关的主表例子:SQLDROP SNAPSHOT LOG ON inventory

DROP SYNONYM

参见:CREATE SYNONYM

语法:DROP [PUBLIC] SYNONYM [user.]synonym

变量:user:建立同义词的用户名synonym:希望删除的同义词的用户名例子:SQLDROP SYNONYM PUBLIC SYNONYM computer;DROP SYNONYM advertisement;

323

Page 324: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DROP TABLE

参见:CREATE TABLE, ALTER TABLE

语法:DROP TABLE [user.] table [CASCADE CONSTRAINTS]

变量:user:建立表的用户名table:希望从数据库中删除的表名例子:SQLDROP TABLE loan;DROP TABLE acct CASCADE CONSTRAINTS;

DROP TABLESPACE

参见:CREATE TABLESPACE,ALTER TABLESPACE

语法:DROP TABLESPACE tablespace [INCLUDING CONTENTS][CASCADE CONSTRAINTS]

变量:tablespace:希望删除的表空间名字例子:SQLDROP TABLESPACE accounting;DROP TABLESPACE airlines INCLUDING CONTENTS;DROP TABLESPACE construction CASCADE CONSTRAINTS;

324

Page 325: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DROP TRIGGER

参见:CREATE TRIGGER,ALTER TRIGGER

语法:DROP TRIGGER [user.] trigger

变量:user: 建立触发器的用户名trigger: 希望删除的数据库触发器名字例子:SQL*PlusDROP TRIGGER accounting.acct_trigger_1;DROP TRIGGER loan_trigger_2;

DROP TYPE

参见:CREATE TYPE, ALTER TYPE,DROP TYPE BODY

语法:DROP TYPE [schema.] type_name [FORCE]

变量:schema: 建立类型的模式名type_name: 对象类型名字例子:SQLDROP TYPE customer_obj;DROP TYPE loan_obj FORCE;

325

Page 326: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DROP TYPE BODY

参见:CREATE TYPE,ALTER TYPE,DROP TYPE BODY

语法:DROP TYPE BODY [schema.] type_name

变量:schema: 建立类型的模式名type_name: 希望删除的对象类型名字例子:SQLDROP TYPE BODY customer_obj;DROP TYPE BODY loan_obj;

DROP USER

参见:CREATE USER

语法:DROP USER user [CASCADE]

变量:user:希望删除的用户名字例子:SQLDROP USER john;DROP USER robert CASCADE;

326

Page 327: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DROP VIEW

参见:CREATE VIEW, ALTER VIEW

语法:DROP VIEW [user.]view

变量:user:建立视图的用户名字view:希望删除的视图的名字例子:SQLDROP VIEW marketing.marketview;DROP VIEW loanview;

DUMP

参见:RAWTOHEX, HEXTORAW

语法:DUMP ( s [, fmt [, start [, length] ] ] )

变量:s:CHAR或VARCHAR的字符类型.Fmt:引用的格式,缺省为 ASCII 或 EBCDICStart:S的开始位置Length:长度例子:SQLSELECT DUMP (SALES_AGENT) “DUMP (Sales Agent, 10, 1, 5)” FROMSALES;DUMP (Sales Agent)--------------

327

Page 328: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Typ=1 Len=14: 20,4e,20,46,52.

DUP_VAL_ON_INDEX

参见:TOO_MANY_ROWS,VALUE_ERROR

语法:EXCEPTIONWHEN DUP_VAL_ON_INDEX THENstatement_1,...,statement_n

变量:statement_1,...,statement_n:一序列语句例子:PL/SQLBEGINUPDATE STATISTICSSET ROW_COUNT = ROW_COUNT + 1;IF SQL%ROWCOUNT = 0 THENINSERT INTO STATISTICS VALUES (1);END IF;EXCEPTIONWHEN DUP_VAL_ON_INDEX THENUPDATE STATISTICSSET ROW_COUNT = 0;END;

EDIT

参见:GET, SAVE, SET

语法:

328

Page 329: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ED[IT] [file_name[.ext]]

变量:file_name:希望打开的文件名ext:扩展类型,缺省为.SQL

例子:SQLED LOAN_RPTEDIT ACCT_RPTEDIT LOAN.QRY

EMPTY_BLOB

参见:BFILENAME, EMPTY_CLOB

语法:EMPTY_BLOB ( )

变量:无例子:PL/SQLVar1:= EMPTY_BLOB ();SQLINSERT INTO lob_table VALUES (‘BLOB DEMO’, EMPTY_BLOB());UPDATE lobSET blob_column = EMPTY_BLOB()WHERE name = ‘BLOB DEMO’;

EMPTY_CLOB

参见:

329

Page 330: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

BFILENAME, EMPTY_BLOB

语法:EMPTY_CLOB ( )

变量:无例子:PL/SQLVar1:= EMPTY_CLOB ();SQLINSERT INTO lob_table VALUES (‘CLOB DEMO’, EMPTY_CLOB());UPDATE lobSET clob_column = EMPTY_CLOB()WHERE name = ‘CLOB DEMO’;

EXCEPTION INIT Pragma

DECLARE EXCEPTION,EXCEPTION, SQLERRM

语法:PRAGMA EXCEPTION_INIT (n);变量:n: 例外整数值例子:PL/SQLDECLAREexception_error_occurred exception;pragma exception_init(exception_error_occurred -786);BEGIN......EXCEPTIONWHEN exception_error_occurred THENUPDATE APPLICATION_ERROR_TABLESET ERROR = EXCEPTION ERROR’ ;END;

330

Page 331: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

EXECUTE

参见:PREPARE

语法:EXEC[UTE] statement

变量:statement:a PL/SQL statement

例子:SQLEXECUTE sales_calculation;EXEC sales_input_trigger;

EXISTS

参见:NOT IN, ANY,ALL, BETWEEN

语法:WHERE EXISTS (subquery)

变量:subquery: 一个 SQL SELECT 子句例子:SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE EXISTS (SELECT * FROM MONTHLY_SALES WHEREDAILY_SALES.SALES_AMOUNT = MONTHLY_SALES.SALES_AMOUNT);SALES_AMOUNT----------12.23

331

Page 332: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

EXIT

参见:LOOP, WHILE-LOOP, FOR-LOOP,EXIT-WHEN

语法:LOOPstatement_1,…statement_n;IF condition_1 is true THENEXIT;END IF;END LOOP

变量:statement_1,...,statement_n:一序列 PL/SQL 语句condition_1:适当的 PL/SQL条件句例子:PL/SQLLOOPTotal_Salary:= Base_Salary + Commission + Bonus;IF Total_Salary = 0 THENEXIT;END IF;UPDATE salary SET employee_salary = Total_Salary WHEREemployee_number:= emp_id;END LOOP;

EXIT

参见:COMMIT, DISCONNECT, QUIT

语法:EXIT|QUIT [SUCCESS|FAILURE|WARNING|n|variable]

332

Page 333: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

[COMMIT|ROLLBACK]

变量:n:返回代码正整数variable:用户定义的变量或系统变量例子:SQLEXITEXIT SQL.SQLCODEQUIT.

EXIT-WHEN

参见:LOOP, WHILE-LOOP,FOR-LOOP, EXIT-WHEN

语法:LOOPstatement_1,...statement_n;EXIT WHEN condition_1 is true;END LOOP

变量:statement_1,...,statement_n:可多次执行的 PL/SQL 语句condition_1:适当PL/SQL 条件句例子:PL/SQLLOOPTotal_Salary:= Base_Salary + Commission + Bonus;EXIT WHEN Total_Salary = 0;UPDATE salary SET employee_salary = Total_Salary WHEREemployee_number:= emp_id;END LOOP ;

333

Page 334: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

EXP

参见:SQRT, POWER

语法:EXP (n)

变量:n:数值变量例子:PL/SQLVar1:= EXP (12);SQLSELECT EXP (12) “Exponential Value of 12” FROM DUAL;Exponential Value of 12-----------------------162754.79

EXPLAIN PLAN

参见:ANALYZE

语法:EXPLAIN PLAN[SET STATEMENT ID = statement_name][ INTO [user.]table]FOR query

变量:statement_name:输出表中一个标识说明方案的名字。如果没有给定,将在输出表中存放一个空值。User:建立表的用户名Table:计划存储的表名Query:计划解释的SQL 语句

334

Page 335: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:SQLEXPLAIN PLANSET STATEMENT_ID = ‘exp_plan_customerINTO all_planFORSELECT CUSTOMER_ID, CUSTOMER_NAME FROM CUSTOMER WHERECUSTOMER_ID IN (SELECT CUSTOMER_ID FROM LOAN_APPROVAL );.

FETCH

参见:CLOSE, OPEN, OPEN-FOR

语法:FETCH {cursor_name | cursor_variable_name|:host_cursor_variable_name}INTO {variable_1[, variable_n]... | record_name};

变量:cursor_name: 光标名cursor_variable_name: 光标变量名host_cursor_variable_name: 在PL/SQL宿主变量中声明的光标变量variable_1,...,variable_n: 一序列变量名record_name: 用户定义的, 或 %ROWTYPE 取数据的名字例子:PL/SQLOPEN loan_cur ;LOOPFETCH loan_cur INTO loan_rec;EXIT WHEN loan_cur%NOTFOUND;END LOOP;CLOSE loan_cur;OPEN emp_cur ;LOOPFETCH emp_cur INTO emp_id, emp_name, emp_title,emp_salary;

335

Page 336: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

EXIT WHEN emp_cur%NOTFOUND;END LOOP;CLOSE emp_cur;.

FLOOR

参见:CEIL

语法:FLOOR (n)

变量:n:一个数值变量例子:PL/SQLVar1:= FLOOR (147.2754);SQLSELECT FLOOR (147.2754) “Floor” FROM DUAL;Floor---------147

FOR-LOOP

参见:LOOP, EXIT, WHILE-LOOP,EXIT-WHEN

语法:FOR i in 1..10 LOOPstatement_1,...,statement_n;END LOOP

变量:i:循环指示变量

336

Page 337: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

statement_1,...,statement_n:一序列PL/SQL语句例子:PL/SQLFOR i in 1..total_employees LOOPTotal_Salary:= Base_Salary + Commission + Bonus;UPDATE salary SET employee_salary = Total_Salary WHEREemployee_number:= emp_id;END LOOP;

FORMAT

说明格式的保留字

FORMAT —DATE

日期格式代码表日期代码 格式说明 例子AD 或 BC AD=Anno Domini 公 元 ,BC=Before

Christ公元前。不带点的公元或公元前‘YYYY AD’=1999 AD

A.D. 或 B.C. 带点的公元或公元前 ‘YYYY A.D.’=1999 A.D.AM 或 PM AM= ante meridiem 上午,PM=post

meridiem下午。不带点的上午或下午‘HH12AM’=09AM

A.M.或 P.M. 带点的上午或下午 ‘HH12A.M.’=09A.M.DY 星期几的缩写 Mon,Tue,...DAY 星期几的全拼 Monday,Tuesday,...D 一周的星期几,星期天=1,星期六=7 1,2,3,4,5,6,7DD 一月的第几天,131 1,2,... 31DDD 一年的第几天,1366 1,2,3,...366J 公元前的第几天(从公元前 4712起 ?) 2451514,2451515,...W 一个月的第几周,1 5 1,2,3,4,5WW,IW 一年的第几周,一年的 ISO的第几周 1,2,3,4,... 52MM 两为数的月 01,02,03,...12MON 月份的缩写 Jan,Feb,Mar ,...DecMONTH 月份的全拼 January,February,...RM 罗马数字的月份,I XII I,II,III,IV,...XII

337

Page 338: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

YYYY,YYY,YY,Y

四位数的年,三位数的年 1999,999,99,9

YEAR 年的全拼 Nineteen Ninety-nineSYYYY 如果是公元前(BC),年份前负号 -1250RR 当前年份的后两位数字 01代表 2001年HH,HH12 12 小时制,112 1,2,3,...12HH24 24 小时制,023 0,1,2,3,...23MI 一小时中的第几分,059 0,1,2,3...59SS 一分中的第几秒,059 0,1,2,3,...59SSSSS 一天中的第几秒,086399 0,1,2,3,...86399../-;: 标点符号表示法 文字显示‘text’ 引号表示法 文字显示

FORMAT —NUMBER

9 指定的数字. 如果为正,前用空格; 如果为负,前带 – 号0 以 0 来填在前面$ 美圆号在前B 浮点数整数部分用空格MI 带有负号的负数S 具有给定位置的数值. 正号用+;负号用 -PR 在 <angle brackets>内的负号D 小数后有指定位数的十进制G 在指定位置放组分隔符C 在指定位置的ISO货币符号L 在指定位置的本地货币符号, 在指定位置的豆号. 在指定位置的小数点V 一个被10的n次方乘的数值,n是v后面的位数EEEE 科学记数法表示RN 以罗马数字表示的数字Rn 以罗马小写数字表示的数字FM 一个不带前导和后空的数字.

338

Page 339: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

GET

参见:GET, SAVE, SET, EDIT

语法:GET filename [.ext] [LIS[T]|NOL[IST]]

变量:filename: 希望加载到SQL缓冲区的文件名ext: 文件的扩展名,缺省为 SQL.

例子:SQLGET LOAN_RPTGET LOAN.QRY

GLB

参见:LUB

语法:GLB ( [DISTINCT | ALL] mls)

变量:DISTINCT:不同的保留字,可选ALL:包括相同的所有Mls:MLSLABEL.类型的变量

GOTO

参见:

339

Page 340: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

LOOP, WHILE-LOOP,FOR-LOOP

语法:BEGIN...GOTO <<calculate_loan>;...<<calculate_loan>SELECT loan_amount FROM loan;END

变量:calculate_loan:标记符例子:PL/SQLBEGIN...GOTO <<calculate_total_salary>>;...<<calculate_total_salary>>Total_Salary:= Base_Salary + Commission + Bonus;END

GRANT

参见:REVOKE

语法:GRANT system_privilege | role TO user | role | PUBLIC[WITH ADMIN OPTION]GRANT object_privilege | ALL column ON schema.objectFROM user | role | PUBLIC WITH GRANT OPTION

变量:system_privilege:授与用户或角色的系统权限名role:授个用户的角色名user:用户或角色名

340

Page 341: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

object_privilege:对象的权限名字,可以是: ALTER DELETE EXECUTE INDEX INSERT REFERENCES SELECT UPDATE

Column:列名Schema:模式名Object:对象名字例子:SQLGRANT CREATE TABLE TO gavaskar;GRANT team_leader TO crystal;GRANT INSERT, UPDATE ON sales TO larry WITH GRANTOPTION;GRANT ALL TO PUBLIC;.

GREATEST

参见:GREATEST_LB, LEAST,LEAST_LB

语法:GREATEST (expn1 [, expn2] ...)

变量:expn:表达式或列名例子:SQLSELECT GREATEST(‘JOHN’, ‘JONNY’, ‘JANARTHAN’) “GREATEST” FROMDUAL;

341

Page 342: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

GREAT-------------JONNY

GREATEST_LB

参见:GREATEST, LEAST, LEAST_LB

语法:GREATEST_LB (label1 [, label2] ...)

变量:label:MLSLABEL 或 RAW MLSLABEL.类型变量

HEXTORAW

参见:RAWTOHEX

语法:HEXTORAW (‘x’)

变量:x:带引号的十六进制例子:SQLSELECT HEXTORAW(animation) “Animation” FROM animation;Animation----------------------------------------3D

342

Page 343: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

HOST

参见:@, START

语法:HO[ST] [command]

变量:command:操作系统命令例子:SQLHOST ls -dHOST ls *.rpt

IF-THEN

参见:IF-THEN-ELSE, IF-THEN-ELSEIF

语法:IF condition_1 is true THENstatement_1,...,statement_nEND IF

变量:condition_1:条件1statement_1,...,statement_n:如果条件1是真要执行的一序列PL/SQL 语句例子:PL/SQLIF sales > quota THENTotal_Salary:= Base_Salary + bonus;END IF;

343

Page 344: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

IF-THEN-ELSE

参见:IF-THEN, IF-THEN-ELSEIF

语法:IF condition_1 is true THENstatement_1,...,statement_nELSEstatement_11,...,statement_n1END IF

变量:condition_1:适当的条件statement_1,....,statement_n:如果条件1是真要执行的一序列PL/SQL 语句statement_11,...,statement_n1:如果条件1是假要执行的一序列PL/SQL 语句例子:PL/SQLIF sales > quota THENTotal_Salary:= Base_Salary + Commission +Bonus;ELSETotal_Salary:= Base_Salary + Commission;END IF;

IF-THEN-ELSEIF

参见:IF-THEN-ELSE, IF-THEN-ELSEIF

语法:IF condition_1 is true THENstatement_1,...,statement_nELSEIF condition_2 i,...,true THENstatement_11,...,statement_n1ELSE

344

Page 345: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

statement_12,...,statement_n2END IF

变量:condition_1:第一个被判断的确定的条件condition_2:下一个被判断的确定的条件statement_1,...,statement_n:如果判断condition_1为真才执行的一系列PL/SQL语句 statement_11,...,statement_n1:如果判断condition_2为真才执行的一系列PL/SQL语句statement_12,...,statement_n2:如果判断condition_1和condition_2都为假才执行的一系列PL/SQL语句例子:PL/SQLIF sales > quota THENTotal_Salary:= Base_Salary + Commission +Bonus;ELSEIF sales = quota THENTotal_Salary:= Base_Salary + Commission;ELSETotal_Salary:= Base_Salary;END IF;.

INITCAP

参见:LOWER, UPPER

语法:INITCAP (‘x’)

变量:x:一个由圆括号所界定的字符变量例子:PL/SQLVar1:= INITCAP (‘oracle is a good database’);SQLSELECT INITCAP(‘oracle is a good database.’) “Sentence” FROMDUAL;

345

Page 346: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Sentence--------------------------Oracle Is A Good Database.

INPUT

参见:ACCEPT

语法:I[NPUT] text

变量:text:你想添加到SQL缓冲区里的文字

例子:SQLI WHERE state = ‘FL’INPUT ORDER BY last_name

INSERT

参见:DELETE, UPDATE, SELECT,SELECT INTO

语法:INSERT INTO {table | (sub_query)}[(column_1[, column_2,...column_n)]{VALUES(sql_expression_1[,sql_expression_2,...,sql_expression_n ])| sub_query);

变量:table:数据库中用户正在插入数据的表,用户要有INSERT权限column_1,...,column_n:指定数据库表中将要被插入数据的列

346

Page 347: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

sql_expression_1,...,sql_expression_n:一串有效的SQL表达式序列例子:SQL*PlusINSERT INTO employees VALUES (‘John Doe’, ‘124561123’,‘Manager’);INSERT INTO employees(employee_name, employee_id)VALUES(‘John Doe’, ‘124561123’);INSERT INTO employees(SELECT * FROM department_head) ;.

INSTR

参见:函数 INSTRB

语法:INSTR (‘w’,’x’ [,’y’,’z’])

变量:w:一个由单括弧界定的字符类型或 VARCHAR2 类型的变量,你将替换掉这个变量里的某些字符。X:一个由单括弧界定的字符类型或VARCHAR2类型的变量,它是你想查找的变量。Y:一个表示查找起始位置的数字变量。缺省值为1。这个值是可选的。Z:一个正的数字变量,它表示查找第几位的字符。缺省为1。这个值是可选的。例子:PL/SQLVar1:= INSTR (‘Oracle Training’, ‘ra’, 1, 2);SQLSELECT INSTR (‘Oracle Training’, ‘ra’, 1, 2) “Instring” FROMDUAL;Instring---------9.

347

Page 348: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

INSTRB

参见:INSTR

语法:INSTRB (‘w’,’x’ [,’y’,’z’])

变量:w:一个由单括弧界定的字符类型或 VARCHAR2 类型的变量,你将替换掉这个变量里的某些字符。.x:一个由单括弧界定的字符类型或VARCHAR2类型的变量,它是你想查找的变量。Y:一个表示查找起始位置的数字变量。缺省值为1。这个值是可选的。Z:一个正的数字变量,它表示查找第几位的字符。缺省为1。这个值是可选的。例子:PL/SQLVar1:= INSTRB (‘Oracle Training’, ‘ra’, 1, 2);SQLSELECT INSTRB (‘Oracle Training’, ‘ra’, 1, 2) “Instring Bytes”FROM DUAL;Instring Bytes--------------9. INSTRB 函数与INSTR函数几乎一样,除了INSTR 函数返回一个字符类型的值而INSTRB返回一个字节值。INSTRB函数在W里查找字符串x中从第y位开始的第z位字符。 如果y 是负数,oracle就会从w的末尾向前查找。如果没有找到,Oracle返回0。

INTERSECT

参见:UNION, UNION ALL, MINUS

语法:b1 INTERSECT b2

变量:

348

Page 349: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

b1 和 b2 是选择语句例子:SQLSELECT SALES_AMOUNT FROM DAILY_SALES WHERE SALES_DATE =‘09-FEB-96’INTERSECTSELECT SALES_AMOUNT FROM DAILY_SALES WHERE SALES_DATE =‘09-FEB-97’ ;SHIPPING_T----------299.95

INVALID_CURSOR

参见:CURSOR_ALREADY_OPEN

语法:EXCEPTIONWHEN INVALID_CURSOR THENstatement_1,...,statement_n

变量:statement_1,...,statement_n:一个语句序列

例子:PL/SQLBEGINOPEN loan_cur;LOOPFETCH loan_cur INTO loan_rec;EXIT WHEN loan_cur%NOTFOUND;END LOOP;EXCEPTIONWHEN INVALID_CURSOR THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘INVALID_CURSOR’ ;END;

349

Page 350: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

INVALID_NUMBER

参见:VALUE_ERROR, ZERO_DIVIDE

语法:EXCEPTIONWHEN INVALID_NUMBER THENstatement_1,...,statement_n

变量:statement_1,...,statement_n:一个语句序列

例子:PL/SQLDECLAREtotal_salary NUMBER;BEGINtotal_salary:= TO_NUMBER (‘ABC’);EXCEPTIONWHEN INVALID_NUMER THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘INVALID NUMBERCONVERSION’ ;END;

KEYWORDS

Oracle 有一列没有保留但仍在Oracle 语法中使用的单词表。这些单词就是关键字。 你可以使用这些关键字作为变量名或对象名,不过系统强烈建议你不要这样做,因为这样会使你的代码难于阅读和理解。下面就是一个关键字表。

Table A-16 关键字列表关键字 关键字 关键字 关键字

350

Page 351: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ADMIN AFTER ALLOCATE ANALYZE

ARCHIVE ARCHIVELOG AUTHORIZATION AVG

BACKUP BEGIN BECOME BEFORE

BLOCK BODY

CACHE CANCEL CASCADE CHANGE

CHARACTER CHECKPOINT CLOSE COBOL

COMMIT COMPILE CONSTRAINT CONSTRAINTS

CONTENTS CONTINUE CONTROLFILE COUNT

CURSOR CYCLE

DATABASE DATAFILE DBA DEC

DECLARE DISABLE DISMOUNT DOUBLE

DUMP

EACH ENABLE END ESCAPE

EVENTS EXCEPT EXCEPTIONS EXEC

EXPLAIN EXECUTE EXTENT EXTERNALLY

FETCH FLUSH FREELIST FREELISTS

FORCE FOREIGN FORTRAN FOUND

FUNCTION

GO GOTO GROUPS

INCLUDING INDICATOR INITRANS INSTANCE

INT

KEY

Keyword Keyword Keyword Keyword

LANGUAGE LAYER LINK LISTS

LOGFILE

MANAGE MANUAL MAX MAXDATAFILES

MAXINISTANCES MAXLOGFILES MAXLOGHISTORY MAXLOGMEMBERS

MAXTRANS MAXVALUE MIN MINEXTENTS

MINVALUE MODULE MOUNT

NEXT NEW NOARCHIVELOG NOCACHE

NOCYCLE NOMAXVALUE NOMINVALUE NONE

NOORDER NORESETLOGS NORMAL NOSORT

NUMERIC

OFF OLD ONLY OPTIMAL

OPEN OWN

PACKAGE PARALLEL PASCAL PCTINCREASE

PCTUSED PLAN PLI PRECISION

PRIMARY PRIVATE PROCEDURE PROFILE

QUOTA

READ REAL RECOVER REFERENCES

REFERENCING RESETLOGS RESTRICTED REUSE

ROLE ROLES ROLLBACK

SAVEPOINT SCHEMA SCN SECTION

SEGMENT SEQUENCE SHARED SNAPSHOT

351

Page 352: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SOME SORT SQLCODE SQLERROR

STATEMENT_ID STATISTICS STOP STORAGE

SUM SWITCH SYSTEM

TABLES TABLESPACE TEMPORARY THREAD

TIME TRACING TRANSACTION TRIGGERS

TRUNCATE

UNDER UNLIMITED UNTIL USE

USING

WHEN WRITE WORK.

LABELS

参见:BLOCK

语法:<<my_label>>LOOPstatement_1,...,statement_nEND LOOP <<my_label>>

变量:my_label:一个未声明的标识符statement_1,...,statement_n:一个语句序列例子:PL/SQL<<calculate_salary>>LOOPnew_salary:= base_salary + bonus + commission;END LOOP calculate_salary;

LAST_DAY

参见:NEXT_DAY, SYSDATE,

352

Page 353: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ADD_MONTHS

语法:LAST_DAY (d)

变量:d:一个有效的日期型变量例子:PL/SQLDays_Left:= LAST_DAY(SYSDATE) - SYSDATE;SQLSELECT LAST_DAY(SYSDATE) “Last Day” FROM DUAL;Last Day---------30-NOV-97

LEAST

参见:GREATEST, GREATEST_LB,LEAST_LB

语法:LEAST (expn1 [, expn2] ...)

变量:expn:任何一个有效的表达式或列。例子:SQLSELECT LEAST(‘JOHN’, ‘JONNY’, ‘JANARTHAN’) “LEAST” FROM DUAL;LEAST---------JANARTHAN

353

Page 354: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

LEAST_LB

参见:GREATEST, GREATEST_LB, LEAST

语法:LEAST_LB (label1 [, label2] ...)

变量:label:一个 MLSLABEL 类型或 RAW MLSLABEL.类型的变量

LENGTH

参见:LENGTHB

语法:LENGTH (‘x’)

变量:x:一个由单括弧界定的字符类型或 varchar2 类型的变量。例子:PL/SQLVar1:= LENGTH (‘Oracle’);SQLSELECT LENGTH (‘Oracle’) “Length” FROM DUAL;Length---------6

354

Page 355: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

LENGTHB

参见:LENGTH

语法:LENGTHB (‘x’)

变量:x:一个由单括弧界定的CHAR 类型或VARCHAR2 类型的变量。例子:PL/SQLVar1:= LENGTHB (‘Oracle’);SQLSELECT LENGTHB (‘Oracle’) “Length in bytes” FROM DUAL;Length in bytes---------------6

LIKE

参见:AND, OR, NOT

语法:WHERE column1 LIKE ‘valuepattern’

变量:column1:一个你要查找的CHAR 或 VARCHAR2 类型的列。Value:那些与你所要查找的模式相似的值。Pattern:有下面3种模式: 表A-17 LIKE 查找模式示例 模式 例子 查找对象 % ‘abc%’ 以abc开头的值 _ ‘__a’ 在第三位上的是a的值

355

Page 356: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

% ‘%a%a%’ 含有两个a的值

%标号是通配符。_标志是一个位置标志。Oracle 中匹配模式对所给条件是相当敏感的。例子:SQLSELECT NAME_OF_AGENT “AGENT NAME” FROM SALES WHERENAME_OF_AGENT LIKE ‘MICHAEL%’;“AGENT NAME”-------------------MICHAEL GEORGEMICHAEL JORDANMICHAEL MAGNUMSELECT NAME_OF_AGENT FROM SALES WHERE NAME_OF_AGENT LIKE ‘__C’;“AGENT NAME”-------------------MICKYARCHIEMICHAEL

LIST

参见:PAUSE

语法:L[IST] [n|n m|n *|n LAST|*|* n|* LAST|LAST]

变量:n:SQL*Plus 列出的SQL缓冲区里的第n行。n m:SQL*Plus 列出的SQL缓冲区里从m行开始的n行。n *:SQL*Plus 列出的SQL缓冲区里从当前行开始的n行。n LAST:SQL*Plus 缓冲区里从最后一行开始向前的n行。SQL*Plus 将列出这n行。*:SQL*Plus将列出的SQL缓冲区里的当前行。* n:SQL*Plus 缓冲区里从当前行开始向后的n行,SQL*Plus将列出这n行。* LAST:SQL*Plus 将列出的SQL缓冲区里从当前行开始到最后一行结束的所有行。LAST:SQL*Plus 将列出的SQL缓冲区里的最后一行。

356

Page 357: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:SQLL 2

LN

参见:LOG

语法:LN (n)

变量:n:一个大于0的数字变量。例子:PL/SQLVar1:= LN (12);SQLSELECT LN (12) “Logarithm of 12” FROM DUAL;Logarithm of 12---------------2.4849066

LOCK TABLE

参见:COMMIT, ROLLBACK,SAVEPOINT, SET TRANSACTION

语法:LOCK TABLE table_1 [,table_2, ..., table_n] IN lock_mode MODENOWAIT

变量:table_1,...,table_n: 一系列你想通过使用LOCK TABLE语句锁住的数据库表。

357

Page 358: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

lock_mode: 对于某一数据库表你要设定的锁定模式。你可以从如下的锁定模式中任选一个。 EXCLUSIVE SHARE ROW EXCLUSIVE SHARE SHARE UPDATE ROW SHARE ROW EXCLUSIVE

NOWAIT: Oracle will not wait to lock the given Table(s), if the Table(s) is(are) notavailable

例子:SQLLOCK TABLE loan IN SHARE MODE ;LOCK TABLE region IN EXCLUSIVE MODE NOWAIT;LOCK TABLE acct IN SHARE UPDATE MODE;LOCK TABLE bank IN ROW EXCLUSIVE MODE NOWAIT;LOCK TABLE user IN SHARE ROW EXCLUSIVE MODE;LOCK TABLE branch IN ROW SHARE MODE NOWAIT;.

LOG

参见:LN

语法:LOG (m, n)

变量:m:任何一个不是0 或 1的正的数字变量。.n:任何一个正的数字变量。.

例子:PL/SQLVar1:= LOG (12, 2);SQLSELECT LOG (12, 2) “Log base 2 of 12” FROM DUAL;Log base 2 of 12----------------.27894295

358

Page 359: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

LOGIN_DENIED

参见:NOT_LOGGED_ON

语法:EXCEPTIONWHEN LOGIN_DENIED THENstatement_1,...,statement_n

变量:statement_1,...,statement_n:一系列的语句例子:PL/SQLBEGINOPEN loan_cur;LOOPFETCH loan_cur INTO loan_rec;EXIT WHEN loan_cur%NOTFOUND;END LOOP;EXCEPTIONWHEN LOGIN_DENIED THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘ACCESS DENIED’ ;END;

LOOP

参见:EXIT, WHILE-LOOP,FOR-LOOP, EXIT-WHEN

语法:LOOPstatement_1,..., statement_n

359

Page 360: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END LOOP

变量:statement_1,...,statement_n:一系列PL/SQL 将重复执行的语句例子:PL/SQLLOOPTotal_Salary:= Base_Salary + Commission + Bonus;UPDATE salary SET employee_salary = Total_Salary WHEREemployee_number:= emp_id;END LOOP;

LOWER

参见:INITCAP, UPPER

语法:LOWER (‘x’)

变量:x:一个由单括弧界定的字符类型或VARCHAR2类型的变量。例子:PL/SQLVar1:= LOWER (‘ORACLE’);SQLSELECT LOWER (‘ORACLE IS A GOOD DATABASE’) “LowerCase Sentence”FROM DUAL;LowerCase Sentence-------------------------oracle is a good database

LPAD

参见:

360

Page 361: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

RPAD, REPLACE

语法:LPAD (‘x’, n [,’y’])

变量:x:一个由单括弧界定的字符类型或VARCHAR2类型的变量。N:一个正的数字变量。Y;一个由单括弧界定的字符类型或VARCHAR2l类型的变量。这个变量是可选的。如果不指定,缺省是空字符。.

例子:PL/SQLVar1:= LPAD (‘Oracle’, 1);SQLSELECT LPAD (‘ is a good database’, 25, ‘Oracle’) “Example ofLeft Padding” FROM DUAL;Example of Left Padding-------------------------Oracle is a good database

LTRIM

参见:RTRIM

语法:LTRIM (‘x’ [,’y’])

变量:x:一个由单括弧界定的字符类型或VARCHAR2类型的变量。Y:一个由单括弧界定的字符类型或VARCHAR2l类型的变量。这个变量是可选的。如果不指定,缺省是空字符。.

例子:PL/SQLVar1:= LTRIM (‘Oracle’, ‘Or’);SQLSELECT LTRIM (‘The Theresa of all mothers’, ‘The’) “Example ofLTrim” FROM DUAL;

361

Page 362: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Example of LTrim-----------------------Theresa of all mothers

LUB

参见:GLB

语法:LUB ( [DISTINCT | ALL] mls)

变量:DISTINCT:这个选项使函数只考虑那些参数中有不同值的情况,此项是可选的。ALL:这个选项使函数考虑所有的情况,包括参数中有拷贝值。此项是可选的。Mls:这是一个 MLSLABEL.类型的变量。

MAKE_REF

参见:DEREF, REFTOHEX

语法:MAKE_REF(view, key [,key...])

变量:view:你想为其中的行创建引用的对象视图。Key:命令中作为主键的键。例子:SQLCREATE TYPE loan_obj AS OBJECT(loan_amount NUMBER, interest_rate NUMBER);CREATE TABLE loan_table(loan_amount NUMBER, interest_rate NUMBER);CREATE VIEW loan_view

362

Page 363: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

OF loan_tableWITH OBJECT loan_view_obj(loan_amount,interest_rate) ASSELECT * from loan_table;SELECT MAKE_REF(loan_view_obj, 1, 3) FROM DUAL;

MAX

参见:MIN, SUM

语法:MAX ( [DISTINCT | ALL] expn)

变量:DISTINCT:这个选项使函数只考虑那些参数中有不同值的情况,这项是可选的。ALL:这个选项使函数考虑所有的情况包括参数中有相同值,这项是可选的。Expn:这可以是一列SQL查询也可以是一列数学表达式。.

例子:PL/SQLVar1:= MAX (1, 2, 3);SQLSELECT MAX (DAILY_SALES) “Maximum Sales” FROM SALES;Maximum Sales--------------133

MIN

参见:MAX, SUM

语法:MIN ( [DISTINCT | ALL] expn)

变量:

363

Page 364: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DISTINCT:这个选项使函数只考虑那些参数中有不同值的情况,这项是可选的。ALL:这个选项使函数考虑所有的情况包括参数中有相同值,这项是可选的。Expn:这可以是一列SQL查询也可以是一列数学表达式。.

例子:PL/SQLVar1:= MIN (1, 2, 3);SQLSELECT MIN (DAILY_SALES) “Minimum Sales” FROM SALES;Minimum Sales--------------12

MINUS

参见:UNION, UNION ALL, INTERSECT

语法:b1 MINUS b2

变量:b1 and b2 是SELECT语句。例子:SQLSELECT SALES_AMOUNT FROM DAILY_SALES WHERE SALES_DATE =‘09-FEB-96’MINUSSELECT SALES_AMOUNT FROM DAILY_SALES WHERE SALES_DATE =‘09-FEB-97’ ;SHIPPING_T----------199.95

364

Page 365: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

MOD

语法:MOD (x , y)

变量:x:数字变量y:数字变量例子:PL/SQLVar1:= MOD (12, 5);SQLSELECT MOD (12, 5) “Modulus Value of 12/5” FROM DUAL;Modulus Value of 12/5---------------------2

MONTHS_BETWEEN

参见:ADD_MONTHS

语法:MONTHS_BETWEEN (d1, d2)

变量:d1 & d2:有效的日期型变量例子:PL/SQLMONTHS_INBETWEEN:= SYSDATE - SALES_DATE;SQLSELECT MONTHS_BETWEEN (SYSDATE, ‘26-JAN-98’) “MONTHS_INBETWEEN”FROM DUAL;MONTHS_INBETWEEN----------------

365

Page 366: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

-2.53143

NEW_TIME

参见:SYSDATE

语法:NEW_TIME (d, ‘tz1’, ‘tz2’)

变量:d::一个有效的日期型变量tz1 & tz2::下表中的任一时区表A-18 NEW_TIME的时区说明时区1 时区2 说明AST ADT 大西洋标准时间BST BDT 白令海标准时间CST CDT 中部标准时间EST EDT 东部标准时间GMT 格林尼治标准时间HST HDT 阿拉斯加—夏威夷标准时间MST MDT 山区标准时间NST 纽芬兰标准时间PST PDT 太平洋标准时间YST YDT YUKON标准时间例子:PL/SQLLONDON_TIME:= NEW_TIME (SYSDATE, ‘EST’, ‘GMT’)SQLSELECT NEW_TIME (SYSDATE, ‘EST’, ‘GMT’) “LONDON_TIME” FROMDUAL;LONDON_TI---------09-NOV-97.

366

Page 367: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

NEXT_DAY

参见:LAST_DAY, SYSDATE

语法:NEXT_DAY (d, ‘x’)

变量:d::一个有效的日期型变量x: 一个有括号界定的字符变量,它代表星期中的某一天(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, and SUNDAY)

例子:PL/SQLDATE_FOR_NEXT_WEEK:= NEXT_DAY(‘26-JAN-47’,’TUESDAY’);SQLSELECT NEXT_DAY(‘26-JAN-47’,’TUESDAY’) “DATE_AFTER_TUESDAY_26-JAN-47” FROM DUAL;DATE_AFTER---------28-JAN-47

NEXTVAL

参见:CREATE SEQUENCE,CURRVAL, PSEUDOCOLUMN

语法:[user.]sequence.NEXTVAL

变量:user: 创建序列的用户sequence: 你要从中取出下一个值的序列例子:

367

Page 368: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SQL*PlusSELECT loan_seq.NEXTVAL FROM DUAL;

NLS_CHARSET_DECL_LEN

参见:DELETE, UPDATE, SELECT, SELECT INTO

语法:NLS_CHARSET_DECL_LEN (len, char_id)

变量:len: 列的长度char_id::列的ID字符集合例子:SQLSELECT NLS_CHARSET_DECL_LEN (130, nls_charset_id (‘char_cs’))FROM DUAL;

NLS_CHARSET_ID

参见:NLS_CHARSET_DECL_LEN,NLS_CHARSET_NAME

语法:NLS_CHARSET_ID (‘x’)

变量:x: 一个由括号界定的字符串变量例子:SQLSELECT NLS_CHARSET_ID (‘char_cs’)) FROM DUAL;SELECT NLS_CHARSET_ID (‘nchar_cs’)) FROM DUAL;

368

Page 369: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

NLS_CHARSET_NAME

参见:NLS_CHARSET_DECL_LEN,NLS_CHARSET_ID

语法:NLS_CHARSET_NAME (n)

变量:n::一个有效的数值变量例子:SQLSELECT NLS_CHARSET_NAME (2) FROM DUAL;SELECT NLS_CHARSET_NAME (1001) FROM DUAL;

NLS_INITCAP

参见:NLS_LOWER, NLS_UPPER

语法:NLS_INITCAP (‘x’ [,’nlsparm’])

变量:x::一个由单括弧界定的字符变量nlsparm:这个变量确定了排序规则。它可以是语言的排序顺序也可以是 BINARY 排序顺序,语言上的排序顺序主要是针对那些由于事例转换而引起的特殊语言的要求。这个参数是可选的,如果没有给定它,函数就会在此会话期间使用缺省的排序顺序。‘nlsparams’ 值可以有下述形式:‘NLS_SORT = sort’

例子:SQLSELECT NLS_INITCAP(‘strutz’, ‘NLS_SORT = XGerman’) “Sentence”FROM DUAL;

369

Page 370: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Senten------Strutz

NLS_LOWER

参见:NLS_INITCAP, NLS_UPPER

语法:NLS_LOWER (‘x’ [,’nlsparm’])

变量:x::一个由单括弧界定的字符变量nlsparm:这个变量确定了排序规则。它可以是语言的排序顺序也可以是 BINARY 排序顺序,语言上的排序顺序主要是针对那些由于事例转换而引起的特殊语言的要求。这个参数是可选的,如果没有给定它,函数就会在此会话期间使用缺省的排序顺序。‘nlsparams’ 值可以有下述形式:‘NLS_SORT = sort’

例子:SQLSELECT NLS_LOWER (‘strutz’, ‘NLS_SORT = XGerman’) “LowerCaseSentence” FROM DUAL;LowerC------strutz

NLS_UPPER

参见:NLS_INITCAP, NLS_LOWER

语法:NLS_UPPER (‘x’ [,’nlsparm’])

变量:

370

Page 371: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

x::一个由单括弧界定的字符变量nlsparm:这个变量确定了排序规则。它可以是语言的排序顺序也可以是 BINARY 排序顺序,语言上的排序顺序主要是针对那些由于事例转换而引起的特殊语言的要求。这个参数是可选的,如果没有给定它,函数就会在此会话期间使用缺省的排序顺序。‘nlsparams’ 值可以有下述形式:‘NLS_SORT = sort’

例子:SQLSELECT NLS_UPPER (‘strutz’, ‘NLS_SORT = XGerman’) “UpperCaseSentence” FROM DUAL;UpperC------STRUTZ

NO_DATA_FOUND

参见:TOO_MANY_ROWS

语法:EXCEPTIONWHEN NO_DATA_FOUND THENstatement_1,...,statement_n

变量:statement_1,...,statement_n::一系列的语句例子:PL/SQLBEGINOPEN loan_cur;LOOPFETCH loan_cur INTO loan_rec;EXIT WHEN loan_cur%NOTFOUND;END LOOP;EXCEPTIONWHEN NO_DATA_FOUND THENRAISE_APPLICATION_ERROR (-20001,‘No Data Found’);

371

Page 372: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END;

NOAUDIT

参见:AUDIT

语法:NOAUDIT statement | system_privilege BY user [WITHGRANT OPTION] [WHENEVER [NOT] SUCCESSFUL]NOAUDIT object_operating ON schema.object [WHENEVER[NOT] SUCCESSFUL]

变量:statement::你想停止检查的语句system_privilege::你想停止检查的系统权限user::你想停止检查的用户例子:PL/SQLNOAUDIT SELECT TABLE BY john;NOAUDIT CREATE TABLE BY martha;NOAUDIT SELECT ON loanschema.loan WHENEVER SUCCESSFUL;.

NOT_LOGGED_ON

参见:LOGIN_DENIED

语法:EXCEPTIONWHEN NOT_LOGGED_ON THENstatement_1,...,statement_n

变量:statement_1,...,statement_n::一系列的语句

372

Page 373: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:PL/SQLBEGINOPEN loan_cur;LOOPFETCH loan_cur INTO loan_rec;EXIT WHEN loan_cur%NOTFOUND;END LOOP;EXCEPTIONWHEN NOT_LOGGED_ON THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘NOT LOGEED ON’ ;END;

NULL

参见:ASSIGNMENT, DECLARE

语法:IF condition_1 is true THENstatement_1,...,statement_nELSENULLEND IF

变量:condition_1:一个PL/SQL 将判断的确定的条件statement_1,...,statement_n: 一系列如果condition_1 为真 PL/SQL 就迭代执行的语句。例子:PL/SQLIF sales > quota THENTotal_Salary:= Base_Salary + Commission +Bonus;ELSENULL;END IF;

373

Page 374: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

NVL

参见:函数 NULL

语法:NVL (value, substitute)

变量:value::任何一种类型的变量,包括 CHAR, VARCHAR2, NUMBER, DATE, 和其它。substitute: 与 value相同类型的变量,如果substitute 的类型与value不一样此函数就会首先对它进行类型转换。例子:SQLSELECT NVL(SALES_AGENT, ‘AGENT NAME NOT AVAILABLE’) “NAMES OFSALES AGENT” FROM SALES;NAMES OF SALES AGENT-----------------------------------JOHN HOPKINSMICHAEL JORDANAGENT NAME NOT AVAILABLE

OPEN

参见:CLOSE, OPEN-FOR, FETCH

语法:OPEN cursor_name [(parameter_1 [,parameter_2,...,parameter_n]...)]

变量:cursor_name: 你要打开的指定游标的名字。parameter_1,...,parameter_n: 你要传递给游标的参数。

374

Page 375: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:PL/SQLOPEN loan_cur;OPEN loan_cur (1, ‘Bank Holdings, Inc.’, 500000)

OPEN-FOR

参见:CLOSE, OPEN, FETCH

语法:OPEN {cursor_name |:host_cursor_variable_name} FORselect_statement;

变量:cursor_name:你想打开的游标名字。host_cursor_variable_name: 在一个 PL/SQL 主环境中声明的游标变量的名字。host environmentselect_statement: 一个有效的 SELECT 语句,它返回了传送给游标的值。例子:PL/SQLOPEN loan_cur FOR SELECT * FROM loan;OPEN:emp_cur FOR SELECT * FROM employee;OPEN salary_cur FOR SELECT * FROM salary;

运算符

0 + - PRIOR1 * /2 =3 > < !=4 NOT

375

Page 376: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

5 AND6 OR.

运算符— < >

参见:=, <, <=, >, >=

语法:b1 <> b2

变量:b1, b2: 数字变量。例子:PL/SQLIF DAILY_SALES <> (MONTHLY_SALES/30)THENTARGET: = -1END IF;SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE <> ‘09-FEB-96’;DISCOUNT_T----------1222.12

运算符—>

参见: =, !=, <=, <, >=

语法:b1 > b2

376

Page 377: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

变量:b1, b2::数字变量。例子:PL/SQLIF DAILY_SALES > (MONTHLY_SALES/30) THENTARGET: = -1END IF;SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE > ‘09-FEB-96’;DISCOUNT_T----------168.5

运算符—> =

参见:=, !=, <=, <, >

语法:b1 >= b2

变量:b1, b2: 数字变量。例子:PL/SQLIF DAILY_SALES >= (MONTHLY_SALES/30) THENTARGET: = -1END IF;SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE >= ‘09-FEB-96’;DISCOUNT_T----------2268.5

377

Page 378: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

运算符—! =

参见:=, <, <=, < >, >, >=

语法:b1 != b2

变量:b1, b2:数字变量。例子:PL/SQLIF DAILY_SALES != (MONTHLY_SALES/30) THENTARGET: = -1END IF;SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE != ‘09-FEB-96’;DISCOUNT_T----------1222.12

运算符—*

参见: +, -, /

语法:b1 * b2

变量:b1, b2:数字变量。例子:PL/SQLAnnualSalary:= MonthlySalary * 12;

378

Page 379: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DiscountAmount:= ProductValue *DiscountPercent;SQL*PlusSELECT SALES_AMOUNT * 10 DISCOUNT_TOTALFROM DAILY_SALESWHERE SALES_DATE = ‘09-FEB-96’;DISCOUNT_T----------6850

运算符—+

参见: -, *, /

语法:b1 + b2 + ... + bn

变量:b1, b2,..., bn::数字变量。例子:PL/SQLNewSalary:= CurrentSalary + Bonus + Commission + Raise;TotalPayment:= Mortgage + Interest + RealEstateTaxes +Insurance;SQLSELECT SALES_AMOUNT + 4.95 SHIPPING_TOTALFROM DAILY_SALESWHERE SALES_DATE = ‘09-FEB-96’;SHIPPING_T----------699.95

379

Page 380: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

运算符—-*

参见: -, *, /

语法:b1 - b2

变量:b1, b2:数字变量。例子:PL/SQLNetProfit:= Revenue - Expenses;NetPay:= GrossIncome - Taxes;SQLSELECT SALES_AMOUNT - 10.00 DISCOUNT_TOTALFROM DAILY_SALESWHERE SALES_DATE = ‘09-FEB-96’;DISCOUNT_T----------685

运算符—/

参见:+, -, *

语法:b1 / b2

变量:b1, b2:数字变量。例子:PL/SQLMonthlySalary:= AnnualSalary / 12;

380

Page 381: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SQLSELECT SALES_AMOUNT / 10 DISCOUNT_TOTALFROM DAILY_SALESWHERE SALES_DATE = ‘09-FEB-96’;DISCOUNT_T----------68.5

运算符—<=

参见: =, !=, <, >, >=

语法:b1 <= b2

变量:b1, b2::数字变量。例子:PL/SQLIF DAILY_SALES <= (MONTHLY_SALES/30) THENTARGET: = -1END IF;SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE <= ‘09-FEB-96’;DISCOUNT_T----------168.5

运算符—=

参见: !=, <, <=, < >, >, >=

381

Page 382: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:b1 = b2

变量:b1, b2:数字变量。例子:PL/SQLIF DAILY_SALES = (MONTHLY_SALES/30)THENTARGET: = 1END IF;SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE = ‘09-FEB-96’;DISCOUNT_T----------68.5

运算符—AND

参见:OR, NOT

语法:b1 AND b2

变量:b1, b2::任何变量或结果。例子:PL/SQLIF (DAILY_SALES = MONTHLY_SALES/30) AND(ANNUAL_SALES > 0 )THENBONUS: = 100END IF;SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE <= ‘09-FEB-96’ AND SALES_DATE >= ‘09-MAR-96’;

382

Page 383: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DISCOUNT_T----------368.5

运算符—BETWEEN

参见:IN, NOT IN, ANY,ALL, BETWEEN

语法:WHERE column BETWEEN n AND m

变量:n and m:任何相同的数据类型的变量。例子:SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE BETWEEN ‘09-FEB-96’ AND ‘10-FEB-96’;DISCOUNT_T----------68.512.5

运算符—IN

参见:NOT IN, ANY, ALL, BETWEEN

语法:WHERE column IN

例子:SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE IN (‘09-FEB-96’, ‘10-FEB-96’);

383

Page 384: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DISCOUNT_T----------68.512.5

运算符—IS NOT NULL

参见:IS NULL

语法:WHERE column IS NOT NULL

例子:SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE IS NOT NULL;DISCOUNT_T----------12.215.3

运算符—IS NULL

参见:IS NOT NULL

语法:WHERE column IS NULL

例子:SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE IS NULL;DISCOUNT_T----------

384

Page 385: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

10.2

运算符—NOT

参见:AND, OR

语法:b1 NOT b2

变量:b1, b2:结果。

例子:PL/SQLIF NOT (DAILY_SALES != MONTHLY_SALES/30) THENBONUS: = 100END IF;SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE NOT (SALES_DATE = ‘09-FEB-96’);DISCOUNT_T----------4468.5

运算符—NOT BETWEEN

参见:其中运算符,如 IN, NOT IN, ANY, ALL,

BETWEEN

语法:WHERE column NOT BETWEEN n AND m

385

Page 386: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

变量:n and m:任何相同数据类型的变量。例子:SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE NOT BETWEEN ‘09-FEB-96’ AND ‘10-FEB-96’;DISCOUNT_T----------13144.12

运算符—NOT IN

参见:其中运算符,如 IN, ANY, ALL, BETWEEN

语法:WHERE column NOT IN

例子:SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE NOT IN (‘09-FEB-96’, ‘10-FEB-96’);DISCOUNT_T----------100.1262.5

运算符—OR

参见:AND, NOT

386

Page 387: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:b1 OR b2

变量:b1, b2:任何变量或结果。例子:PL/SQLIF (DAILY_SALES = MONTHLY_SALES/30) OR (ANNUAL_SALES >0 )THENBONUS: = 100END IF;SQLSELECT SALES_AMOUNT FROM DAILY_SALESWHERE SALES_DATE <= ‘09-FEB-96’ OR SALES_DATE >= ‘09-MAR-96’;DISCOUNT_T----------3368.5

PRIOR

参见:CONNECT BY

语法:SELECT sql_expn FROM [user.]table WHERE where_conditionCONNECT BY [PRIOR] expn = [PRIOR] expnSTART WITH expn = expnORDER BY expn

变量:sql_expn::一个有效的 SQL 表达式。User:表的所有者。Table: SQL 将再其上执行SELECT的表。where_condition:SQL SELECT 的WHERE 条件。Expn: 任何有效的表达式。例子:SQL

387

Page 388: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SELECT employee_name, department_name FROM employeeCONNECT BY emp_no = PRIOR department_noORDER BY department_no;

PROGRAM_ERROR

参见:NO_DATA_FOUND,TOO_MANY_ROWS,STORAGE_ERROR

语法:EXCEPTIONWHEN PROGRAM_ERROR THENstatement_1,...,statement_n

变量:statement_1,...,statement_n:一系列的语句。例子:PL/SQLBEGINOPEN loan_cur;LOOPFETCH loan_cur INTO loan_rec;EXIT WHEN loan_cur%NOTFOUND;END LOOP;EXCEPTIONWHEN PROGRAM_ERROR THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘INTERNAL PROGRAM ERROR’ ;END;

PROMPT

参见:

388

Page 389: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:PROMPT [text]

变量:text:你要SQL*Plus 显示的一行文本。例子:SQLPROMPTPROMPT The system will be shut down within 10 minutes.

PSEUDOCOLUMN

参见:CURRVAL, LEVEL, NEXTVAL,NULL, ROWID, ROWNUM,SYSDATE, UID, USER

例子:See sections on specific pseudocolumns for 例子:.

RAISE

参见:EXCEPTIONS

语法:RAISE exception_name

变量:exception_name:一个的或用户定义的异常。例子:PL/SQLIF past_due > 90 THENRAISE past_due_exception;

389

Page 390: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END IF;

RAWTOHEX

参见:HEXTORAW

语法:RAWTOHEX (r)

变量:r:一个 RAW.类型的变量。例子:SQLSELECT RAWTOHEX(animation) “Animation” FROM animation;Animation----------------------------------------3D

RECORD

参见:TABLE

语法:TYPE type_name IS RECORD OF( field_name1 {field_type | variable%TYPE |table.column%TYPE | table%ROWTYPE }[NOT NULL],field_name2 {field_type | variable%TYPE |table.column%TYPE | table%ROWTYPE }[NOT NULL] )

变量:type_name:一个在记录的后继声明中使用的类型标识符。field_type:任何包括RECORD和TABLE的数据类型。

390

Page 391: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:PL/SQLDECLARETYPE LoanRecTyp IS RECORD( cname CHAR(50),loan_amount NUMBER (5));loan_rec LoanRecTyp;

BEGINSELECT cust_name, loan_amt INTO loan_rec FROMLOAN;END;DECLARETYPE TimeTyp IS RECORD( minute SMALLINT,hour SMALLINT);TYPE MeetingTyp IS RECORD( day DATE,time TimeTyp,place CHAR(20));meeting MeetingTyp;BEGINmeeting.day := ‘26-JAN-51’;meeting.time.minute := 45;meeting.time.hour := 12;END;.

REFTOHEX

参见:DEREF, MAKE_REF

语法:REFTOHEX (expn)

变量:expn:任何一个返回对象引用的表达式。

391

Page 392: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:SQLCREATE TABLE customer_tab (customer_no NUMBER,loan REF loan_tab);SELECT REFTOHEX (loan) FROM customer_tab;

REMARK

参见:--, /* */

语法:REM[ARK] [comment]

变量:comment:你要包括在命令文件中的注释。例子:SQLREMREM Loan account information

RENAME

参见:COPY

语法:RENAME old TO new

变量:old::你要命名的表、视图、序列或私有同义词。New:表、视图、序列或私有同义词的新名字。例子:SQL

392

Page 393: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

RENAME accounting TO loanacctsRENAME marketing TO sales

REPFOOTER

参见:BTITLE, TTITLE, REPHEADER

语法:REPF[OOTER] [PAGE] [printspec [text | variable]] | [OFF|ON]

变量:printspec:printspec包括下面这些从句,SQL*Plus用它们来放置和格式化报表脚注的文本。

COL n S[KIP] [n] TAB n LE[FT] CE[NTER] R[IGHT] BOLD FORMAT text

Text:报表脚注的文本。Variable:含有下列系统保留值的文本。Values:

SQL.LNO (current line number) SQL.PNO (current page number) SQL.RELEASE (current Oracle release number) SQL.SQLCODE (current error code) SQL.USER (current Username)

例子:SQLREPFOOTER PAGE RIGHT ‘END OF REPORT’REPFOOTER OFFREPFOOTER ON.

393

Page 394: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

REPHEADER

参见:BTITILE, TTITLE, REPFOOTER

语法:REPH[EADER] [PAGE] [printspec [text|variable] ] | [OFF|ON]

变量:printspec:包括下列从句, SQL*Plus用它们来放置和格式化报表表头的文本。

COL n S[KIP] [n] TAB n LE[FT] CE[NTER] R[IGHT] BOLD FORMAT text

Text:报表表头文本。Variable:含有下列系统保留值的变量。Values:

SQL.LNO (current line number) SQL.PNO (current page number) SQL.RELEASE (current Oracle release number) SQL.SQLCODE (current error code) SQL.USER (current Username)

例子:SQLREPHEADER PAGE CENTER ‘TOTAL SALES BY REGION’REPHEADER PAGE BOLD ‘TOTAL UNITS SOLD’REPHEADER OFFREPHEADER ON.

394

Page 395: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

REPLACE

参见:TRANSLATE

语法:REPLACE (‘x’ [,’y’,’z’])

变量:x:应该在单引号中指定的字符型或varchar2 型变量,你想在这个变量中替换字符。Y:应该在单引号中指定的字符型或varchar2 型变量,它指向你想替换的串。它是可选的。Z:应该在单引号中指定的字符型或varchar2 型变量,它指向你想用来替换的串。它是可选的。例子:PL/SQLVar1:= REPLACE (‘Oracle’, ‘Or’, ‘Mir’,);SQLSELECT REPLACE (‘Oracle’, ‘Or’, ‘Mir’) “Example “ FROM DUAL;Example-------Miracle

REPLACE

参见:TRANSLATE

语法:REPLACE (‘x’ [,’y’,’z’])

变量:x:应该在单引号中指定的字符型或varchar2 型变量,你想在这个变量中替换字符。Y:应该在单引号中指定的字符型或varchar2 型变量,它指向你想替换的串。它是可选的。Z:应该在单引号中指定的字符型或varchar2 型变量,它指向你想用来替换的串。它是可选的。

395

Page 396: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:PL/SQLVar1:= REPLACE (‘Oracle’, ‘Or’, ‘Mir’,);SQLSELECT REPLACE (‘Oracle’, ‘Or’, ‘Mir’,); ‘’Example of replacingstrings’’ FROM DUAL;Example of replacing strings----------------------------Miracle

RETURN

参见:Functions, Procedures, RAISE

语法:RETURN [expression]

变量:expression:一个有效表达式。有效表达式包括变量,操作符,文字,函数调用或常量。例子:PL/SQLRETURN loan_bal;RETURN 5;

REVOKE

参见:GRANT

语法:REVOKE system_privilege | role FROM user | role | PUBLICREVOKE system_privilege | role FROM user | role | PUBLICREVOKE object_privilege | ALL ON schema.object FROM user| role | PUBLIC CASCADE CONSTRAINTS

396

Page 397: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

变量:system_privilege:从用户或角色收回的系统权限。object_privilege:从用户或角色收回的系统权限。对象权限可为如下之一:

ALTER DELETE EXECUTE INDEX INSERT REFERENCES SELECT UPDATE

Role:从用户收回的角色。例子:SQLREVOKE ALTER TABLESPACE FROM john;REVOKE GRANT ANY ROLE FROM todd;REVOKE manager FROM imran;REVOKE INSERT ON sales FROM javed;REVOKE ALL ON marketing FROM terry;.

ROLLBACK

参见:COMMIT, SAVEPOINT,SET TRANSACTION, LOCK TABLE

语法:ROLLBACK [WORK ] [TO [SAVEPOINT] savepoint_work]

变量:WORK:可选关键字。使用这个关键字没有实际影响。它仅仅使这条语句看起来更完整一些。.SAVEPOINT:可选关键字。使用这个关键字没有实际影响。它仅仅使这条语句看起来更完整一些。savepoint_work:在当前事务中的在此之前的改变可以由 ROLLBACK 语句取消。例子:SQL

397

Page 398: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

ROLLBACK;ROLLBACK WORK;ROLLBACK TO loan_changes;ROLLBACK TO SAVEPOINT loan_changes;ROLLBACK WORK TO SAVEPOINT loan_changes;

ROUND

参见:TRUNC

语法:ROUND (d [, ‘fmt’])

变量:d:有效的日期型变量。Fmt:在引号中指定的字符变量、表示返回日期的方式。.

表A-20 ROUND 命令的变量方式 结果CC, SCC 世纪SYYYY, YYYY, YEAR, SYEAR, YYY, YY Y 年 (对6月1日进行取整)IYYY, IY, IY I ISO 年Q 季度 (对季度的第二个月份的16号进行取整)MONTH, MON, MM, RM 月份(对月份的16号进行取整)WW 将某周的某一天作为一年的第一天WN 将某周的某一天作为一年的第一天IW 将某周的某一天作为ISO年的第一天W 将某周的某一天作为某月的第一天DDD, DD, J 按天向上取整DAY, DY, D 按周的第一天取整HH, HH12, HH24 按小时取整MI 按分钟取整例子:PL/SQLFISCAL_YEAR:= ROUND (SYSDATE,’YEAR’);SQLSELECT ROUND (SYSDATE,’YEAR’) “CURRENT_FISCAL_YEAR” FROM DUAL;CURRENT_F

398

Page 399: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

---------01-JAN-98

PL/SQLVar1:= ROUND (124.1666, 2);SQLSELECT ROUND (124.16666, -2) “Rounded Value” FROM DUAL;Rounded Value-------------100

ROWIDTOCHAR

参见:CHARTOROWID

语法:ROWIDTOCHAR (r)

变量:r:ROWID类型的变量。.

例子:SQLSELECT ROWIDTOCHAR (ROWID) “VARCHAR2 TYPE” FROM EMPLOYEE;VARCHAR2 TYPE------------------00000545.0001.000500000546.0000.0005

ROWTYPE_MISMATCH

参见:NO_DATA_FOUND,TOO_MANY_ROWS

399

Page 400: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:EXCEPTIONWHEN ROWTYPE_MISMATCH THENstatement_1,...,statement_n

变量:statement_1,...,statement_n:语句序列。例子:PL/SQLBEGINOPEN loan_cur;LOOPFETCH loan_cur INTO emp_rec;EXIT WHEN loan_cur%NOTFOUND;END LOOP;EXCEPTIONWHEN ROWTYPE_MISMATCH THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘ ROWTYPE_MISMATCH INCURSOR’ ;END;

RPAD

参见:LPAD, REPLACE

语法:RPAD (‘x’, n [,’y’])

变量:x:应该在单引号中指定的字符或varchar2 型变量。n:正的数字变量。y:应该在单引号中指定的字符或varchar2 型变量。该变量为可选的。若未指定,则缺省值为空字符。例子:PL/SQL

400

Page 401: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

Var1:= RPAD (‘Oracle’, 1);SQLSELECT RPAD (‘Oracle is a good ‘, 25, ‘database’) “Example ofRight Padding” FROM DUAL;Example of Right Padding-----------------------Oracle is a good database

RTRIM

参见:LTRIM

语法:RTRIM (‘x’ [,’y’])

变量:x:应该在单引号中指定的字符型或varchar2 型变量。Y:应该在单引号中指定的字符型或varchar2 型变量。.这个变量是可选的。若未指定,则缺省值为空字符。例子:PL/SQLVar1:= RTRIM (‘Oracle’, ‘Or’);SQLSELECT RTRIM (‘Mother Theresa, The’, ‘The’) “Example of RightTrimming” FROM DUAL;Example of Right----------------Mother Theresa,

SAVE

参见:SET, EDIT, GET

语法:

401

Page 402: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SAV[E] filename[.ext] [CRE[ATE]|REP[LACE]|APP[END]]

变量:filename:你将把缓冲区中的内容存入的文件。ext:若使用文件后缀,缺省的文件后缀为SQL。例子:SQLSAVE LOANRPTSAVE ACCT.NEW

SAVEPOINT

参见:COMMIT, ROLLBACK, SETTRANSACTION, LOCK TABLE

语法:SAVEPOINT savepoint_work

变量:savepoint_work:在当前事务中用于存储当前的未声明的标识符。例子:SQLSAVEPOINT loan_changes;SAVEPOINT update_loan;

SELECT

参见:基本查询语句 SELECT INTO, DECLARECURSOR, FETCH

语法:SELECT [DISTINCT | ALL] {* | column1[, column2]...}FROM {table_1 | (subquery)} [alias]

402

Page 403: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

[, {table_2 | (subquery)} [alias]]...[WHERE condition][CONNECT BY condition [START WITH condition][GROUP BY expn] [HAVING expn][{ UNION [ALL] | INTERSECT | MINUS } SELECT . . . ][ ORDER BY [expn ] [ ASC | DESC][ FOR UPDATE [OF [user.]table | view] column ][NOWAIT]

变量:item_1,...,item_n:SELECT 语句选择的列。table_1,...,table_n:用于选择数据的数据库表。sub_query:向SELECT 语句提供值和值集的 SELECT语句。Alias:一般是指表的短名字, 或者是在 SELECT语句中引用的视阈。column_1,...,column_n:给定数据和修改表中的指定列。where_condition: 有效的 WHERE 子句。例子:PL/SQLSELECT employee_id, employee_name, employee_titleFROM employeesWHERE employee_id = emp_idORDER BY employee_id;.

SELECT INTO

参见:SELECT, DECLARECURSOR, FETCH

语法:SELECT [DISTINCT | ALL] {* | item_1[, item_2]...}INTO {variable_1[, variable_2]... | record_1}FROM {table_1 | (subquery)} [alias][, {table_2 | (subquery)} [alias]]...rest_of_select_statement;

变量:item_1,...,item_n:SELECT INTO 语句选择并存入给定变量中的项。

403

Page 404: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

variable_1,...,variable_n:将保存数据的变量。record_1:用户定义的记录或 %ROWTYPE 记录使用 SELECT INTO 语句将行的值提取出并置放在该记录中。table_1,...,table_n:从其中选择数据的数据库表。sub_query:向SELECT INTO 语句提供值或侄集的SELECT语句。Alias:一般是SELECT语句中引用的表,或视图的短名字。column_1,...,column_n:指定将要被修改表的列。sql_expression:有效的 SQL 表达式。WHERE search_condition:有效的WHERE 子句,用于指定s将要被修改的行。CURRENT OF cursor_name:与cursor_name指定的游标相关的 FETCH 语句处理的当前行。rest_of_select_statement:在SELECT 语句中FROM子句之后的合法语句。例子:PL/SQLSELECT employee_name, employee_id,employee_titleINTO e_name, e_id, e_titleFROM employeesWHERE employee_id = emp_id;.

SET

参见:EDIT, GET, SAVE

语法:SET variable value

变量:value:系统变量的值。Variable:可以用 SQL*Plus 设置值的系统变量。该变量可以取下列的系统变量。 表A_21 SQL*Plus SET 命令中的变量变量 语法APPI[NFO] {ON|OFF|text}ARRAY[SIZE] {20|n}AUTO[COMMIT] {OFF|ON|IMM[EDIATE]|n}AUTOP[RINT] {OFF|ON}AUTOT[RACE] {OFF|ON|TRACE[ONLY]}EXP[LAIN] [STAT[ISTICS]]BLO[CKTERMINATOR] {.|c}

404

Page 405: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CLOSECUR[SOR] {OFF|ON}CMDS[EP] {;|c|OFF|ON}COLSEP {_|text}COM[PATIBILITY] {V6|V7|NATIVE}CON[CAT] {.|c|OFF|ON}COPYC[OMMIT] {0|n}COPYTYPECHECK {OFF|ON}CRT crtDEF[INE] {‘&’|c|OFF|ON}ECHO {OFF|ON}EDITF[ILE] file_name[.ext]EMBEDDED {OFF|ON}ESC[APE] {\|c|OFF|ON}FEED[BACK] {6|n|OFF|ON}FLAGGER {OFF|ENTRY|INTERMED[IATE]|FULL}FLU[SH] {OFF|ON}HEA[DING] {OFF|ON}HEADS[EP] {||c|OFF|ON}LIN[ESIZE] {80|n}LONG {80|n}LONGC[HUNKSIZE] {80|n}MAXD[ATA] nNEWP[AGE] {1|n}NULL textNUMF[ORMAT] formatNUM[WIDTH] {10|n}PAGES[IZE] {24|n}PAU[SE] {OFF|ON|text}RECSEP {WR[APPED]|EA[CH]|OFF}RECSEPCHAR {_|c}SERVEROUT[PUT] {OFF|ON} [SIZE n] [FOR[MAT] {WRA[PPED]| WOR[D_WRAPPED]|TRU[NCATED]}].SHOW[MODE] {OFF|ON}SQLC[ASE] {MIX[ED]|LO[WER]|UP[PER]}SQLCO[NTINUE] {> |text}SQLN[UMBER] {OFF|ON}SQLPRE[FIX] {#|c}SQLP[ROMPT] {SQL>|text}SQLT[ERMINATOR] {;|c|OFF|ON}SUF[FIX] {SQL|text}TAB {OFF|ON}TERM[OUT] {OFF|ON}TI[ME] {OFF|ON}TIMI[NG] {OFF|ON}

405

Page 406: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

TRIM[OUT] {OFF|ON}TRIMS[POOL] {ON|OFF}UND[ERLINE] {-|c|ON|OFF}VER[IFY] {OFF|ON}WRA[P] {OFF|ON}

例子:SQLSET AUTOPRINT ONSET AUTOCOMMIT OFFSET APPINFO ONSET PAUSE ‘Enter the last name of the customer’SET TIMING OFF.

SET ROLE

参见:ALTER SESSION, ALTER SYSTEM

语法:SET ROLE role_name IDENTIFIED BY passwordSET ROLE ALLSET ROLE ALL EXCEPT role_nameSET ROLE NONE

变量:role_name:你想在当前会话中设置的角色。password: 你要设置的角色的口令。例子:SQLSET ROLE manager IDENTIFIED BY magic;SET ROLE ALL;SET ROLE ALL EXCEPT manager;SET ROLE NONE;

406

Page 407: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SET TRANSACTION

参见:COMMIT, ROLLBACK,SAVEPOINT, LOCK TABLE

语法:SET TRANSACTION{ READ ONLY | READ WRITE | ISOLATION LEVEL {SERIALIZABLE| READ COMMITTED}| USE ROLLBACK SEGMENT rollback_segment_name}

变量:rollback_segment_name:回滚段的名字。例子:SQLSET TRANSACTION READ ONLY;SET TRANSACTION READ WRITE;

SHOW

参见:SET

语法:SHO[W] option

变量:option:该选项可以为下列子句之一:

ALL BTI[TLE] ERR[ORS] [{FUNCTION|PROCEDURE|PACKAGE|PACKAGE

BODY|TRIGGER|VIEW}schema.]name] LABEL LNO

407

Page 408: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

PNO REL[EASE] REPF[OOTER] REPH[EADER] SPOO[L] SQLCODE TTI[TLE] USER

例子:SQLSHOW USERSHOW LNOSHOW BTITLESHOW LABELSHOW LINESIZESHOW ALL.

SIGN

参见:ABS

语法:SIGN (x)

变量:x: 数字型变量。描述SIGN函数返回值的符号。下表表示三种可能情况下的结果值。 表A_22 SIGN函数在数的范围上的结果 x的值 结果 < 0 -1 0 0 > 0 1

例子:PL/SQLVar1:= SIGN (3);SQLSELECT SIGN (-5) “SIGN OF -5” FROM DUAL;

408

Page 409: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SIGN OF -5-----------1.

SIN

参见:COS, COSH, SINH,TAN, TANH

语法:SIN (n)

变量:n:数字型变量。例子:PL/SQLVar1:= SIN (20);SQLSELECT SIN (90) “Sine of 90 degrees” FROM DUAL;Sine of 90 degrees------------------.89399666

SINH

参见:COS, COSH, SIN,TAN, TANH

语法:SINH (n)

变量:n:数字型变量。例子:

409

Page 410: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

PL/SQLVar1:= SINH (20);SQLSELECT SINH (20) “Hyperbolic Sine of 20 deg” FROM DUAL;Hyperbolic Sine of 20 deg-------------------------242582598

SOUNDEX

语法:SOUNDEX (‘x’)

变量:x:应该在单引号中指定字符或Varchar2型变量。例子:SQLSELECT DPL_NAME FROM DENIED_PARTIES_LIST WHERESOUNDEX(DPL_NAME) = SOUNDEX(‘Saddam Hussain’) ;DPL_NAME----------------------------------------------Al HusseniSadda Al Sada.

SPOOL

参见:EDIT, SAVE

语法:SPO[OL] [filename[.ext] | OFF | OUT]

变量:filename:你想输出(spool)的文件名。ext:文件的后缀。缺省的后缀是LST(或LIS)。

410

Page 411: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:SQLSPOOL REPORTSPOOL REPORT OUTSPOOL REPORT OFF

SQLERRM

参见:DECLARE EXCEPTION,EXCEPTION, EXCEPTION_INIT PRAGMA

语法:SQLERRM [n]

变量:n:表示 SQLCODE 取整数值。这是可选项。.

例子:PL/SQLerror_message := SQLERRM (1401);

SQLPLUS

语法:SQLPLUS [[-S[ILENT]] [logon] [start]]|

变量:logon:用户标识,口令和数据库信息的格式如下:username[/password] [@database_specification]|/|/NOLOGstart:在 SQL*Plus 中执行的命令文件。例子:SQLSQLPLUS john/cage

411

Page 412: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SQLPLUS -S john/cageSQLPLUS -S john/cage@LOANSQLPLUS john/cage @LOAN_RPT

SQRT

参见:EXP, POWER

语法:SQRT (n)

变量:n:正的数字变量。例子:PL/SQLVar1:= SQRT (ABS(Var2));SQLSELECT SQRT (4) “Square Root of 4” FROM DUAL;Square Root of 4----------------2

START

参见:@, DEFINE

语法:STA[RT] filename[.ext] [arg_1,...,arg_N]

变量:filename:在 SQL*Plus 中执行的命令文件。Ext:命令文件的后缀,缺省的后缀是 SQL。arg_1,...,arg_N:如果参数可用,则为命令文件参数。

412

Page 413: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:SQLSTART CALCSALARY 1START LOAN_RPTSTART ACCT.QRY

STDDEV

参见:SUM, VARIANCE

语法:STDDEV ( [DISTINCT | ALL] expn)

变量:DISTINCT:该选项使函数只考虑参数的不同值。是可选项。.ALL:这个选项使函数考虑参数中包括所有重复值。该项是可选项。.Expn:可以是SQL查询的一列或是几列的数学表达式。例子:PL/SQLVar1:= STDDEV (1, 2, 3);SQLSELECT STDDEV (DAILY_SALES) “Standard Deviation” FROM SALES;Standard Deviation------------------3416.842

STORAGE

参见:CREATE CLUSTER, CREATEINDEX, CREATE ROLLBACKSEGMENT, CREATE SNAPSHOT,CREATE SNAPSHOT LOG,CREATE TABLE,

413

Page 414: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CREATE TABLESPACE

语法:STORAGE ( [INITIAL n [K | M] )[NEXT n [K | M] ][PCTINCREASE n][MINEXTENTS n][MAXEXTENTS n][OPTIMAL n [K | M] | NULL ][FREELISTS n ][FREELIST GROUP n ]

变量:n:任何有效的正整数变量。STORAGE_ERROR

参见:PROGRAM_ERROR, NO_DATA_FOUND, TOO_MANY_ROWS

语法:EXCEPTIONWHEN STORAGE_ERROR THENstatement_1,...,statement_n

变量:statement_1,...,statement_n:一系列的语句。例子:PL/SQLBEGINOPEN loan_cur;LOOPFETCH loan_cur INTO loan_rec;EXIT WHEN loan_cur%NOTFOUND;END LOOP;EXCEPTIONWHEN STORAGE_ERROR THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘STORAGE ERROR’ ;

414

Page 415: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

END;

STORE

参见:SAVE, GET

语法:STORE {SET} filename[.ext] [CRE[ATE]|REP[LACE]| APP[END]]

变量:filename:你要在其中存储SQL*Plus环境属性的文件名。Ext:若后缀可用,则为文件后缀。例子:SQLSTORE SET MYENVSTORE SET MYENV.NEW APPENDSTORE SET MYENV CREATESTORE SET MYENV.OLD REPLACE

SUBSTR

参见:SUBSTRB

语法:SUBSTR (‘x’ [,y, z])

变量:x:在单引号中指定的字符或Varchar2型的变量。.y:指出替换串起市始位置的数字型变量。是可选项。如果这个项指定为0,则作为1处理。Z:指出需要被替换的字符总数的数字型变量。是可选项。例子:PL/SQLVar1:= SUBSTR (‘Oracle’, 1, 3);

415

Page 416: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SQLSELECT SUBSTR (‘Oracle’, 1, 3) “Substr” FROM DUAL;Sub---Ora

SUBSTRB

参见:SUBSTR

语法:SUBSTRB (‘x’ [,y, z])

变量:x:在单引号中指定的字符或Varchar2型的变量。.y:指出替换串起市始位置的数字型变量。是可选项。如果这个项指定为0,则作为1处理。Z:指出需要被替换的字符总数的数字型变量。是可选项。例子:PL/SQLVar1:= SUBSTRB (‘Oracle’, 1, 3);SQLSELECT SUBSTRB (‘Oracle’, 1, 3) “Substr “ FROM DUAL;Sub---Ora.

SUM

参见:Group by AVG, MAX, MIN,STDDEV, VARIANCE

语法:SUM ( [DISTINCT | ALL] expn)

变量:

416

Page 417: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

DISTINCT:该选项使函数只考虑参数的不同值。是可选项。.ALL:这个选项使函数考虑重复值的所有参数值。该项是可选项。.Expn:可以是SQL查询的一列或是几列的数学表达式。例子:PL/SQLVar1:= SUM (1, 2, 3);SQLSELECT SUM (DAILY_SALES) “SUM” FROM SALES;SUM--------------1212.1221

SYSDATE

参见:PSEUDOCOLUMN

语法:SYSDATE

例子:SQLSELECT SYSDATE “THE DATE TODAY” FROM DUAL;THE DATE---------09-NOV-97

TABLE

参见:RECORD

语法:TYPE type_name IS TABLE OF{ column_type | variable%TYPE | table.column%TYPE } [NOTNULL]

417

Page 418: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

INDEX BY BINARY_INTEGER ;

变量:type_name:在接下来的PL/SQL 表中声明的类型标识。column_type:诸如CHAR,DATE,或 NUMBER的数据类型。例子:PL/SQLDECLARETYPE CnameTabTyp IS TABLE OF CHAR(10)INDEX BY BINARY_INTEGER;Cname_tab CnameTabType;BEGINCname_tab (1) := ‘LARRY’;END;

TAN

参见:COS, COSH, SIN,SINH, TANH

语法:TAN (n)

变量:n:数字型变量。例子:PL/SQLVar1:= TAN (20);SQLSELECT TAN (20) “Tangent of 20 degrees” FROM DUAL;Tangent of 20 degrees---------------------2.2371609

418

Page 419: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

TANH

参见:COS, COSH, SIN,SINH, TAN

语法:TANH (n)

变量:n:数字型变量。例子:PL/SQLVar1:= TANH (20);SQLSELECT TANH (20) “Hyperbolic Tangent of 20 deg” FROM DUAL;Hyperbolic Tangent of 20 deg----------------------------1

TIMEOUT_ON_RESOURCE

参见:NO_DATA_FOUND,TOO_ MANY_ROWS

语法:EXCEPTIONWHEN TIMEOUT_ON_RESOURCE THENstatement_1,...,statement_n

变量:statement_1,...,statement_n:一系列语句。例子:PL/SQL

419

Page 420: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

BEGINOPEN loan_cur;LOOPFETCH loan_cur INTO loan_rec;EXIT WHEN loan_cur%NOTFOUND;END LOOP;EXCEPTIONWHEN TIMEOUT_ON_RESOURCE THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘ TIMEOUT ON RESOURCE ‘ ;END;

TIMING

参见:CLEAR, SET

语法:TIMI[NG] [START text|SHOW|STOP]

变量:text: 计时器的名字。例子:SQLTIMING START new_timerTIMING SHOWTIMING STOP

TO_CHAR (date)

参见:TO_DATE, FORMAT —Date

语法:TO_CHAR (d [, ‘x’, ‘nls_parm’])

420

Page 421: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

变量:d:有效的日期变量。X:在单引号中指定的字符型变量,它表示返回的日期类型。是可选项。nls_parm:指定返回的年、月和日的语言。该参数是可选的。缺省的,它将采用缺省的日期语言。这个参数可以指定为:‘NLS_DATE_LANGUAGE = language’。例子:PL/SQLFISCAL_YEAR:= TO_CHAR (SYSDATE,’YEAR’);

SQLSELECT TO_CHAR (SYSDATE,’YEAR’) “CURRENT_FISCAL_YEAR” FROMDUAL;CURRENT_FISCAL_YEAR-----------------------NINETEEN NINETY-SEVEN.

TO_CHAR (label)

参见:TO_LABEL

语法:TO_CHAR (mls [, ‘x’])

变量:mls:有效的MLSLABEL 变量。X:在单引号中指定的字符变量,它表示返回的字符串的形式。该项是可选的。TO_CHAR (number)

参见:TO_NUMBER,FORMAT —NUMBER

语法:

421

Page 422: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

TO_CHAR (n [, ‘x’, ‘nls_parm’])

变量:n:有效的数字变量。X:在引号中指定的字符变量,它表示返回的数字形式。是可选项。nls_parm:指 定 返 回数字的语言。该 项是可选 项。这个参数可以如下指 定 ‘NLS_NUMERIC_CHARACTERS = ‘’,.’’’‘NLS_CURRENCY = ‘’$’’’

例子:PL/SQLFISCAL_YEAR:= TO_CHAR (786);SQLSELECT TO_CHAR(786,’L99G999D99MI’,’NLS_NUMERIC_CHARACTERS =‘’,.’’ NLS_CURRENCY = ‘’$’’ ‘) “Net Payable” FROM DUAL;Net Payable--------------------$786,00.

TO_DATE (char)

参见:TO_CHAR, TO_NUMBER,FORMAT —DATE

语法:TO_DATE (‘s’ [, ‘x’, ‘nls_parm’])

变量:s:在引号中指定的CHAR 或 VARCHAR2 型变量。X:在引号中指定的字符变量,它表示返回的日期形式。该项是可选的。Nls_parm:指定返回的年、月、日的语言。该参数是可选的。缺省的,它将采用缺省的日期语言。这个参数可以指定为‘NLS_DATE_LANGUAGE = language’。例子:PL/SQLFISCAL_YEAR:= TO_DATE (‘26-JAN-47’);

SQL

422

Page 423: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SELECT TO_DATE (‘01/26/47’, ‘mm/dd/yy’) “REPUBLIC DAY” FROMDUAL;REPUBLIC---------26-JAN-47.

TO_LABEL (char)

参见:TO_CHAR

语法:TO_LABEL (‘s’ [, ‘x’])

变量:s:在引号中指定的有效的CHAR 或 VARCHAR2 型变量。X:在引号中指定的字符型变量,它表示返回的标号方式。该项为可选项。.

TO_MULTI_BYTE (char)

参见:TO_SINGLE_BYTE

语法:TO_MULTI_BYTE (‘s’)

变量:s:在引号中指定的有效的 CHAR 或 VARCHAR2 型变量。

TO_NUMBER (char)

参见:TO_CHAR, TO_DATE,FORMAT —NUMBER

423

Page 424: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

语法:TO_NUMBER (‘s’ [, ‘x’, ‘nls_parm’])

变量:s:在引号中指定的 CHAR 或 VARCHAR2 型变量。X:在引号中指定的字符变量,表示返回的数字的形式,该项是可选项。Nls_parm:指定需要返回值的字符。该参数是可选的。缺省的,它将采用缺省的数字形式。这个参数如下指定: ‘NLS_NUMERIC_CHARACTERS = ‘’,.’’’

‘NLS_CURRENCY = ‘’$’’’

例子:PL/SQLFISCAL_YEAR:= TO_NUMBER (‘1947’);SQLSELECT TO_NUMBER (‘1947’) “FISCAL_YEAR” FROM DUAL;FISCAL_YEAR-----------1947.

TO_SINGLE_BYTE (char)

参见:TO_MULTI_BYTE

语法:TO_SINGLE_BYTE (‘s’)

变量:s:在引号中指定有效的 CHAR 或 VARCHAR2 型变量。

TOO_MANY_ROWS

参见:

424

Page 425: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

NO_DATA_FOUND

语法:EXCEPTIONWHEN TOO_MANY_ROWS THENstatement_1,...,statement_n

变量:statement_1,...,statement_n:一系列语句。例子:PL/SQLDECLAREtotal_salary NUMBER;BEGINSELECT salary INTO total_salary FROM employee;EXCEPTIONWHEN TOO_MANY_ROWS THENUPDATE APPLICATION_ERROR_TABLESET ERROR =‘ MORE THAN 1 ROW FOR THEINTO VARIABLE’ ;END;

TRANSLATE

参见:REPLACE

语法:TRANSLATE (‘x’ [,’y’,’z’])

变量:x:在单引号中指定的字符或varchar2型变量,在该变量中替换字符。Y:在单引号中指定的字符或varchar2型变量,它指向你想替换的字符。Z:在单引号中指定的字符或varchar2型变量,它指向你想替换的字符。.

例子:PL/SQLVar1:= TRANSLATE (‘Oracle’, ‘Or’, ‘Mir’,);

425

Page 426: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SQLSELECT TRANSLATE (‘Oracle’, ‘Or’, ‘Mir’,); ‘’Example oftranslating strings’’ FROM DUAL;Example of translating strings----------------------------Miracle.

TRUNC (date)

参见:ROUND

语法:TRUNC (d [, ‘x’])

变量:d:有效的日期变量。X:在引号中指定的字符变量,它表示返回的日期方式。 表A_24 TRUNC (date) 命令的方式方式 结果CC, SCC 世纪SYYYY, YYYY, YEAR, SYEAR, YYY, YY, Y 年(对6月1日舍入)IYYY, IY, IY, I ISO 年Q 季节 (对季节的第二月份的16号舍入)MONTH, MON, Month,MM, RM 月(对16号舍入)WW 将某周的某一天作为某年的第一天IW 将某周的某一天作为ISO年的第一天W 将某周的某一天作为月份的第一天DDD, DD, J 按日期取整DAY, DY, D 按周的第一天取整HH, HH12, HH24 按小时取整MI 按分钟取整例子:PL/SQLFISCAL_YEAR:= TRUNC (SYSDATE,’YEAR’);SQLSELECT TRUNC (SYSDATE,’YEAR’) “CURRENT_FISCAL_YEAR” FROM DUAL;CURRENT_F

426

Page 427: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

---------01- JAN-97.

TRUNC (number)

参见:ROUND

语法:TRUNC (x [, y])

变量:x: 数字型变量y: 数字型变量(可选)例子:PL/SQLVar1:= TRUNC (124.1666, 2);SQLSELECT TRUNC (124.16666, -2) “Rounded Value” FROM DUAL;Rounded Value-------------100SELECT TRUNC (124.16666, 2) “Rounded Value” FROM DUAL;Rounded Value-------------124.16

TRUNCATERUNCATE

DELETE, DROP TABLE

语法:TRUNCATE [TABLE | CLUSTER]schema.[table][cluster] [DROP | REUSE STORAGE]

变量:

427

Page 428: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

table:希望删除行的表名cluster:希望删除行的CLUSTER名schema:表或 cluster的schema名例子:SQLTRUNCATE TABLE inventory;TRUNCATE CLUSTER marketing DROP STORAGE;TRUNCATE TABLE loan REUSE STORAGE;

TTITLE

参见:BTITLE,REPHEADER, REPFOOTER

语法:TTI[TLE] [printspec [text|variable] ...]|[OFF|ON]

变量:printspec:printspec 包含 SQL*Plus 将用来作为题目的如下语句:

COL n S[KIP] [n] TAB n LE[FT] CE[NTER] R[IGHT] BOLD FORMAT text

text::题目的内容。Variable:包含如下系统维护的变量:

SQL.LNO (当前行数) SQL.PNO (当前页数) SQL.RELEASE (当前 Oracle 版本号) SQL.SQLCODE (当前错误代码) SQL.USER (当前用户名)

例子:SQLTTITLE LEFT ‘ADVENTURE REPORT’TTITLE OFF

428

Page 429: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

TTITLE ON.

UID

参见:USER

语法:UID

变量:无例子:SQLSELECT UID FROM DUAL;UID-----33

UNDEFINE

参见:DEFINE, START

语法:UNDEF[INE] variable_1 ... variable_n

变量:variable_1 ... variable_n:希望删除的变量例子:SQLUNDEFINE myVar1UNDEFINE loan_bal acct_balUNDEFINE myVar1 myVar2 myVar3

429

Page 430: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

UNION

参见:UNION ALL, INTERSECT, MINUS

语法:b1 UNION b2

变量:b1 和 b2 是 SELECT 语句例子:SQLSELECT SALES_AMOUNTFROM DAILY_SALESWHERE SALES_DATE = ‘09-FEB-96’UNIONSELECT SALES_AMOUNTFROM DAILY_SALESWHERE SALES_DATE = ‘09-FEB-97’ ;SHIPPING_T----------699.95122.95

UNION ALL

参见:ALL UNION, INTERSECT,MINUS, SELECT

语法:b1 UNION ALLb2

变量:b1 和 b2 是 SELECT 语句

430

Page 431: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:SQLSELECT SALES_AMOUNTFROM DAILY_SALESWHERE SALES_DATE = ‘09-FEB-96’UNION ALLSELECT SALES_AMOUNTFROM DAILY_SALESWHERE SALES_DATE = ‘09-FEB-97’ ;SHIPPING_T----------699.12122.12111.12112.33

UPDATE

参见:INSERT, DELETE, SELECT,SELECT INTO

语法:UPDATE {table | (sub_query)} [alias]SET { column_name = {sql_expression | (sub_query)}| (column_name[, column_name]...) = (subquery)}[, { column_name = {sql_expression | (subquery)}| (column_name[, column_name]...) = (subquery)}]...[WHERE {search_condition | CURRENT OF cursor_name}];

变量:table:希望更新的表名sub_query:一个 SELECT 子查询alias:别名column_1,...,column_n:列名sql_expression:有效的 SQL表达式WHERE search_condition:有效的 WHERE 子句例子:

431

Page 432: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

SQLUPDATE salarySET employee_salary = Total_SalaryWHERE employee_number:= emp_id;UPDATE employeesSET employee_active_flag = ‘N’WHERE employee_id in(SELECT employee_idFROM department_headWHERE department_active_flag = ‘N’);.

UPPER

参见:INITCAP, LOWER

语法:UPPER (‘x’)

变量:x:单引号中指定的字符型或Varchar2型变量。例子:PL/SQLVar1:= UPPER (‘oracle’);SQLSELECT UPPER (‘oracle is a good database’) “UpperCase Sentence”FROM DUAL;UpperCase Sentence-------------------------ORACLE IS A GOOD DATABASE

USER

参见:UID, PSEUDOCOLUMN

语法:

432

Page 433: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

USER

变量:无例子:SQLSELECT USER FROM DUAL;USER-----FED_REG

USERENV

参见:UID, USER

语法:USERENV (‘type’)

变量:type:可以采用如下的选项并且必须在引号中指定: 表A_25 USERENV 命令的选项设置选项 描述ENTRYID 返回当前用户会话输入的 IDSESSIONID 返回当前用户会话IDTERMINAL 返回当前系统会话的操作系统标识OSDBA 若当前用户会话有OSDBA 角色则返回TRUELABEL 返回当前用户会话标号.LANGUAGE 返回当前用户会话的语言和区域CLIENT_INFO 为当前用户会话返回client_info域的值。这个值由 dbms_application_info.set_client_info 过程设置LANG 返回以ISO 省略形式的3字符表示的当前用户会话使用的语言

例子:SQLSELECT USERENV(‘SESSIONID’) “SESSION ID” FROM DUAL;SESSION ID---------------

433

Page 434: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

21323.

VALUE_ERROR

参见:NO_DATA_FOUND,TOO_MANY_ROWS

语法:EXCEPTIONWHEN VALUE_ERROR THENstatement_1,...,statement_n

变量:statement_1,...,statement_n: 一序列语句例子:PL/SQLDECLAREname VARCHAR2(10);total_salary NUMBER;BEGINtotal_salary:= total_salary * name;EXCEPTIONWHEN VALUE_ERROR THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘VALUE_ERROR -INVALID MULTIPLICATION’ ;END;

VARIABLE

参见:ACCEPT, DEFINE

语法:VAR[IABLE][variable [NUMBER|CHAR|CHAR (n)|VARCHAR2 (n)| REFCURSOR]]

434

Page 435: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

变量:variable: 声明的二进制变量名例子:SQLVARIABLE quota NUMBERVARIABLE last_name CHAR(35)VARIABLE r REFCURSOR

VARIABLE ASSIGNMENT

参见:DECLARE, NULL

语法:a:= 5

变量:a: 用于赋值变量例子:PL/SQLTotal_Salary:= Base_Salary + Commission + Bonus;

VARIANCE

参见:SUM, STDDEV, VARIANCE

语法:VARIANCE ( [DISTINCT | ALL] expn)

变量:DISTINCT: 变量的目标值ALL: 包括重复的在内的所有值expn: 可以是查询的列名或表达式

435

Page 436: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

例子:PL/SQLVar1:= VARIANCE (1, 2, 3);SQLSELECT VARIANCE (DAILY_SALES) “ VARIANCE “ FROM SALES;VARIANCE--------------34.12

VSIZE

参见:LENGTH

语法:VSIZE (v)

变量:v:任何正整数例子:SQLSELECT VSIZE (‘ORACLE’) “VSIZE” FROM DUAL;VSIZE--------6SELECT VSIZE (21.543) “VSIZE” FROM DUAL;VSIZE--------4

RESERVED WORDS

ACCESS ADD ALL ALTERAND ANY AS ASCAUDITBETWEEN BY

436

Page 437: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

CHAR CHECK CLUSTER COLUMNCOMMENT COMPRESS CONNECT CREATECURRENTDATE DECIMAL DEFAULT DELETEDESC DISTINCT DROPELSE EXCLUSIVE EXISTSFILE FLOAT FOR FROMGRANT GROUPHAVINGIDENTIFIED IMMEDIATE IN INCREMENTINDEX INITIAL INSERT INTEGERINTERSECT INTO ISLEVEL LIKE LOCK LONGMAXEXTENTS MINUS MODE MODIFYNOAUDIT NOCOMPRESS NOT NOWAITNULL NUMBEROF OFFLINE ON ONLINEOPTION OR ORDERPCTFREE PRIOR PRIVILEGES PUBLICRAW RENAME RESOURCE REVOKEROW ROWID ROWLABEL ROWNUMROWSSELECT SESSION SET SHARESIZE SMALLINT START SUCCESSFULSYNONYM SYSDATETABLE THEN TO TRIGGERUID UNION UNIQUE UPDATEUSERVALIDATE VALUES VARCHAR VARCHAR2VIEWWHENEVER WHERE WITH.

WHENEVER OSERROR

参见:WHENEVER SQLERROR

语法:WHENEVER OSERROR {EXIT [SUCCESS|FAILURE|n|variable][COMMIT|ROLLBACK]|CONTINUE [COMMIT|ROLLBACK|NONE]}

437

Page 438: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

变量:n:SQL*Plus返回的成功或失败的代码variable:SQL*Plus返回的成功或失败的变量例子:SQLWHENEVER OSERROR EXIT COMMITWHENEVER OSERROR EXIT retcode ROLLBACK.

WHENEVER SQLERROR

参见:WHENEVER OSERROR

语法:WHENEVER SQLERROR {EXIT [SUCCESS|FAILURE|n|variable][COMMIT|ROLLBACK]|CONTINUE [COMMIT|ROLLBACK|NONE]}

变量:n:SQL*Plus返回的成功或失败的代码variable:SQL*Plus返回的成功或失败的变量例子:SQLWHENEVER SQLERROR EXIT COMMITWHENEVER SQLERROR EXIT FAILURE retcode ROLLBACK.

WHILE-LOOP

参见:LOOP, EXIT, FOR-LOOP,EXIT-WHEN

语法:WHILE condition1 is true LOOPstatement_1,...,statement_n;END LOOP

438

Page 439: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

变量:condition_1:PL/SQL 条件statement_1,...,statement_n:一序列PL/SQL 执行语句例子:PL/SQLWHILE Total_Salary > 0 LOOPTotal_Salary:= Base_Salary + Commission + Bonus;UPDATE salary SET employee_salary = Total_Salary WHEREemployee_number:= emp_id;END LOOP;

ZERO_DIVIDE

参见:INVALID_NUMBER

语法:EXCEPTIONWHEN ZERO_DIVIDE THENstatement_1,...,statement_n

变量:statement_1,...,statement_n:a sequence of statements

说明:如果用0 除, PL/SQL 将隐含地启动ZERO_DIVIDE 例外。 相关的错误代码是ORA-01476

例子:PL/SQLDECLAREtotal_salary NUMBER;BEGINtotal_salary:= total_salary / 0;EXCEPTIONWHEN ZERO_DIVIDE THENUPDATE APPLICATION_ERROR_TABLESET ERROR = ‘DIVISION BY ZEROINVALID’ ;END;

439

Page 440: 第二部分 Oracle PL/SQL基础 - pudn.comread.pudn.com/downloads122/ebook/518784/OraclePLSQ…  · Web view使用文字编辑处理软件编辑存储过程源码,要用类似WORD

440