PL/SQL有两种复合数据结构:记录和集合。记录由不同的域组成,集合由不同的元素组成。
记录:
记录是PL/SQL的一种复合数据结构,scalar数据类型和其他数据类型只是简单的在包一级进行预定义,但复合数据类型在使用前必须被定义,记录之所以被称为复合数据类型是因为他由域这种由数据元素的逻辑组所组成。域可以是scalar数据类型或其他记录类型,它与c语言中的结构相似,记录也可以看成表中的数据行,域则相当于表中的列,在表和虚拟表(视图或查询)中非常容易定义和使用,行或记录中的每一列或域都可以被引用或单独赋值,也可以通过一个单独的语句引用记录所有的域。在存储过程或函数中记录也可能有参数。
创建记录:显示定义和隐式定义;一旦记录被定义后,声明或创建定义类型的记录变量,然后才是使用该变量。隐式声明是在基于表的结构或查询上使用%TYPE属性,隐式声明是一个更强有力的工具,这是因为数据变量是动态创建的
显示定义:显示定义记录是在PL/SQL程序块中创建记录变量之前的声明部分定义:
TYPE record_type IS RECORD(field_definition_list);
Field_definition_list是由逗号分隔的列表,语法如下:
Field_name data_type_and_size [NOT NULL][{:=|DEFAULT} default_value]
DECLARE
TYPE stock_quote_rec IS RECORD
(symbol stock.symbol %TYPE,
bid NUMBER(10, 4),
ask NUMBER(10, 4),
volumn NUMBER NOT NULL:=0,
exchange VARCHAR2(6) DEFAULT 'NASDAQ'
);
real_time_quote stock_quote_rec;
variable

域定义时的%TYPE属性用于引用数据库中的表或视图的数据类型和大小,而在此之前程序不知道类型和大小。在上面的例子中记录域在编译时将被定义为与列SYMBOL相同的数据类型和大小,当代码中要使用来自数据库中的数据时,在变量或域定义中最好使用%TYPE来定义。
隐士定义:我们不用描述记录的每一个域,这是因为我们不需要定义记录的结构,不需要使用TYPE,相反在生命记录变量时用%ROWTYPE命令定义与数据库表,试图,游标有相同结构的记录,与TYPE命令相同的是它是一种定义获得数据库记录的好方法。
CURSOR xactions_cur(acct_no IN VARCHAR2) IS
SELECT action, timestamp, holding
FROM portfolios
WHERE account_nbr = 'acct_no';xaction_info xactions_cur%ROWTYPE;
variableDECLARE
CURSOR xactionS_cur IS
SELECT action, timestamp, holding
FROM portfolios
WHERE account_nbr = '37';BEGIN
FOR xaction_rec in xactions_cur
LOOP
IF xaction_rec.holding = 'orcl'
THEN
notify_shareholder;
END IF
END LOOP;
END

使用记录:
用户可以给记录赋值、将值传递给其他程序。记录作为一种复合数据结构意味作他有两个层次可用。用户可以引用整个记录,使用select into或fetch转移所有域,也可以将整个记录传递给一个程序或将所有域的值赋给另一个记录。在更低的层次,用户可以处理记录内单独的域,用户可以给单独的域赋值或者在单独的域上运行布尔表达式,也可以将一个或更多的域传递给另一个程序。
引用记录:记录由域组成,访问记录中的域使用点(.)符号,我们使用上面的例子看看
DECLARE
TYPE stock_quote_rec IS RECORD(
symbol stock.symbol%TYPE,
bid NUMBER(10, 4),
ask NUMBER(10, 4),
volumn NUMBER NOT NULL := 0,
exchange VARCHAR2(6) DEFAULT 'NASDQA'
);TYPE detailed_quote_rec IS RECORD(
quote stock_quote_rec,
timestamp DATE,
bid_size NUMBER,
ask_size NUMBER,
last_tick VARCHAR2(4)
);real_time_detail detail_quote_rec;BEGIN
real_time_detail.bin_size:=1000;
real_time_detail.quote.volumn:=156700;
log_quote(real_time_detail.quote);

给记录赋值:
使用SELECT INTO: 使用SELECT INTO给记录赋值要将记录或域放在INTO子串中,INTO子串中的变量与SELECT中列的位置相对应。
DECLARE
stock_info1 stocks%ROWTYPE;
stock_info2 stocks%ROWTYPE;
BEGIN
SELECT symbol, exchange
INTO stock_info1.symbol, stock_info1.exchange
FROM stocks
WHERE symbol = 'ORCL';SELECT * INTO stock_info2 FROM stocks
WHERE symbol = 'ORCL';
END

使用FETCH:
如果SQL语句返回多行数据或者希望使用带参数的游标,那么就要使用游标,这种情况下使用FETCH语句代替INSTEAD INTO是一个更简单、更有效率的方法,但在安全性较高的包中FETCH的语法如下: FETCH cursor_name INTO variable;
DECLARE
CURSOR stock_cur(symbol_in VARCHAR2) IS
SELECT symbol, exchange, begin_date
FROM stock
WHERE symbol = UPPER(symbol_in);stock_info stock_cur%ROWTYPEBEGIN
OPEN stock_cur('ORCL');
FETCH stock_cur INTO stock_info;

使用赋值语句将整个记录复制给另一个记录是一项非常有用的技术,不过记录必须精确地被声明为相同的类型,不能是基于两个不同的TYPE语句来获得相同的结构。
DECLARE
TYPE stock_quote_rec IS RECORD(
symbol stocks.symbols%TYPE,
bid NUMBER(10, 4),
ask NUMBER(10, 4),
volumn NUMBER
);
TYPE stock_quote_too IS RECORD(
symbol stocks.symbols%TYPE,
bid NUMBER(10, 4),
ask NUMBER(10, 4),
volumn NUMBER
);
stock_one stocks_quote_rec;
stock_two stocks_quote_rec;stock_also stock_rec_too;BEGIN
stock_one.symbol:='orcl';
stock_one.volumn:=12334400;
stock_two:=stock_one; // correct
stock_also:=stock_one; // incorrect, the data type is wrong
stock_also.symbol:=stock_one.symbol;
stock_also.volumn:=stock_one.volumn;
END

记录不能用于INSERT语句和将记录直接用于比较,下面两种情况是错误的:
INSERT INTO stocks VALUES(stock_record);
IF stock_rec1 > stock_rec2 THEN
集合:集合与其他语言中的数组相似,在ORACLE7.3及以前的版本中只有一种集合称为PL/SQL表,这种类型的集合依然保留,就是索引(INDEX_BY)表,与记录相似,集合在定义的时候必须使用TYPE语句,然后才是创建和使用这种类型的变量
集合的类型:index_by表,嵌套表,VARRAY。这三种类型的集合之间由许多差异,包括数据绑定、稀疏性(sparsity)、数据库中的存储能力都不相同。绑定涉及到集合中元素数量的限制,VARRAY集合中的元素的数量是有限Index_by和嵌套表则是没有限制的。稀疏性描述了集合的下标是否有间隔,Index_by表总是稀疏的,如果元素被删除了嵌套表可以是稀疏的VARRAY类型的集合则是紧密的,它的下标之间没有间隔
Index_by表不能存储在数据库中,但嵌套表和VARRAY可以被存储在数据库中。
虽然这三种类型的集合有很多不同之处,但他们也由很多相似的地方:
·         都是一维的类似数组的结构
·         都有内建的方法
·         访问由点分隔
集合的创建:
Index_by
TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY BINRAY_INTEGER;
Eg.
DECLARE
TYPE symbol_tab_typ IS TABLE OF VARCHAR2(5) INDEX BY BINARY_INTEGER;
symbol_tab symbol_tab_typ;
BEGIN

嵌套表:嵌套表非常类似于Index_by表,创建的语法也非常相似。使用TYPE语句,只是没有INDEX BY BINARY_INTEGER子串
TYPE type_name IS TABLE OF element_type [NOT NULL]
VARRAY:
TYPE type_name IS [VARRAY|VARRAYING] (max_size) OF element_type [NOT NULL]
使用集合:像记录一样,集合可以在两个层面上使用
o    操作整个集合
o    访问集合中的 单个元素
第一种情况使用集合名,第二种情况使用下标collection(subscript)
初始化、删除、引用集合:
使用集合之前必须要初始化,对于Index_by表初始化是自动进行的,但是对于嵌套表和VARRAY就必须使用内建的构造函数。如果重新调用,嵌套表和VARRAY自动置NULL,这不只是元素置NULL,而是整个集合置NULL。给集合内的元素赋值需要使用下标符号。将一个集合的值赋给另一个集合,只需要简单的使用赋值操作符
Index_by:
DECLARE
TYPE symbol_tab_typ IS TABLE OF VARCHAR2(5) INDEX BY BINARY_INTEGER;
TYPE account_tab_typ IS TABLE OF accounts%ROWTYPE INDEX BY BINARY_INTEGER;
symbol_tab symbol_tab_typ;
account_tab account_tab_typ;
new_acct_tab account_tab_typ;
BEGIN
SELECT * INTO account_tab(147) FROM accounts WHERE account_nbr = 147;
SELECT * INTO account_tab(-3) FROM accounts WHERE account_nbr = 3003;
IF account_tab(147).balance < 500 THEN
change_maintenance_fee(147);
END IF
new_acct_tab:=account_tab;
symbol_tab(1):='ORCL';
symbol_tab(2):='CSCO';
symbol_tab(3):='SUN';publish_portfolio(symbol_tab);

嵌套表和VARRAY构造函数初始化,构造函数和集合的名字相同,同时有一组参数,每个参数对应一个元素,如果参数为NULL,那么对应的元素就被初始化为NULL,如果创建了元素,但没有填充数据,那么元素将保持null值,可以被引用,但不能保持数据。如果元素没有初始化,那么就不能引用该元素。
DECLARE
TYPE stock_list IS TABLE OF stock.symbol%TYPE;
TYPE top10_list IS VARRAY(10) OF stock.symbol%TYPE;
biotech_stocks stock_list;
tech_10 top10_list;BEGIN
biotech_stocks(1):='AMGN'; // this is illegal, becuase biotech_stocks do not been initialize
IF biotech_stocks IS NULL THEN
biotech_stocks:=('AMGN', 'BGEN', 'IMCL', 'GERN', 'CAR');
END IF;tech_10:=top10_list('ORCL', 'CSCO', 'MSFT', 'INTC', 'SUNW', 'IBM', NULL, NULL);
IF tech_10(7) IS NULL THEN
tech_10(7):='CPQ';
END IF
tech_10(8):='DELL';
END

在这个例子中,嵌套表BIOTECH_STOCKS初始化有5个元素,VARRAY tech_10集合最多能有10 个元素,但构造函数只创建了8个元素,其中还有两个元素是NULL值,在程序中给他们赋值。
初始化基于记录的集合,就必须将记录传递给构造函数,注意不能只是简单的将记录的域传递给构造函数。例如:
DECLARE
TYPE stock_quote_rec IS RECORD(
symbol stock.symbol%TYPE,
bid NUMBER(10, 4),
ask NUMBER(10, 4),
volumn NUMBER NOT NULL:=0
);
TYPE stock_tab_typ IS TABLE OF stock_quote_rec;
quote_list stock_tab_typ;
single_quote stock_quote_rec;BEGIN
single_quote.symbol:='OPCL';
single_quote.bid:=100;
single_quote.ask:=101;
single_quote.volumn:=230000;
quote_list:=stock_tab_typ(single_quote); // legal
quote_list:=stock_tab_typ('CSCO', 43, 323, 323000); // illegal
DBMS_OUTPUT.LINE(quote_list(1).bid);
END

集合的方法:除了构造函数外,集合还有很多内建函数,这些函数称为方法。调用方法的语法如下: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。
 
TRIM
从集合末端开始删除一个元素
对于index_by不合法
TRIM()
从集合末端开始删除x个元素
对index_by不合法
关于集合之间的比较:
集合不能直接比较,要比较两个集合,可以设计一个函数,该函数返回一个标量数据类型。
IF stock_list > stock_list2 --非法
IF sort_collection(stock_list1) > sort_collection(stock_list2) THEN --合法

转载于:https://www.cnblogs.com/garinzhang/archive/2012/06/27/2566511.html

PL/SQL七复合数据结构相关推荐

  1. 全面探讨PL/SQL的复合数据类型

    http://www.yesky.com/20020819/1625866.shtml

  2. Oracle PL/SQL语言初级教程(自学)

    Oracle PL/SQL语言初级教程 PL/SQL 语言基础 PL/SQL 是一种高性能的基于事务处理的语言,能运行在任何 ORACLE 环境中,支持所有数据处理命令. 通过使用 PL/SQL 程序 ...

  3. Oracle PL/SQL 程序设计读书笔记 - 第7章 使用数据

    Oracle PL/SQL 程序设计读书笔记 - 第7章 使用数据 Oracle PL/SQL 程序设计读书笔记 - 第7章 使用数据 7.1 程序数据的命名 PL/SQL要求在给数据结构命名的时候应 ...

  4. Oracle PL/SQL基础知识

    Oracle PL/SQL基础知识 过程(存储过程) 过程用于执行特定的操作,当建立过程时,既可以指定输入参数(in),也可以指定输出参数(out).通过在过程中使用输入参数,可以将数据传递到执行部分 ...

  5. PL/SQL编程1-基础

    编写第一个存储过程 create or replace procedure test_pro1 is begininsert into test1 values('01','zydev');end;/ ...

  6. oracle学习总结2(pl/sql 游标 异常的处理 存储过程和函数 包 触发器)

    pl/sql的学习 给sql添加了逻辑判断与流程控制的功能 语法: declare begin exception end; 运算符 重要的就是赋值运算符了:=        连接  ||       ...

  7. PL/SQL复合变量

    复合变量可以将不同数据类型的多个值存储在一个单元中.由于复合类型可以由用户自己根据需要定义其结构,所以复合数据类型也称为自定义数据类型. 在PL/SQL中,使用%TYPE声明的变量类型与数据表中字段的 ...

  8. 第七章 控制PL/SQL错误

    一.错误控制一览 在PL/SQL中,警告或错误被称为异常.异常可以是内部(运行时系统)定义的或是用户定义的.内部定义的案例包括除零操作和内存溢出等.一些常见的内部异常都有一个预定义的名字,如ZERO_ ...

  9. PL/SQL复合数据类型

    --一.PL/SQL复合数据类型 --(一).PL/SQL记录 --1.定义PL/SQL记录 --(1).定义PL/SQL记录 --Grammar TYPE type_name IS RECORD(f ...

最新文章

  1. Android使用ViewPager实现左右循环滑动及轮播效果
  2. 苹果电脑如何删除软件_软件开发公司误将委托人系统数据删除,责任如何认定?...
  3. C/C++运行时库 解释
  4. 运行Qt release版本时出现“丢失QtCore4.dll”错误
  5. seaborn.FacetGrid
  6. “退学吧,开始行动”——埃里森在耶鲁的演讲(历史上最牛的演讲)
  7. 面试官:Java为什么只有值传递?
  8. 架设流媒体服务器[转]
  9. git更新pull报错Pulling 1 repository Remote does not have refs/heads/rel5.1 available for fetch
  10. 虾米回应“关闭”消息:不予置评;明年 Win 10 或将原生运行安卓应用;Perl 项目治理新规| 极客头条...
  11. string-indexOf、substring、split
  12. MySQL解压缩版配置安装详解【图解】
  13. 解决TortoiseGit文件夹和文件状态图标不显示问题
  14. 人脸识别及数据流处理
  15. java倒计时器_Java并发系列5--倒计时器CountDownLatch
  16. Modern C++ JSON nlohmann::json 使用详解
  17. 蓝桥杯计算机软件大赛什么时间,“蓝桥杯”全国软件设计大赛
  18. 早间简评:黄金亚盘快速下跌   1300关口岌岌可危?
  19. 2021年中国5G手机发展现状及市场竞争格局分析:华为持续领跑国内5G手机市场[图]
  20. 解决U盘受保护(适用于U盘或移动硬盘)-亲测有效

热门文章

  1. Linux系统下各文件目录的含义 入门
  2. linux终端刷新网络命令,在Ubuntu Linux操作系统中重新启动网络的方法
  3. 个人见解:*与(c语言)
  4. [攻防世界 pwn]——level0
  5. html flash 动画效果代码大全,flash动作代码大全
  6. linux下kill多个进程
  7. tp5 模型中配置数据库连接信息
  8. vue路由切换和用location切换url的区别
  9. jquery ajax 滚动加载数据
  10. TeraTerm设定(窗体大小,字体字号)保存为默认值