⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 第六章 pl-sql与oracle间交互 - pl-sql用户指南与参考 - whatiswhat.htm

📁 sql初学者不错的教程
💻 HTM
📖 第 1 页 / 共 5 页
字号:
                        <P>游标是可以接收参数的,这些参数可以在关联查询中允许出现常量的地方使用。游标的形式参数都必须是IN模式的。因此,它们不能把值赋给实际参数。并且,我们不能给游标的参数添加NOT 
                        NULL约束。</P>
                        <P>如下例所示,我们为游标参数初始化一个默认值。这样,我们就能给游标传递不同个数的实参。并且,我们还可以在不改变游标引用的情况下添加新的参数。</P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>DECLARE</STRONG><BR>&nbsp;&nbsp;<STRONG>CURSOR</STRONG>&nbsp;c1&nbsp;(low&nbsp;<STRONG>INTEGER</STRONG>&nbsp;<STRONG>DEFAULT</STRONG>&nbsp;0,&nbsp;high&nbsp;<STRONG>INTEGER</STRONG>&nbsp;<STRONG>DEFAULT</STRONG>&nbsp;99)&nbsp;<STRONG>IS</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>SELECT</STRONG>&nbsp;*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;... 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>游标参数作用域对于游标来说是本地的,这也就意味着它们只能在游标声明时所指定的查询语句中使用。游标参数的值只在游标被打开的时候被使用。 
                        </P>
                        <UL>
                          <LI>打开游标 </LI></UL>
                        <P>游标只能在打开之后才能执行查询操作。对于使用了FOR 
                        UPDATE子句的游标来说,OPEN语句会把满足查询条件的行琐住,如下例所示: </P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>DECLARE</STRONG><BR>&nbsp;&nbsp;<STRONG>CURSOR</STRONG>&nbsp;c1&nbsp;<STRONG>IS</STRONG>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>SELECT</STRONG>&nbsp;ename,&nbsp;job<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;emp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>WHERE</STRONG>&nbsp;sal&nbsp;&amp;lt;&nbsp;3000;<BR>&nbsp;&nbsp;...<BR><STRONG>BEGIN</STRONG><BR>&nbsp;&nbsp;<STRONG>OPEN</STRONG>&nbsp;c1;<BR>&nbsp;&nbsp;...<BR><STRONG>END</STRONG>; 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>OPEN语句执行时结果集中的行并不被选取,只有在FETCH语句执行的时候数据才被取得。 </P>
                        <UL>
                          <LI>传递游标参数 </LI></UL>
                        <P>我们可以用OPEN语句来为游标传递参数。如果在没有使用参数默认值的情况下,我们就必须在OPEN语句中为游标声明中的每一个形式参数指定一个对应的实际参数。比如下面的游标声明:</P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>DECLARE</STRONG><BR>&nbsp;&nbsp;emp_name&nbsp;&nbsp;&nbsp;emp.ename%<STRONG>TYPE</STRONG>;<BR>&nbsp;&nbsp;salary&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;emp.sal%<STRONG>TYPE</STRONG>;<BR><BR>&nbsp;&nbsp;<STRONG>CURSOR</STRONG>&nbsp;c1&nbsp;(NAME&nbsp;<STRONG>VARCHAR2</STRONG>,&nbsp;salary&nbsp;<STRONG>NUMBER</STRONG>)&nbsp;<STRONG>IS</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>SELECT</STRONG>&nbsp;*<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;... 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>下面三个语句都能打开游标:</P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>OPEN</STRONG>&nbsp;c1(emp_name,&nbsp;3000);<BR><STRONG>OPEN</STRONG>&nbsp;c1(<EM>'ATTLEY'</EM>,&nbsp;1500);<BR><STRONG>OPEN</STRONG>&nbsp;c1(emp_name,&nbsp;salary); 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>在上面的例子中,标识符salary用在游标声明的时候,它引用的是形式参数。但是,当用在OPEN语句中时,它引用的就是PL/SQL变量,为了避免混乱,最好使用唯一的标识。</P>
                        <P>有默认值的形参不需要有对应的实参,在OPEN语句执行时程序会自动使用它们的默认值。</P>
                        <P>我们可以用位置标识法或名称标识法把OPEN语句中的实参和游标声明中的形参关联起来。每个实参的数据类型和它对应的形参数据类型必须兼容。</P>
                        <UL>
                          <LI>从游标中取值 </LI></UL>
                        <P>除非在FETCH时使用BULK 
                        COLLECT子句,否则FETCH语句每次只会从结果集中取出一条记录,并把游标向下移动,指向当前记录的下一条记录。下面演示了FETCH语句的用法: 
                        </P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>FETCH</STRONG>&nbsp;c1&nbsp;<STRONG>INTO</STRONG>&nbsp;my_empno,&nbsp;my_ename,&nbsp;my_deptno; 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>对于游标查询返回的每一个字段值,在INTO列表中都必须有一个与之对应且类型兼容的变量。通常,我们可以像下面这样使用FETCH语句:</P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>LOOP</STRONG><BR>&nbsp;&nbsp;<STRONG>FETCH</STRONG>&nbsp;c1&nbsp;<STRONG>INTO</STRONG>&nbsp;my_record;<BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>EXIT</STRONG>&nbsp;<STRONG>WHEN</STRONG>&nbsp;c1%NOTFOUND;<BR>&nbsp;&nbsp;<EM>--&nbsp;process&nbsp;data&nbsp;record</EM><BR><STRONG>END</STRONG>&nbsp;<STRONG>LOOP</STRONG>; 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>查询可以在它的作用域范围内引用PL/SQL变量,但是,在查询中的任何变量只有在游标被打开时才计算它的值。在下面的例子中,每个被检索出来的salary只和2相乘,即使factor值在后续的操作中已经发生了改变:</P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>DECLARE</STRONG><BR>&nbsp;&nbsp;my_sal&nbsp;&nbsp;&nbsp;emp.sal%<STRONG>TYPE</STRONG>;<BR>&nbsp;&nbsp;my_job&nbsp;&nbsp;&nbsp;emp.job%<STRONG>TYPE</STRONG>;<BR>&nbsp;&nbsp;factor&nbsp;&nbsp;&nbsp;<STRONG>INTEGER</STRONG>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:=&nbsp;2;<BR><BR>&nbsp;&nbsp;<STRONG>CURSOR</STRONG>&nbsp;c1&nbsp;<STRONG>IS</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>SELECT</STRONG>&nbsp;factor&nbsp;*&nbsp;sal<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;emp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>WHERE</STRONG>&nbsp;job&nbsp;=&nbsp;my_job;<BR><STRONG>BEGIN</STRONG><BR>&nbsp;&nbsp;...<BR>&nbsp;&nbsp;<STRONG>OPEN</STRONG>&nbsp;c1;&nbsp;&nbsp;&nbsp;<EM>--&nbsp;here&nbsp;factor&nbsp;equals&nbsp;2</EM><BR><BR>&nbsp;&nbsp;<STRONG>LOOP</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FETCH</STRONG>&nbsp;c1<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>INTO</STRONG>&nbsp;my_sal;<BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>EXIT</STRONG>&nbsp;<STRONG>WHEN</STRONG>&nbsp;c1%NOTFOUND;<BR>&nbsp;&nbsp;&nbsp;&nbsp;factor&nbsp;&nbsp;:=&nbsp;factor&nbsp;+&nbsp;1;&nbsp;&nbsp;&nbsp;<EM>--&nbsp;does&nbsp;not&nbsp;affect&nbsp;FETCH</EM><BR>&nbsp;&nbsp;<STRONG>END</STRONG>&nbsp;<STRONG>LOOP</STRONG>;<BR><STRONG>END</STRONG>; 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>要想改变查询结果集或查询中的变量值,我们就必须关闭并重新打开含有输入变量的游标,这样才能使用新的输入变量值。 
                        </P>
                        <P>但是,我们可以为同一游标每次取得的数据指定一个不同的INTO列表。这样每次取得的数据就会被放到目标变量中去,如下例所示: 
                        </P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>DECLARE</STRONG><BR>&nbsp;&nbsp;<STRONG>CURSOR</STRONG>&nbsp;c1&nbsp;<STRONG>IS</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>SELECT</STRONG>&nbsp;ename<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;emp;<BR><BR>&nbsp;&nbsp;name1&nbsp;&nbsp;&nbsp;emp.ename%<STRONG>TYPE</STRONG>;<BR>&nbsp;&nbsp;name2&nbsp;&nbsp;&nbsp;emp.ename%<STRONG>TYPE</STRONG>;<BR>&nbsp;&nbsp;name3&nbsp;&nbsp;&nbsp;emp.ename%<STRONG>TYPE</STRONG>;<BR><STRONG>BEGIN</STRONG><BR>&nbsp;&nbsp;<STRONG>OPEN</STRONG>&nbsp;c1;<BR>&nbsp;&nbsp;<STRONG>FETCH</STRONG>&nbsp;c1<BR>&nbsp;&nbsp;&nbsp;<STRONG>INTO</STRONG>&nbsp;name1;&nbsp;&nbsp;&nbsp;<EM>--&nbsp;this&nbsp;fetches&nbsp;first&nbsp;row</EM><BR>&nbsp;&nbsp;<STRONG>FETCH</STRONG>&nbsp;c1<BR>&nbsp;&nbsp;&nbsp;<STRONG>INTO</STRONG>&nbsp;name2;&nbsp;&nbsp;&nbsp;<EM>--&nbsp;this&nbsp;fetches&nbsp;second&nbsp;row</EM><BR>&nbsp;&nbsp;<STRONG>FETCH</STRONG>&nbsp;c1<BR>&nbsp;&nbsp;&nbsp;<STRONG>INTO</STRONG>&nbsp;name3;&nbsp;&nbsp;&nbsp;<EM>--&nbsp;this&nbsp;fetches&nbsp;third&nbsp;row</EM><BR>&nbsp;&nbsp;...<BR>&nbsp;&nbsp;<STRONG>CLOSE</STRONG>&nbsp;c1;<BR><STRONG>END</STRONG>; 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>如果游标的指向超过了结果集中的最后一行,那么目标变量的值就无法确定。 </P>
                        <P>注意:在结果集的最后一次执行的FETCH语句一定取不到数据,而且没有异常发生。想要发现这种情况,我们就必须得使用游标的%FOUND或%NOTFOUND属性。 
                        </P>
                        <UL>
                          <LI>批量取得游标中的数据 </LI></UL>
                        <P>BULK 
                        COLLECT子句能让我们批量的绑定数据。这样我们就能一次性从结果集中取得所有的行。在下面的例子中,我们从游标中批量取得数据分别放到两个集合中去:</P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>DECLARE</STRONG><BR>&nbsp;&nbsp;<STRONG>TYPE</STRONG>&nbsp;numtab&nbsp;<STRONG>IS</STRONG>&nbsp;<STRONG>TABLE</STRONG>&nbsp;<STRONG>OF</STRONG>&nbsp;emp.empno%<STRONG>TYPE</STRONG>;<BR><BR>&nbsp;&nbsp;<STRONG>TYPE</STRONG>&nbsp;nametab&nbsp;<STRONG>IS</STRONG>&nbsp;<STRONG>TABLE</STRONG>&nbsp;<STRONG>OF</STRONG>&nbsp;emp.ename%<STRONG>TYPE</STRONG>;<BR><BR>&nbsp;&nbsp;nums&nbsp;&nbsp;&nbsp;&nbsp;numtab;<BR>&nbsp;&nbsp;names&nbsp;&nbsp;&nbsp;nametab;<BR><BR>&nbsp;&nbsp;<STRONG>CURSOR</STRONG>&nbsp;c1&nbsp;<STRONG>IS</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>SELECT</STRONG>&nbsp;empno,&nbsp;ename<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;emp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>WHERE</STRONG>&nbsp;job&nbsp;=&nbsp;<EM>'CLERK'</EM>;<BR><STRONG>BEGIN</STRONG><BR>&nbsp;&nbsp;<STRONG>OPEN</STRONG>&nbsp;c1;<BR>&nbsp;&nbsp;<STRONG>FETCH</STRONG>&nbsp;c1<BR>&nbsp;&nbsp;<STRONG>BULK</STRONG>&nbsp;<STRONG>COLLECT</STRONG>&nbsp;<STRONG>INTO</STRONG>&nbsp;nums,&nbsp;names;<BR>&nbsp;&nbsp;...<BR>&nbsp;&nbsp;<STRONG>CLOSE</STRONG>&nbsp;c1;<BR><STRONG>END</STRONG>; 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <UL>
                          <LI>关闭游标 </LI></UL>
                        <P>CLOSE语句可以关闭游标,游标被关闭后,我们还可以重新打开它。操作一个已经关闭了的游标会抛出预定义异常INVALID_CURSOR。 
                        </P>
                        <UL>
                          <LI>在游标中使用子查询 </LI></UL>
                        <P>子查询就是出现在另外一个SQL数据操作语句中的查询(通常用圆括号封闭)。计算时,子查询能为语句提供一个值或是一个值集合。通常,子查询用在WHERE子句中。例如,下面的查询就用于返回不在芝加哥居住的雇员:</P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>DECLARE</STRONG><BR>&nbsp;&nbsp;<STRONG>CURSOR</STRONG>&nbsp;c1&nbsp;<STRONG>IS</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>SELECT</STRONG>&nbsp;empno,&nbsp;ename<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;emp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>WHERE</STRONG>&nbsp;deptno&nbsp;<STRONG>IN</STRONG>&nbsp;(<STRONG>SELECT</STRONG>&nbsp;deptno<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;dept<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>WHERE</STRONG>&nbsp;loc&nbsp;&lt;&gt;&nbsp;<EM>'CHICAGO'</EM>); 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>再举一个在FROM子句中使用子查询的例子,下面语句能够返回含有五个或五个以上雇员的部门编号和部门名称: 
                        </P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>DECLARE</STRONG><BR>&nbsp;&nbsp;<STRONG>CURSOR</STRONG>&nbsp;c1&nbsp;<STRONG>IS</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>SELECT</STRONG>&nbsp;t1.deptno,&nbsp;dname,&nbsp;"STAFF"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;dept&nbsp;t1,&nbsp;(<STRONG>SELECT</STRONG>&nbsp;&nbsp;&nbsp;deptno,&nbsp;COUNT&nbsp;(*)&nbsp;"STAFF"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;emp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>GROUP</STRONG>&nbsp;<STRONG>BY</STRONG>&nbsp;deptno)&nbsp;t2<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>WHERE</STRONG>&nbsp;t1.deptno&nbsp;=&nbsp;t2.deptno&nbsp;<STRONG>AND</STRONG>&nbsp;"STAFF"&nbsp;&gt;=&nbsp;5; 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>针对一个数据表的子查询只执行一次,而具有关联关系的子查询会为每一行结果执行一次。如下面的查询,它的作用是找出工资超过所在部门的平均工资的雇员姓名和工资。对于emp表中的每一行,关联子查询都会为它计算一次部门的平均工资。 
                        </P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>DECLARE</STRONG><BR>&nbsp;&nbsp;<STRONG>CURSOR</STRONG>&nbsp;c1&nbsp;<STRONG>IS</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>SELECT</STRONG>&nbsp;&nbsp;&nbsp;deptno,&nbsp;ename,&nbsp;sal<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;emp&nbsp;t<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>WHERE</STRONG>&nbsp;sal&nbsp;&gt;&nbsp;(<STRONG>SELECT</STRONG>&nbsp;<STRONG>AVG</STRONG>&nbsp;(sal)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>FROM</STRONG>&nbsp;emp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>WHERE</STRONG>&nbsp;t.deptno&nbsp;=&nbsp;deptno)<BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>ORDER</STRONG>&nbsp;<STRONG>BY</STRONG>&nbsp;deptno; 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P class=title2>2、隐式游标一览</P>
                        <P>Oracle会隐式地打开一个游标处理所有那些不与显式游标相关联的SQL语句。我们可以引用这个隐式的SQL游标,虽然不能使用OPEN、FETCH和CLOSE语句来控制SQL游标,但可以利用它的属性来获取与最近执行的SQL语句的相关信息。 
                        </P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -