简单的plsql语句问题

JS 2012-03-02 07:15:06

原表是:mdsys.emp (记录举例)
DEPTID DEPTNAME EMPID EMPNAME SALARY
------ ---------- ------ ---------- -----------
1 销售部 1 陈一 1200
1 销售部 2 陈二 4500
1 销售部 3 陈三 4900
2 市场部 4 陈三 2000

SQL> declare
2 type name_array_type is varray(10) of varchar2(10);
3 name_array name_array_type;
4 cursor emp_cursor is select empname from mdsys.emp;
5
6 begin
7 open emp_cursor;
8 fetch emp_cursor bulk collect into name_array limit 10;
9 for i in 1..10 loop
10 dbms_output.put(name_array(i));
11 end loop;
12 close emp_cursor;
13 end ;
14 /
PL/SQL procedure successfully completed (这里没有记录输出来啊。。。。)
奇怪的事情是我执行了另外一个程序,结果却在那个程序结果里面出来了。。。。
SQL> declare
2 type name_array_type is varray(5) of varchar2(10);
3 name_array name_array_type;
4 cursor emp_cursor is select empname from mdsys.emp;
5 rows int :=5;
6 v_count int :=0;
7 begin
8 open emp_cursor;
9 loop
10 fetch emp_cursor bulk collect into name_array limit rows;
11 dbms_output.put('雇员名:');
12 for i in 1..(emp_cursor%rowcount-v_count) loop
13 dbms_output.put(name_array(i)||' ');
14 end loop;
15 dbms_output.new_line;
16 v_count:=emp_cursor%rowcount;
17 exit when emp_cursor%notfound;
18 end loop;
19 close emp_cursor;
20 end;
21 /

王丽刘娜袁野李欣刘明雇员名:袁野 王丽 刘娜 李欣 刘明
雇员名:张亚东 刘明凯 季岚 梁栋 汤佳
雇员名:田康 陈巍伟 孙鹏 巍伟 陈淑华
雇员名:王朋 单红 王祥

请大侠帮我看看是什么问题。。。先谢过~
...全文
251 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
JS 2012-03-04
  • 打赏
  • 举报
回复
谢谢解答[Quote=引用 9 楼 mailking 的回复:]
fetch bulk collect into 只是批量读取并赋值。相对于游标的fetch每次只读一条记录
你不加limit 10,他就一次性批量的将数据存入array数组,你加了就每次存10条记录。如果你游标有20条记录你就需要执行两次fetch bulk collect into。
其实跟简单显示游标的原理一样,只不过fetch into 操作的是记录,而fetch bulk collec……
[/Quote]
mailking 2012-03-04
  • 打赏
  • 举报
回复
fetch bulk collect into 只是批量读取并赋值。相对于游标的fetch每次只读一条记录
你不加limit 10,他就一次性批量的将数据存入array数组,你加了就每次存10条记录。如果你游标有20条记录你就需要执行两次fetch bulk collect into。
其实跟简单显示游标的原理一样,只不过fetch into 操作的是记录,而fetch bulk collect into操作的是集合open cursor
loop
fetch
exit when xxxx
end loop
我心飞翔 2012-03-03
  • 打赏
  • 举报
回复
结果:
我心飞翔 2012-03-03
  • 打赏
  • 举报
回复
实测

DECLARE
TYPE name_array_type IS VARRAY(20) OF VARCHAR2(20);
name_array name_array_type;
CURSOR emp_cursor is select EmpName from T146;

BEGIN
OPEN emp_cursor;
FETCH emp_cursor BULK COLLECT INTO name_array ;
FOR i IN 1..4 LOOP
dbms_output.put(name_array(i));
END LOOP;
dbms_output.put_line(''); --加一行代码
CLOSE emp_cursor;
END;
mingchaoyan 2012-03-03
  • 打赏
  • 举报
回复
这个和缓冲区有关
JS 2012-03-03
  • 打赏
  • 举报
回复
fetch emp_cursor bulk collect into name_array limit 10;
dbms_output.put('雇员名:');
for i in 1..10 loop
dbms_output.put(name_array(i)||' ');
end loop;
请问一下,不是fetch了10条记录之后再loop循环的吗?怎么会存在您说的那种情况呢,您能说说清楚吗
[Quote=引用 7 楼 mailking 的回复:]
你的问题出在

SQL code

fetch emp_cursor bulk collect into name_array limit 10;


下面是正确的写法

SQL code

SQL> declare
2 type name_array_type is varray(10) of varchar2(10);
3 name_array ……
[/Quote]
xpingping 2012-03-03
  • 打赏
  • 举报
回复
set serveroutput on
mailking 2012-03-03
  • 打赏
  • 举报
回复
你的问题出在

fetch emp_cursor bulk collect into name_array limit 10;

下面是正确的写法

SQL> declare
2 type name_array_type is varray(10) of varchar2(10);
3 name_array name_array_type;
4 cursor emp_cursor is select empname from mdsys.emp;
5
6 begin
7 open emp_cursor;
8 loop
9 fetch emp_cursor bulk collect into name_array limit 10;
10 exit when name_array.count=0;
11 end loop;
12 for i in 1..10 loop
13 dbms_output.put(name_array(i));
14 end loop;
15 close emp_cursor;
16 end ;


因为你用的是游标,并且这游标查询出来的记录数量你是不能确定的,但你又限制的批量赋值的数量,所以可能存在一次赋值没有将游标记录处理完的情况,因此需要加循环操作。循环的退出条件就是ame_array.count=0来确定游标记录被处理完了。
JS 2012-03-03
  • 打赏
  • 举报
回复
您的解答是正确的,我弱弱的问一下是什么原因呢,您能分析一下吗。[Quote=引用 4 楼 luiseradl 的回复:]

实测
SQL code

DECLARE
TYPE name_array_type IS VARRAY(20) OF VARCHAR2(20);
name_array name_array_type;
CURSOR emp_cursor is select EmpName from T146;

BEGIN
OPEN emp_cursor;
FETCH……
[/Quote]
JS 2012-03-02
  • 打赏
  • 举报
回复
自己先顶起来 希望高人相救啊
PL/SQL Developer是一个集成开发环境,专门面向Oracle数据库存储程序单元的开发。如今,有越来越多的商业逻辑和应用逻辑转向了Oracle Server,因此,PL/SQL编程也成了整个开发过程的一个重要组成部分。PL/SQL Developer侧重于易用性、代码品质和生产力,充分发挥Oracle应用程序开发过程中的主要优势。 目录 简介 背景 主要特性 编程基础知识程序结构 控制结构 变量声明与赋值 SQL基本命令 过程与函数 游标显示游标 隐式游标 简介 背景 主要特性 编程基础知识 程序结构 控制结构 变量声明与赋值 SQL基本命令 过程与函数 游标 显示游标 隐式游标 展开 编辑本段简介 PLSQL   PL/SQL(Procedural Language/SQL)是一种过程化语言,属于第三代语言,它与C、C++、Java等语言一样关注于处理细节,可以用来实现比较复杂的业务逻辑。它允许SQL的数据操纵语言和查询语句包含在块结构(block_structured)和代码过程语言中,使PL/SQL成为一个功能强大的事务处理语言。在甲骨文数据库管理方面,PL/SQL是对结构化查询语言(SQL)的过程语言扩展。PL/SQL的目的是联合数据库语言和过程语言。PL/SQL的基本单位叫做一个区段,由三个部分组成:一个申明部分,一个可运行部分,和排除-构建部分。   因为PL/SQL允许混合SQL申明和过程结构,因此可以在将申明发送到甲骨文系统去执行之前使用PL/SQL区段和副程序来组合SQL申明,没有PL/SQL,甲骨文需要就每次处理SQL申明,在网络环境中,这将影响交通流量,而且增加响应时间。PL/SQL区段只被编译一次并且以可运行的形式储存,以降低响应时间。 编辑本段背景   结构化查询语言(Structured Query Language,简称SQL)是用来访问关系型数据库一种通用语言,属于第四代语言(4GL),其执行特点是非过程化,即不用指明执行的具体方法和途径,而是简单地调用相应语句来直接取得结果即可。显然,这种不关注任何实现细节的语言对于开发者来说有着极大的便利。然而,有些复杂的业务流程要求相应的程序来描述,这种情况下4GL就有些无能为力了。PL/SQL的出现正是为了解决这一问题,PL/SQL是一种过程化语言,属于第三代语言,它与C、 C++、Java等语言一样关注于处理细节,可以用来实现比较复杂的业务逻辑。本文主要介绍PL/SQL的编程基础,以使入门者对PL/SQL语言有一个总体认识和基本把握。 编辑本段主要特性   PL/SQL编辑器,功能强大——该编辑器具有语法加强、SQL和PL/SQL帮助、对象描述、代码助手、编译器提示、PL/SQL完善、代码内容、代码分级、浏览器按钮、超链接导航、宏库等许多智能特性,能够满足要求性最高的用户需求。当您需要某个信息时,它将自动出现,至多单击即可将信息调出。   集成调试器(要求Oracle 7.3.4或更高)——该调试器提供您所需要的全部特性:跳入(Step In)、跳过(Step Over)、跳出(Step Out)、异常时停止运行、断点、观察和设置变量、观察全部堆栈等。基本能够调试任何程序单元(包括触发器和Oracle8 对象类型),无需作出任何修改。   PL/SQL完善器——该完善器允许您通过用户定义的规则对SQL和PL/SQL代码进行规范化处理。在编译、保存、打开一个文件时,代码将自动被规范化。该特性提高了您编码的生产力,改善了PL/SQL代码的可读性,促进了大规模工作团队的协作。   SQL 窗口——该窗口允许您输入任何SQL语句,并以栅格形式对结果进行观察和编辑,支持按范例查询模式,以便在某个结果集合中查找特定记录。另外,还含有历史缓存,您可以轻松调用先前执行过的SQL语句。该SQL编辑器提供了同PL/SQL编辑器相同的强大特性。   命令窗口——使用PL/SQL Developer 的命令窗口能够开发并运行SQL脚本。该窗口具有同SQL*Plus相同的感观,另外还增加了一个内置的带语法加强特性的脚本编辑器。这样,您就可以开发自己的脚本,无需编辑脚本/保存脚本/转换为SQL*Plus/运行脚本过程,也不用离开PL/SQL Developer集成开发环境。   报告——PL/SQL Developer提供内置的报告功能,您可以根据程序数据或Oracle字典运行报告。PL/SQL Developer本身提供了大量标准报告,而且您还可以方便的创建自定义报告。自定义报告将被保存在报告文件中,进而包含在报告菜单内。这样,运行您自己经常使用的自定义报告就非常方便。   您可以使用Query Reporter免费软件工具来运行您的报告,不需要PL/SQL Developer,直接从命令行运行即可。   工程——PL/SQL Developer内置的工程概念可以用来组织您的工作。一个工程包括源文件集合、数据库对象、notes和选项。PL/SQL Developer允许您在某些特定的条目集合范围之内进行工作,而不是在完全的数据库或架构之内。这样,如果需要编译所有工程条目或者将工程从某个位置或数据库移动到其他位置时,所需工程条目的查找就变得比较简单,   To-Do条目——您可以在任何SQL或PL/SQL源文件中使用To-Do条目快速记录该文件中那些需要进行的事项。以后能够从To-Do列表中访问这些信息,访问操作可以在对象层或工程层进行。   对象浏览器——可配置的树形浏览能够显示同PL/SQL开发相关的全部信息,使用该浏览器可以获取对象描述、浏览对象定义、创建测试脚本以便调试、使能或禁止触发器或约束条件、重新编译不合法对象、查询或编辑表格、浏览数据、在对象源中进行文本查找、拖放对象名到编辑器等。   此外,该对象浏览器还可以显示对象之间的依存关系,您可以递归的扩展这些依存对象(如包参考检查、浏览参考表格、图表类型等)。   性能优化——使用PL/SQL Profiler,可以浏览每一执行的PL/SQL代码行的时序信息(Oracle8i或更高),从而优化您SQL和PL/SQL的代码性能。   更进一步,您还可以自动获取所执行的SQL语句和PL/SQL程序统计信息。该统计信息包括CPU使用情况、块I/O、记录I/O、表格扫描、分类等。   HTML指南——Oracle目前支持HTML格式的在线指南。您可以将其集成到PL/SQL Developer工作环境中,以便在编辑、编译出错或运行时出错时提供内容敏感帮助。   非PL/SQL对象——不使用任何SQL,您就可以对表格、序列、符号、库、目录、工作、队列、用户和角色进行浏览、创建和修改行为。PL/SQL Developer提供了一个简单易用的窗体,只要将信息输入其中,PL/SQL Developer就将生成相应的SQL,从而创建或转换对象。   模板列表——PL/SQL Developer的模板列表可用作一个实时的帮助组件,协助您强制实现标准化。只要点击相应的模板,您就可以向编辑器中插入标准的SQL或PL/SQL代码,或者从草稿出发来创建一个新程序。   查询构建器——图形化查询构建器简化了新选择语句的创建和已有语句的修改过程。只要拖放表格和视窗,为区域列表选择专栏,基于外部键约束定义联合表格即可。   比较用户对象——对表格定义、视图、程序单元等作出修改后,将这些修改传递给其他数据库用户或检查修改前后的区别将是非常有用的。这也许是一个其他的开发环境,如测试环境或制作环境等。而比较用户对象功能则允许您对所选对象进行比较,将不同点可视化,并运行或保存应用必要变动的SQL脚本。   导出用户对象——该工具可以导出用户所选对象的DDL(数据定义语言)语句。您可以方便的为其他用户重新创建对象,也可以保存文件作为备份。   工具——PL/SQL Developer为简化日常开发专门提供了几种工具。使用这些工具,您可以重新编译全部不合法对象、查找数据库源中文本、导入或导出表格、生成测试数据、导出文本文件、监控dbms_alert和dbms_pipe事件、浏览会话信息等。   授权——大多数开发环境中,您不希望所有数据库都具备PL/SQL Developer的全部功能性。例如,数据库开发中您可以允许PL/SQL Developer的全部功能性,而数据库测试中您可以仅允许数据查询/编辑和对象浏览功能,而数据库制作中您甚至根本不希望PL/SQL Developer访问。利用PL/SQL Developer授权功能,您可以方便的定义特定用户或规则所允许使用的功能。   插件扩展——可以通过插件对PL/SQL Developer功能进行扩展。Add-ons页面提供插件可以免费下载。Allround Automations或其他用户均可提供插件(如版本控制插件或plsqldoc插件)。如果您具备创建DLL的编程语言,您还可以自己编写插件。   多线程IDE——PL/SQL Developer是一个多线程IDE。这样,当SQL查询、PL/SQL程序、调试会话等正在运行时,您依然可以继续工作。而且,该多线程IDE还意味着出现编程错误时不会中止:您在任何时间都可以中断执行或保存您的工作。   易于安装——不同于SQL*Net,无需中间件,也无需数据库对象安装。只需点击安装程序按钮,您就可以开始安装从而使用软件了。 编辑本段编程基础知识 程序结构   PL/SQL程序都是以块(block)为基本单位,整个PL/SQL块分三部分:声明部分(用declare开头)、执行部分(以 begin开头)和异常处理部分(以exception开头)。其中执行部分是必须的,其他两个部分可选。无论PL/SQL程序段的代码量有多大,其基本结构就是由这三部分组成。如下所示为一段完整的PL/SQL块:   /*声明部分,以declare开头*/   declare v_id integer;   v_name varchar(20);   cursor c_emp is select * from employee where emp_id=3;   /*执行部分,以begin开头*/   begin open c_emp; //打开游标    loop   fetch c_emp into v_id,v_name; //从游标取数据   exit when c_emp%notfound ;    end loop ;   close c_emp; //关闭游标   dbms_output.PUT_LINE(v_name);   /*异常处理部分,以exception开始*/   exception   when no_data_found then   dbms_output.PUT_LINE('没有数据');   end ; 控制结构   PL/SQL程序段中有三种程序结构:条件结构、循环结构和顺序结构。   1) 条件结构   与其它语言完全类似,语法结构如下:   if condition then   statement1   else   statement2   end if ; 2) 循环结构   这一结构与其他语言不太一样,在PL/SQL程序中有三种循环结构:   a. loop … end loop;   b. while condition loop … end loop;   c. for variable in low_bound . . upper_bound loop … end loop;   其中的“…”代表循环体。   3) 顺序结构   实际就是goto的运用,不过从程序控制的角度来看,尽量少用goto可以使得程序结构更加的清晰。 变量声明与赋值   PL/SQL主要用于数据库编程,所以其所有的数据类型跟Oracle数据库里的字段类型是一一对应的,大体分为数字型、布尔型、字符型和日期型。这里简单介绍两种常用数据类型:number、varchar2。   number   用来存储整数和浮点数。范围为1e130~10e125,其使用语法为:   number[(precision, scale)]   其中(precision, scale)是可选的,precision表示所有数字的个数,scale表示小数点右边数字的个数。   varchar2   用来存储变长的字符串,其使用语法为:   varchar2[(size)]   其中size为可选,表示该字符串所能存储的最大长度。   在PL/SQL中声明变量与其他语言不太一样,它采用从右往左的方式声明,比如声明一个number类型的变量v_id,那其形式应为:   v_id number;   如果给上面的v_id变量赋值,不能用“=”,应该用“:=”,即形式为:   v_id :=5; SQL基本命令   PL/SQL使用的数据库操作语言还是基于SQL的,所以熟悉SQL是进行PL/SQL编程的基础。SQL语言的分类情况大致如下:   1) 数据定义语言(DDL):Create,Drop,Grant,Revoke,…   2) 数据操纵语言(DML):Update,Insert,Delete,…   3) 数据控制语言(DCL):Commit,Rollback,Savapoint,…   4) 其他:Alter System,Connect,Allocate, …   具体的语法结构可以参阅其他关于SQL语言的资料,这里不再赘述。 编辑本段过程与函数   PL/SQL中的过程和函数与其他语言的过程和函数一样,都是为了执行一定的任务而组合在一起的语句。过程无返回值,函数有返回值。其语法结构为:   过程:Create or replace procedure procname(参数列表) as PL/SQL语句块   函数:Create or replace function funcname(参数列表) return 返回值 as PL/SQL语句块   为便于理解,举例如下:   问题:假设有一张表t1,有f1和f2两个字段,f1为number类型,f2为varchar2类型,要往t1里写两条记录,内容自定。   Create or replace procedure test_procedure as   V_f11 number :=1; /*声明变量并赋初值*/   V_f12 number :=2;   V_f21 varchar2(20) :='first';   V_f22 varchar2(20) :='second';   Begin   Insert into t1 values (V_f11, V_f21);   Insert into t1 values (V_f12, V_f22);   End test_procedure; /*test_procedure可以省略*/   至此,test_procedure存储过程已经完成,经过编译后就可以在其他PL/SQL块或者过程中调用了。函数与过程具有很大的相似性,此处不再详述。 编辑本段游标   游标的定义为:用游标来指代一个DML SQL操作返回的结果集。即当一个对数据库的查询操作返回一组结果集时,用游标来标注这组结果集,以后通过对游标的操作来获取结果集中的数据信息。这里特别提出游标的概念,是因为它在PL/SQL的编程中非常的重要。定义游标的语法结构如下:   cursor cursor_name is SQL语句;   在本文第一段代码中有一句话如下:   cursor c_emp is select * from employee where emp_id=3;   其含义是定义一个游标c_emp,代表employee表中所有emp_id字段为3的结果集。当需要操作该结果集时,必须完成三步:打开游标、使用fetch语句将游标里的数据取出、关闭游标。   游标用来处理从数据库中检索的多行记录(使用SELECT语句)。利用游标,程序可以逐个地处理和遍历一次检索返回的整个记录集。   为了处理SQL语句,Oracle将在内存中分配一个区域,这就是上下文区。这个区包含了已经处理完的行数、指向被分析语句的指针,整个区是查询语句返回的数据行集。游标就是指向上下文区句柄或指针。 显示游标   显示游标被用于处理返回多行数据的SELECT 语句,游标名通过CURSOR….IS 语句显示地赋给SELECT 语句。   在PL/SQL中处理显示游标所必需的四个步骤:   1)声明游标;CURSOR cursor_name IS select_statement   2)为查询打开游标;OPEN cursor_name   3)取得结果放入PL/SQL变量中;   FETCH cursor_name INTO list_of_variables;   FETCH cursor_name INTO PL/SQL_record;   4)关闭游标。CLOSE cursor_name   注意:在声明游标时,select_statement不能包含INTO子句。当使用显示游标时,INTO子句是FETCH语句的一部分。 隐式游标   所有的隐式游标都被假设为只返回一条记录。   使用隐式游标时,用户无需进行声明、打开及关闭。PL/SQL隐含地打开、处理,然后关掉游标。   例如:   …….   SELECT studentNo,studentName   INTO curStudentNo,curStudentName   FROM StudentRecord   WHERE name=’gg’;   上述游标自动打开,并把相关值赋给对应变量,然后关闭。执行完后,PL/SQL变量curStudentNo,curStudentName中已经有了值。 开放分类: oracle,plsql 我来完善 “plsql”相关词条: sql系统函数 sql 系统函数 百度百科中的词条内容仅供参考,如果您需要解决具体问题(尤其在法律、医学等领域),建议您咨询相关领域专业人士。 327本词条对我有帮助添加到搜藏 分享到: 更多 合作编辑者 百科ROBOT ,潘昊 ,江旭梦然 ,SONGYL525 ,ThinkIBM 更多 如果您认为本词条还需进一步完善,百科欢迎您也来参与编辑词条在开始编辑前,您还可以先学习如何编辑词条 如想投诉,请到百度百科投诉中心;如想提出意见、建议,请到百度百科吧。

17,377

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 基础和管理
社区管理员
  • 基础和管理社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧