📄 第五章 pl-sql集合与记录(2) - pl-sql用户指南与参考 - whatiswhat.htm
字号:
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P class=title2>3、使用RETURNING INTO子句将DML的操作结果绑定到集合</P>
<P>我们还可以在INSERT、UPDATE或DELETE语句的RETURNING INTO子句中使用BULK
COLLECT来进行数据绑定,示例如下: </P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>DECLARE</STRONG><BR> <STRONG>TYPE</STRONG> numlist <STRONG>IS</STRONG> <STRONG>TABLE</STRONG> <STRONG>OF</STRONG> emp.empno%<STRONG>TYPE</STRONG>;<BR><BR> enums numlist;<BR><STRONG>BEGIN</STRONG><BR> <STRONG>DELETE</STRONG> <STRONG>FROM</STRONG> emp<BR> <STRONG>WHERE</STRONG> deptno = 20<BR> RETURNING empno<BR> <STRONG>BULK</STRONG> <STRONG>COLLECT</STRONG> <STRONG>INTO</STRONG> enums;<BR> <EM>-- if there were five employees in department 20,</EM><BR> <EM>-- then enums contains five employee numbers</EM><BR><STRONG>END</STRONG>;
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P class=title2>4、BULK COLLECT的限制</P>
<P>下面是使用BULK COLLECT的一些限制: </P>
<OL>
<LI>不能对使用字符串类型作键的关联数组使用BULK COLLECT子句。
<LI>只能在服务器端的程序中使用BULK
COLLECT,如果在客户端使用,就会产生一个不支持这个特性的错误。
<LI>BULK COLLECT INTO的目标对象必须是集合类型,如下例所示:
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>DECLARE</STRONG><BR> <STRONG>TYPE</STRONG> namelist <STRONG>IS</STRONG> <STRONG>TABLE</STRONG> <STRONG>OF</STRONG> emp.ename%<STRONG>TYPE</STRONG>;<BR><BR> names namelist;<BR> salary emp.sal%<STRONG>TYPE</STRONG>;<BR><STRONG>BEGIN</STRONG><BR> <STRONG>SELECT</STRONG> ename, sal<BR> <STRONG>BULK</STRONG> <STRONG>COLLECT</STRONG> <STRONG>INTO</STRONG> names, salary <EM>-- illegal target</EM><BR> <STRONG>FROM</STRONG> emp<BR> <STRONG>WHERE</STRONG> <STRONG>ROWNUM</STRONG> < 50;<BR> ...<BR><STRONG>END</STRONG>;
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<LI>复合目标(如对象类型)不能在RETURNING INTO子句中使用。
<LI>如果有多个隐式的数据类型转换的情况存在,多重复合目标就不能在BULK COLLECT
INTO子句中使用。
<LI>如果有一个隐式的数据类型转换,复合目标的集合(如对象类型集合)就不能用于BULK COLLECT
INTO子句中。 </LI></OL>
<P class=title2>5、把FORALL和BULK COLLECTION结合起来使用</P>
<P>我们可以把BULK
COLLECT和FORALL语句结合起来使用,这时,SQL引擎会批量绑定字段值。下例中,如果集合depts有三个元素,每个元素都能执行五次DELETE操作,当语句执行完毕的时候,enums中就会有十五个元素:
</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>FORALL</STRONG> j <STRONG>IN</STRONG> depts.FIRST .. depts.LAST<BR> <STRONG>DELETE</STRONG> <STRONG>FROM</STRONG> emp<BR> <STRONG>WHERE</STRONG> empno = depts(j)<BR> RETURNING empno<BR> <STRONG>BULK</STRONG> <STRONG>COLLECT</STRONG> <STRONG>INTO</STRONG> enums;
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>我们不能在FORALL语句中使用SELECT ... BULK
COLLECT语句。否则,就会得到一条错误消息:不能在SELECT语句中同时使用FORALL和BULK
COLLECT INTO(cannot use FORALL and BULK COLLECT INTO
together in SELECT statements)。 </P>
<P class=title2>6、使用主数组进行批量绑定 </P>
<P>客户端程序可以使用匿名PL/SQL块来把数据批量地从主数组中输入或批量地输出到主数组。实际上,这是与服务器端交互传递集合的最高效的方法。</P>
<P>主数组是声明在主环境中的,如OCI或Pro*C程序,并且必须以冒号为前缀,以区别于PL/SQL集合。在下面的例子中,DELETE语句中使用到一个输入主数组。运行时,匿名PL/SQL块被发送到数据库服务器端执行:
</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>DECLARE</STRONG><BR> ...<BR><STRONG>BEGIN</STRONG><BR> <EM>-- assume that values were assigned to the host array</EM><BR> <EM>-- and host variables in the host environment</EM><BR> <STRONG>FORALL</STRONG> i <STRONG>IN</STRONG> :lower..:upper<BR> <STRONG>DELETE</STRONG> <STRONG>FROM</STRONG> emp <BR> <STRONG>WHERE</STRONG> deptno = :depts(i);<BR> ...<BR><STRONG>END</STRONG>;
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P class=title1>十五、什么是记录</P>
<P>记录就是相关的数据项集中存储在一个单元中,每项都有它自己的名字和数据类型。假定我们有关于雇员的各种数据信息,如名字、薪水和雇佣日期,这些项在逻辑上是相关联的,但类型不相似。记录可以把它所拥有的每一项当作一个逻辑单元,这样就便于组织和表现信息。
</P>
<P>%ROWTYPE属性能让我们声明代表数据表中一行记录的类型。但是我们不能利用它指定或声明自己的数据类型。不过没关系,RECORD关键字可以满足我们定义自己的记录的要求。
</P>
<P class=title1>十六、定义和声明记录</P>
<P>要创建记录,我们就得先声明记录类型,然后声明该类型的记录。我们可以在PL/SQL块、子程序或包的声明部分使用下面的语法来定义RECORD类型:</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>TYPE</STRONG> type_name <STRONG>IS</STRONG> <STRONG>RECORD</STRONG> (field_declaration[,field_declaration]...);
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>其中field_declaration的形式如下: </P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap>field_name field_type [[<STRONG>NOT</STRONG> <STRONG>NULL</STRONG>] {:= | <STRONG>DEFAULT</STRONG>} expression]
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>type_name是声明记录用的类型区分符,field_type是除了REF
CURSOR以外的任何PL/SQL数据类型,expression的结果值与field_type相同。 </P>
<P>注意:与VARRAY类型和TABLE(嵌套)类型不同的是,RECORD是不能存在于数据库中的。</P>
<P>创建记录时也可以使用%TYPE和%ROWTYPE来指定记录各个域的类型。下例中,我们定义了一个名为DeptRec的记录类型:</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>DECLARE</STRONG><BR> <STRONG>TYPE</STRONG> deptrec <STRONG>IS</STRONG> <STRONG>RECORD</STRONG>(<BR> dept_id dept.deptno%<STRONG>TYPE</STRONG>,<BR> dept_name <STRONG>VARCHAR2</STRONG>(14),<BR> dept_loc <STRONG>VARCHAR2</STRONG>(13)<BR> );<BR><STRONG>BEGIN</STRONG><BR> ...<BR><STRONG>END</STRONG>;
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>在下面的例子中,我们在记录类型中包含对象、集合和其他的记录(又叫嵌套记录)。但是对象类型中不能把RECORD类型作为它的属性。
</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>DECLARE</STRONG><BR> <STRONG>TYPE</STRONG> timerec <STRONG>IS</STRONG> <STRONG>RECORD</STRONG>(<BR> seconds <STRONG>SMALLINT</STRONG>,<BR> minutes <STRONG>SMALLINT</STRONG>,<BR> hours <STRONG>SMALLINT</STRONG><BR> );<BR><BR> <STRONG>TYPE</STRONG> flightrec <STRONG>IS</STRONG> <STRONG>RECORD</STRONG>(<BR> flight_no <STRONG>INTEGER</STRONG>,<BR> plane_id <STRONG>VARCHAR2</STRONG>(10),<BR> captain employee, <EM>-- declare object</EM><BR> passengers passengerlist, <EM>-- declare varray</EM><BR> depart_time timerec, <EM>-- declare nested record</EM><BR> airport_code <STRONG>VARCHAR2</STRONG>(10)<BR> );<BR><STRONG>BEGIN</STRONG><BR> ...<BR><STRONG>END</STRONG>;
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P>下面的例子演示了如何将函数的返回类型指定为RECORD类型: </P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>DECLARE</STRONG><BR> <STRONG>TYPE</STRONG> emprec <STRONG>IS</STRONG> <STRONG>RECORD</STRONG>(<BR> emp_id <STRONG>NUMBER</STRONG>(4),<BR> last_name <STRONG>VARCHAR2</STRONG>(10),<BR> dept_num <STRONG>NUMBER</STRONG>(2),<BR> job_title <STRONG>VARCHAR2</STRONG>(9),<BR> salary <STRONG>NUMBER</STRONG>(7, 2)<BR> );<BR> ...<BR> <STRONG>FUNCTION</STRONG> nth_highest_salary(n <STRONG>INTEGER</STRONG>)<BR> <STRONG>RETURN</STRONG> emprec <STRONG>IS</STRONG> ...<BR> <STRONG>BEGIN</STRONG><BR> ...<BR> <STRONG>END</STRONG>;
</TD></TR></TBODY></TABLE></BLOCKQUOTE>
<P class=title2>1、声明记录</P>
<P>一旦定义了RECORD类型,我们就可以声明该类型的记录。如下例所示,标识符item_info代表了整条记录:
</P>
<BLOCKQUOTE>
<TABLE>
<TBODY>
<TR>
<TD
noWrap><STRONG>DECLARE</STRONG><BR> <STRONG>TYPE</STRONG> stockitem <STRONG>IS</STRONG> <STRONG>RECORD</STRONG>(<BR> item_no <STRONG>INTEGER</STRONG>(3),<BR> description <STRONG>VARCHA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -