PL/SQL有两种复合数据结构:记录和集合。记录由不同的域组成,集合由不同的元素组成。在本文中我们将讨论记录和集合的类型、怎样定义和使用记录和集合。
PL/SQL 记录
记录是PL/SQL的一种复合数据结构,scalar数据类型和其他数据类型只是简单的在包一级进行预定义,但复合数据类型在使用前必须被定义,记录之所以被称为复合数据类型是因为他由域这种由数据元素的逻辑组所组成。域可以是scalar数据类型或其他记录类型,它与c语言中的结构相似,记录也可以看成表中的数据行,域则相当于表中的列,在表和虚拟表(视图或查询)中非常容易定义和使用,行或记录中的每一列或域都可以被引用或单独赋值,也可以通过一个单独的语句引用记录所有的域。在存储过程或函数中记录也可能有参数。
创建记录
在PL/SQL中有两种定义方式:显式定义和隐式定义。一旦记录被定义后,声明或创建定义类型的记录变量,然后才是使用该变量。隐式声明是在基于表的结构或查询上使用%TYPE属性,隐式声明是一个更强有力的工具,这是因为这种数据变量是动态创建的。
显式定义记录
显式定义记录是在PL/SQL程序块中创建记录变量之前在声明部分定义。使用type命令定义记录,然后在创建该记录的变量。语法如下:
TYPE record_type IS RECORD (field_definition_list); |
field_definition_list是由逗号分隔的列表。
域定义的语法如下:
field_name data_type_and_size [NOT NULL][{:=|DEFAULT} default_value] |
域名必须服从与表或列的命名规则相同的命名规则。下面我们看一个例子:
DELCARE |
域定义时的%TYPE属性用于引用数据库中的表或视图的数据类型和大小,而在此之前程序不知道类型和大小。在上面的例子中记录域在编译时将被定义为与列SYMBOL相同的数据类型和大小,当代码中要使用来自数据库中的数据时,在变量或域定义中最好使用%TYPE来定义。
隐式定义记录
隐式定义记录中,我们不用描述记录的每一个域。这是因为我们不需要定义记录的结构,不需要使用TYPE语句,相反在声明记录变量时使用%ROWTYPE命令定义与数据库表,视图,游标有相同结构的记录,与TYPE命令相同的是它是一种定义获得数据库数据记录的好方法。
DECLARE |
有一些PL/SQL指令在使用隐式定义记录时没有使用%ROWTYPE属性,比如游标FOR循环或触发器中的:old和:new记录。
DELCARE |
使用记录
用户可以给记录赋值、将值传递给其他程序。记录作为一种复合数据结构意味作他有两个层次可用。用户可以引用整个记录,使用select into或fetch转移所有域,也可以将整个记录传递给一个程序或将所有域的值赋给另一个记录。在更低的层次,用户可以处理记录内单独的域,用户可以给单独的域赋值或者在单独的域上运行布尔表达式,也可以将一个或更多的域传递给另一个程序。
引用记录
记录由域组成,访问记录中的域使用点(.)符号。我们使用上面的例子看看
DELCARE |
给记录赋值
给记录或记录中的域赋值的方法有几种,可以使用SELECT INTO或FETCH给整个记录或单独的域赋值, 可以将整个记录的值赋给其他记录,也可以通过给每个域赋值来得到记录,以下我们通过实例讲解每一种赋值方法。
1、使用SELECT INTO
使用SELECT INTO给记录赋值要将记录或域放在INTO子串中,INTO子串中的变量与SELECT中列的位置相对应。
例:
DECLARE |
2、使用FETCH
如果SQL语句返回多行数据或者希望使用带参数的游标,那么就要使用游标,这种情况下使用FETCH语句代替INSTEAD INTO是一个更简单、更有效率的方法,但在安全性较高的包中FETCH的语法如下:
FETCH cursor_name INTO variable; |
我们改写上面的例子:
DECLARE |
使用赋值语句将整个记录复制给另一个记录是一项非常有用的技术,不过记录必须精确地被声明为相同的类型,不能是基于两个不同的TYPE语句来获得相同的结构。
例:
DECLARE |
记录不能用于INSERT语句和将记录直接用于比较,下面两种情况是错误的:
INSERT INTO stocks VALUES (stock_record);
和
IF stock_rec1>stock_rec2 THEN
要特别注意考试中试题中有可能用%ROWTYPE来欺骗你,但这是错误的,记住这一点。还有可能会出现用记录排序的情况,ORACLE不支持记录之间的直接比较。对于记录比较,可以采用下面的两个选择:
. 设计一个函数,该函数返回scalar数据类型,使用这个函数比较记录,如
IF sort_rec(stock_one)>sort_rec(stock_two) THEN |
. 可以使用数据库对象,数据库对象可以使用order或map方法定义,允许oracle对复合数据类型进行比较。关于数据库对象的讨论已经超越了本文的范围,要详细了解数据库对象,可以查阅oracle手册。
PL/SQL集合
集合与其他语言中的数组相似,在ORACLE7.3及以前的版本中只有一种集合称为PL/SQL表,这种类型的集合依然保留,就是索引(INDEX_BY)表,与记录相似,集合在定义的时候必须使用TYPE语句,然后才是创建和使用这种类型的变量。
集合的类型
PL/SQL有三种类型的集合
. Index_by表
. 嵌套表
. VARRAY
这三种类型的集合之间由许多差异,包括数据绑定、稀疏性(sparsity)、数据库中的存储能力都不相同。绑定涉及到集合中元素数量的限制,VARRAY集合中的元素的数量是有限,Index_by和嵌套表则是没有限制的。稀疏性描述了集合的下标是否有间隔,Index_by表总是稀疏的,如果元素被删除了嵌套表可以是稀疏的,但VARRAY类型的集合则是紧密的,它的下标之间没有间隔。
Index_by表不能存储在数据库中,但嵌套表和VARRAY可以被存储在数据库中。
虽然这三种类型的集合有很多不同之处,但他们也由很多相似的地方:
. 都是一维的类似数组的结构
. 都有内建的方法
. 访问由点分隔
Index_by表
Index_by表集合的定义语法如下:
TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX |
这里面重要的关键字是INDEX BY BINARY_INTERGET,没有这个关键字,那么集合将是一个嵌套表,element_type可以是任何合法的PL/SQL数据类型,包括:PLS/INTEGER、SIGNTYPE、和BOOLEAN。其他的集合类型对数据库的数据类型都有限制,但Index_by表不能存储在数据库中,所以没有这些限制。
一旦定义了index_by表,就可以向创建其他变量那样创建index_by表的变量:
DECLARE |
嵌套表
嵌套表非常类似于Index_by表,创建的语法也非常相似。使用TYPE语句,只是没有INDEX BY BINARY_INTEGER子串。
TYPE type_name IS TABLE OF element_type [NOT NULL]
NOT NULL选项要求集合所有的元素都要有值,element_type可以是一个记录,但是这个记录只能使用标量数据类型字段以及只用于数据库的数据类型(不能是PLS_INTEGER,BOOLEAN或SIGNTYPE)。
嵌套表和VARRAY都能作为列存储在数据库表中,所以集合自身而不是单个的元素可以为NULL,ORACLE称这种整个集合为NULL的为"自动设置为NULL(atomically NULL)"以区别元素为NULL的情况。当集合为NULL时,即使不会产生异常,用户也不能引用集合中的元素。用户可以使用IS NULL操作符检测集合是否为NULL。
存储在一个数据库中的嵌套表并不与表中的其它数据存放在同一个数据块中,它们实际上被存放在第二个表中。正如没有order by子句select语句不能保证返回任何有顺序的数据,从数据库中取回的嵌套表也不保证元素的顺序。由于集合数据是离线存储的,对于大型集合嵌套表是一个不错的选择。
VARRAY
VARRAY或数据变量都有元素的限制。想起他集合一样VARRAY定义仍然使用TYPE语句,但关键字VARRAY或VARRYING ARRAY告诉ORACLE这是一个VARRAY集合。
TYPE type_name IS [VARRAY|VARYING ARRAY] (max_size) OF |
max_size是一个整数,用于标示VARRAY集合拥有的最多元素数目。VARRAY集合的元素数量可以低于max_size,但不能超过max_size。element_type是一维元素的数据类型,如果element_type是记录,那么这个记录只能使用标量数据字段(与嵌套标相似)。NOT NULL子串表示集合中的每一个元素都必须有值。
与嵌套表相似,VARRAY能够自动为NULL,可以使用IS NULL操作符进行检测。与嵌套表不同的是,当VARRAY存储在数据库中时与表中的其他数据存放在同一个数据块中。正象列的排序保存在表的SELECT*中一样元素的顺序保存在VARRAY中。同样由于集合是在线存储的,VARRAY很适合于小型集合。
窗体顶端
用户登录 注册 天极IT搜索 天极传媒:Yesky | ChinaByte | IT专家网 | Impress中文站
窗体底端
天极网分站
·
笔记本
·
台式机
·
手机
·
·
DIY硬件
·
· 数
码
·
数码相机
·
摄像机
·
·
外设
·
网络
·
服务器
·
数字家庭
·
Vista
查产品 看行情 经销商 导购 评测 | 软件 设计 网页 开发 安全 论坛 | 群乐 E时代 游戏 视频 壁纸 动漫 社区 下载 网摘 博客 科技奥运
|
|
|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
集合的方法
除了构造函数外,集合还有很多内建函数,这些函数称为方法。调用方法的语法如下:
collection.method
下表中列出oracle中集合的方法
方法 | 描述 | 使用限制 |
COUNT | 返回集合中元素的个数 | |
DELETE | 删除集合中所有元素 | |
DELETE() | 删除元素下标为x的元素,如果x为null,则集合保持不变 | 对VARRAY非法 |
DELETE(,) | 删除元素下标从X到Y的元素,如果X>Y集合保持不变 | 对VARRAY非法 |
EXIST() | 如果集合元素x已经初始化,则返回TRUE, 否则返回FALSE | |
EXTEND | 在集合末尾添加一个元素 | 对Index_by非法 |
EXTEND() | 在集合末尾添加x个元素 | 对Index_by非法 |
EXTEND(,) | 在集合末尾添加元素n的x个副本 | 对Index_by非法 |
FIRST | 返回集合中的第一个元素的下标号,对于VARRAY集合始终返回1。 | |
LAST | 返回集合中最后一个元素的下标号, 对于VARRAY返回值始终等于COUNT. | |
LIMIT | 返回VARRY集合的最大的元素个数,对于嵌套表和对于嵌套表和Index_by为null | Index_by集合无用 |
NEXT() | 返回在元素x之后及紧挨着它的元素的值,如果该元素是最后一个元素,则返回null. | |
PRIOR() | 返回集合中在元素x之前紧挨着它的元素的值,如果该元素是第一个元素,则返回null。 | |
TRI M | 从集合末端开始删除一个元素 | 对于index_by不合法 |
TRIM() | 从集合末端开始删除x个元素 | 对index_by不合法 |
关于集合之间的比较
集合不能直接用于比较,要比较两个集合,可以设计一个函数,该函数返回一个标量数据类型。
IF stock_list1>stock_list2 ----非法 |
但可以比较在集合内的两个元素。