版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、目录一、 PL/SQL 简介11.1PL/SQL1PL/SQL 程序结构1PL/SQL 运行过程1注释2二、 变量与数据类型3数据类型3标量类型32.3 变量. 3三、 流程控制语句5条件语句5循环语句6四、 PL/SQL 中的 SQL9PL/SQL 中的SQL 分类9DML(insert,update,delete)和 TCL(commit,rollback)9DDL9五、 PL/SQL 中的 select11select 语句的实现11record 类型11%rowtype125.4 record 变量的. 12cursor 的概念13cursor 的分类13显式cursor 的处理13显
2、式cursor 的属性14隐式cursor 的属性145.10 cursor 的. 14open cursor14fetch cursor15结果集提取的控制15close cursor15六、 集合 Asso 6.4collection19关联数组19tive arrays 的定义19Assotive arrays 类型和变量196.5 关联数组的操作206.6 Assotive arrays 的方法206.7 关联数组的遍历216.8 Assotive arrays 的异常226.9 批量绑定22七、 异常24Oralce 错误24Oralce 错误处理机制24异常的
3、类型24PL/SQL 中的异常24异常捕获24异常的捕获规则25Oralce 预定义错误的捕获25非 Oracle 预定义异常26用户自定义异常26异常处理总结27sqlcode 和 sqlerrm277.12 异常的. 28八、 子程序29子程序29有名子程序29有名子程序的分类29有名子程序的优点29九、 过程 procedure309.1 语法309.2 创建过程30形参和实参30形参的种类319.5 调用过程319.6过程中的参数31对实际参数的要求32形式参数的限制32带参数的过程调用32使用缺省参数329.11过程中的 DDL 语句339.12 变量33PL/SQL 中的SQL 分
4、类34再一次来看SQL 语句的处理过程36软分析和硬分析36对过程 procedure 的基本操作369.17 案例36十、 函数 function3810.1 语法38创建函数38调用函数38对函数function 的基本操作39过程和函数的比较3910.6块中的过程和函数3910.7 案例39十一、 包 package4111.1package41包的组成41包的优点4111.4 package的语法4111.5 package body的语法4211.6 编译包和包体4211.7 案例42十二、 触发器 trigger4412.1问题44DML 触发器的组成44DML 触发器的类型44D
5、ML 触发器的触发顺序44DML 行级触发器44:OLD 和:NEW44触发器的重新编译46触发器的状态46十三、 其他注意事项47PL/SQL 的特点47写 PL/SQL 的好处47命名建议47搞清楚如下内容47保证所有对象的状态都是valid4713.6 declare 中都可什么4713.7 数据库对象47一、PL/SQL 简介 PL/SQL(Procedural Language/SQL)是Oracle 在标准 SQL 的基础上增加了过程化处理,把 DML 和 select 语句组织在 PL/SQL 代码的过程性单元中,通过逻辑判断、循环等操作,实现复杂的功能或者计算的程序语言。扩展:
6、变量和类型、控制结构、过程与函数。注意事项:java 中是写方法,把复杂的业务逻辑写入方法中,再调用方法。PL/SQL 是写过程、函数,把复杂的业务逻辑写入过程、函数中,再调用它们。 程序结构PL/SQL 块:包含三部分,eg1:语法部分:declare;执行部分:begin;异常处理:exception注意事项:最简写的方式为 begin end;eg2:打印o World注意事项:dbms_output 是系统提供的包package,包含多个过程、函数。其中的过程 put_line实现的是输出功能,只有一个参数,只能为“字符类型”(日期和数值也可,系!但 java 中可以),用于接收需输出
7、的字符串。在统自动转换!类型sql 工作表子窗口中可以调用过程。想要在屏幕上输出需要写:set serveroutput on(在 begin 上面写)。如何调用过程:begin 包名.过程名();所有过程都是没有返回值的,即 java 中的void。 运行过程如下图所示:begindbms_output.put_line(o World);end;declarev_AccountID number(5):=1001; v_RealName varchar(20);beginselect real_name info v_RealName from account where id=v_Acc
8、ountID; exceptionwhen on_data_found theninsert info Fee_Log(desrc) values(Account 1001 dece not exit!) commin;end;-(不需要理解代码的具体含义!)注释增加可阅读性,使程序更容易理解。编译时将被忽略。单行注释:由两个连字符“ -”开始,到行尾都是注释。多行注释:由“/*”开头,由“*/”结尾。二、变量与数据类型 数据类型标量类型:数字型、字符型、日期型、型;可以直接用的。复合类型:record、asso 标量类型1)数字类型:numberbinary_tive array、neste
9、d table、varray;需要自己去定义的。number 的子类型 dec(38)、float(38)、real(18)eger(只能在 PL/SQL 中用),按 10 进制赋值,但存的时候会换成 2 进制存。优势是计算快。字符类型:varchar2、varchar(长度:1.32767) string(只能在 PL/SQL 中用,长度:1.32767) char(长度:132767) long日期类型:date类型:用于逻辑值 true,false,null(java 中只有 true,false)。不能向数据库中不能将列值保存到类型的数据。变量中。只能对变量执行逻辑操作。 变量语法:v
10、ar_name type constantnot null:=value;注意事项:PL/SQL 规定没有初始化的变量为null。 2)直接定义类型注意事项:PL/SQL 中没返回值的叫过程;有返回值的叫函数,且必须有指向(要么打印出,要么赋值给变量)。所以,过程和函数的调用是不一样的。java 中的方法一种没有返回值,一种是有返回值;有返回值的如果没返回,则会丢弃。但 PL/SQL!3)%type 方式:变量具有与数据库的表中的某列或其他变量相同的类型。eg1:三种方式eg2:定义变量,打印系统时间,并输出它们的值declare v_RealName varchar2(20);declare
11、 v_RealName account.real_name%type; declare v_TempVar number(7,3) not null :=12.3;v_AnotherVar v_TempVar%type :=12.3;declarev_n1 number :=1;-赋初值要有“冒号”,PL/SQL 中赋值和等号是区分开的v_c1 varchar2(10);v_d1 date :=sysdate;-sysdate 是函数,有返回值begin4)复合类型record 类型、集合类型。详细内容见后面的第五、六章!set serveroutput on declarev_d1 date
12、 :=sysdate; v_c1 varchar2(20);beginv_c1 :=to_char(v_d1,yyyy mm dd hh24:mi:ss); dbms_output.put_line(Current date is | v_c1);-put_line 只有一个参数,所以必须拼接!end;三、流程控制语句条件语句:if、case;循环语句:loop、while、for 条件语句1)if 语句方式一:方式二:方式三:注意事项:else if 在 PL/SQL 中的写法是 elsif!eg:输出类型的变量的值2)case 语句casewhenthenwhenthenelse end;
13、declarev_b1:=false; beginif v_b1 then dbms_output.put_line(true);elsif v_b1 is null then dbms_output.put_line(null);elsedbms_output.put_line(false); end if;end;-注意:put_line 中的参数只能为字符类型,但日期和数值会隐式转换,类型不行!if_exprthen sement;elsif_exprthen sement1;elsesement2; end if:if thensement;elsesement1; end if;if
14、 thensement;end if;/最简写的方式 循环语句1)loop 循环(无条件进入)语法:注意事项:exit when子句是必须的,否则循环将无法停止。when 后面直接写条件,没有尖括号或圆括号。eg1:循环输出数字 110eg2:循环10 条(静态)eg3:循环输出语句 inserto test_chang values(i),i 为字符。2)while 循环语法:whioolean exprloopsement1;sement2; end loop;declare v_index binary_eger :=1; beginloopdbms_output.put_line(in
15、serto test_chang values(|v_index|); v_index := v_index+1;exit when v_index10; end loop;end;declare v_index binary_eger :=1; beginloopinserto test_chang values(v_index); v_index := v_index+1;exit when v_index10; end loop;end;declare v_index binary_eger :=1; beginloopdbms_output.put_line(v_index); v_i
16、ndex := v_index+1;exit when v_index10; end loop;end;loopsement1;sement2;exit when end loop;循环语句执行的顺序是先判断的真假,如果为 true 则循环执行,否则退在 while 循环语句中仍然可以使用exit 或exit when 子句。注意事项:while 后面直接写条件,没有尖括号或圆括号。eg1:循环输出数字 110eg2:循环10 条(动态)3)for 循环语法:(和 java 不一样)。它的作用域仅循环计数器是一个变量,这个变量不需要是在循环中。每循环一次,循环变量自动加 1;使用关键字reve
17、rse,循环变量自动减 1。可以使用exit 或者exit when 子句退出循环。注意事项:跟在 in、in reverse 后面的数字必须是从小到大的顺序,但不一定是整数,可以是能够转换成整数的变量或表达式。不能用 null 作上限或下限下标!eg1:循环输出数字 110eg2:使用 in reverse 循环输出数字 110beginfor i in reverse 1.10 loop dbms_output.put_line(i);beginfor i in 1.10 loop dbms_output.put_line(i);end loop;end;for 循环计数器in 下限 .
18、上限 loop sement1;sement2;end loop;declare v_index binary_eger :=1; beginwhile v_index =10 loopexecute immediate inserto test_chang values(|v_index|); v_index := v_index+1;end loop;end;declare v_index binary_eger :=1; beginwhile v_index =10 loop dbms_output.put_line(v_index); v_index := v_index+1;end
19、loop;end;eg3:循环10 条(静态)beginfor i in 1.10 loopinserto test_chang values(i); end loop;end;end loop;end;四、PL/SQL 中的 SQL 中的 分类静态SQL在 PL/SQL 块中使用的 SQL 语句在编译时是明确的,执行的是确定对象,即 SQL 语句是在 PL/SQL 编译阶段编译的。效率高。能用静态就不用动态!动态SQL在 PL/SQL 块编译时 SQL 语句是不确定的,如根据用户输入的参数的不同而执行不同的操作。编译程序对动态语句部分不进行处理,只是在程序运行时动态的创建语句、对语句进行语法
20、分析并执行该语句。效率低。 (, )和 (, )它们可以直接在 PL/SQL 中使用标准的SQL 语句。语法: 不能原封不动的像 DML 和 TCL 那样直接写。所有的 DDL 语句要在 PL/SQL 中操作,必须用如下的语法形式(转成字符串),即本地动态SQL 是使用execute immediate 语句来实现的。eg1:可执行eg2:不可执行eg3:可执行注意事项:在一段 PL/SQL 程序中,先 create 再 insert,必须用 execute immediate(静态 sql 和动态 sql)beginexecute immediate create table test_ch
21、ang(c1 number); execute immediate inserto test_chang values(1); commit;end;-编译,执行都通过!使用动态 SQLbeginexecute immediate create table test_chang(c1 number); inserto test values(1);commit;end;-报错!是编译错误,说 test_chang 不存在!说明表还没有创建,只是在编译期编译。beginexecute immediate create table test_chang(c1 number); end;-本地动态
22、SQL 执行 DDL 语句begininserto host(id) values(1); commit;end;eg4:用循环向 test_chang 表中10 条。(从 1 到 10)beginexecute immediate create table test_chang(c1 number); for i in 1.10 loopexecute immediate inserto test_chang values(|i|); end loop;commit;end;五、PL/SQL 中的 select 语句的实现根据 select 语句返回的数,将 select 语
23、句的实现分为两类:1)当且仅当只返回“一条”:用 select o语句实现(将结果放入到变量中)。2)返回“0 条或多条”:用 cursor 实现。注意事项:selecto 确认 select 只返回一条,才不报错,否则加异常处理(没有返回或返回太多)。eg:提供客户 ID,打印客户和3)select.o 后的查询结果集种类若查询结果是单行单列, o 子句后用标量类型(标准类型),与 select 子句后的目标数据类型一致即可。若查询结果是单行多列, o 子句后的变量个数、顺序、每个变量的数据类型,应该与 select 子句后的目标数据相匹配;也可以用 类型类型,处理单行多列数据。eg1:语法
24、类型的变量。eg2:打印每个客户的名字,declaretype t_account_rec is record(real_name account.real_name%type,age number(3), idcard_no char(18);v_account t_account_rec;beginselect real_name,round(sysdate-birthdate)/365),idcard_noo v_account from accountdeclaretype t_cost_rec id record(base_cost cost.base_cost%type,-t_co
25、st_rec 是类型base_duration cost.base_duration%type,-base_cost 是成员unix_cost cost.unit_cost%type); v_cost t_cost_rec;-v_cost 是类型的变量v_cost_1 t_cost_rec;declarev_realname account.real_name%type; v_age number(3);beginselect real_name,round(sysdate-birthdate)/365)/减出的是天数 o v_realname,v_agefrom accountwhere i
26、d=1005;-换成 where 1=2 报错:异常,无数据;换成where 1=1 报错:返回太多dbms_output.put_line(: | | v_realname|: | |v_age);end; 用表结构或视图结构定义变量当使用%rowtype 定义完全相同。eg:语法变量时,record 成员的名称和类型与表或视图的列名称和类型 变量 的1)方法是“.”,即变量名.属性名。类型变量的属性eg1:语法eg2:语法注意事项:打印类型,一定是打印它的成员!2)若用 PL/SQL 程序对表进行 DML 操作,则该表必须事先存在,用SQL 建表。eg:语法3)在 insert 语句和up
27、date 语句中可以使用eg:语法类型变量。4)案例eg:提供客户 ID,打印客户名称和号,若该客户不存在,打印客户不存在begininserto cost_t1 values v_cost; update cost_t1 set row = v_cost_1; commit;end;create table cost_t1 aect base_cost,base_duration,unix_host from cost where id=3;declarev_cost cost%rowtype;beginselect *o v_cost from cost where id=1; dbms_
28、output.put_line(v_); dbms_output.put_line(v_cost.base_duration); dbms_output.put_line(v_cost.descr);end;declarev_cost.base_cost :=5.9;v_cost.base_duration :=20;v_cost.unit_cost :=0.4; v_cost_1 :=v_cost;select base_cost,base_duration,unit_costo v_cost_1 from cost where id =2;declarev_cost co
29、st%rowtype;where id=1005;dbms_output.put_line(:|v_account.real_name); dbms_output.put_line(:|v_account.age); dbms_output.put_line(:|v_account.idcard_no);end;-t_account_rec 是类型,real_name 是成员,v_account 是类型的变量。5.5 cursor 的概念1)根据 select 语句返回的数,若返回数是 0 条或多条用cursor 实现。Oralce 使用专有SQL 工作区(private SQL workar
30、ea)来执行 SQL 语句,息。这个工作区称为“cursor”。Oracle 所执行的每一个 SQL 语句都有唯一的cursor 与之相对应。程序员用 PL/SQL 的cursor 定义所需执行的 select 语句。5.6 cursor 的分类隐式:select o 语句、DML 语句处理信显式:返回多条的 select 语句用显式cursor 实现。5.7 显式 cursor 的处理如下图所示:5.8 显式 cursor 的属性属性类型描述declaretype t_account_rec is record(real_name account.real_name%type,idcard_
31、no char(18); v_account t_account_rec;t number;beginselect count(*)ot from account where id =1005; ift=1 thenselect real_name,idcard_noo v_account from account where id=1005; dbms_output.put_line(:|v_account.real_name); dbms_output.put_line( :|v_account.idcard_no);elsedbms_output.put_line(用户不存在); end
32、 if;end;目的:获取有关显式cursor 的状态信息。注意事项:值(true、false、null),当不 fetch 时,open 后直接%found,则返回 null。%notfound 和%found 缺省为 null,由 fetch 去改变。sqlplus 命令:exec 过程名,即可直接调用过程。 隐式 的属性目的:获取有关隐式cursor 的状态信息。注意事项:sql 是指最近的 sql 语句。eg:相关操作 的1)在游标中使用标准的 select 语句。2)如果需要按指定的次序处理行,可在查询中使用 order by 子句。3)可以在查询中eg:语法变量,但必须在curso
33、r 语句之前这些变量。 1)通过 open cursor 来执行 select 语句并标识结果集。 2)select 语句如果没有返回,不会出现异常。 3)语法:open c_service_id(5); 检索当前行,把值赋给变量。变量可以是 record 类型或简单变量。如果是简单变量:包含相同数量的变量。把每一个变量和相应的列进行位置匹配。declarecursor c_service_id(p_cost_id number)iect id from service where cost_id=p_cost_id; beginbegininserto test_chang values(1
34、00); dbms_output.put_line(sql%rowcount); update test_chang set c1=10 where c1=100; dbms_output.put_line(sql%rowcount);end;属性类型描述sql%isopenDML 执行中为 true,结束后为 falsesql%notfound与 SQL%found 属性返回值相反sql%found值为 true 表示DML 操作成功sql%rowcount数值表示 DML 语句成功执行的数据行数cursor_name%isopen如果 cursor 是 open 的,其值为 truecur
35、sor_name%notfound如果前一个fetch 语句没有返回一行,其值为 truecursor_name%found如果前一个fetch 语句返回,其值为 truecursor_name%rowcount数值到目前为止,cursor 已提取的总行数通过循环检测cursor 中是否包含数据行。语法:注意事项:fetcho 变量:变量一定是类型,与 select 后的列的个数、类型相同。cursor 不会因为 select 子句的结果集为 0 或多值报错。 结果集提取的控制使用循环处理显式 cursor 结果集中的多行数据。每次 fetch 一行,反复进行。使用%notfound 属性检测
36、一次不成功的提取操作。使用显式cursor 的属性检测每一次提取是否成功,避免出现无限循环。 处理完结果集中的数据后,应该关闭 cursor。如果需要,可以再次打开该 cursor。3)cursor 一旦关闭,所有和该cursor 相关的资源都会被提取数据。,不可再从关闭的cursor 中4)任何对关闭的cursor 的操作都会invalid_cursor 错误。5)每个 ses能打开的 cursor 数量由 open_cursor 参数决定。6)语法:close c_service_id;eg1:打印每个客户的名字和号码(使用 loop 循环处理cursor)。eg2:打印每个客户的名字和号
37、码,若查询没有返回,打印客户不存在(使用loop 循环处理cursor)。where 1=1 输出所有用户,where 1=2 输出 no accountdeclarecursor c_account iect real_name from account where 1=1; v_realname varchar2(20);beginopen c_account;fetch c_accounto v_realname; if c_account%notfound thendbms_output.put_line(no account);declarecursor c_account iect
38、 real_name from account where 1=1; v_realname varchar2(20);beginopen c_account;-open 则结果集已经在内存中了loopfetch c_accounto v_realname; exit when c_account%notfound;dbms_output.put_line(v_realname);-若输出在判断前,则最后的多打印一次end loop;close c_account;end;fetch cursor_name o var1,var2,|record_name; fetch c_service_id
39、o v_service_ideg3:打印每个客户的名字和号码,若查询没有返回,打印客户不存在(使用loop 循环处理cursor)。v_realname 也可用 rowtype 定义为 cursor 类型,但要注意变量的。eg4:打印每个客户的名字和while 循环处理cursor)。号码,若查询没有返回,打印客户不存在(使用declarecursor c_account iect real_name,idcard_no from account where 1=1; v_account c_account%rowtype;beginopen c_account;fetch c_account
40、o v_account; if c_account%notfound thendbms_output.put_line(no account); elsewhile c_account%found loopdbms_output.put_line(: |v_account.real_name|:|v_account.idcard_no);fetch c_accounto v_account; end loop;end if;declarecursor c_account iect real_name from account where 1=1; v_realname c_accountrow
41、type;beginopen c_account;fetch c_accounto v_realname.real_name; if c_account%notfound thendbms_output.put_line(no account); elseloopdbms_output.put_line(v_realname.real_name); fetch c_accounto v_realname.real_name; exit when c_account%notfound;end loop; end if;close c_account;end;elseloopdbms_output
42、.put_line(v_realname); fetch c_accounto v_realname; exit when c_account%notfound;end loop; end if;close c_account;end;注意事项:用 while 循环和 loop 循环时,注意 fetch 和 put_line()的顺序;否则 while会少打,loop 会多打。号码(使用 for 循环处理 cursor)eg5:打印每个客户的名字和方式一:for 的最简单写法注意事项:for 循环把 cursor 的操作集成了(open、fetch、close),自动打开关闭,自动把值fetc
43、h 给 i,所以 i 的类型是方式二:定义一个cursor类型。eg6:打印每个客户的名字和 for 循环处理cursor)方式一:号码,若查询没有返回,打印客户不存在(使用declarecursor c_account iect real_name,idcard_no from account where 1=1; v_account c_account%rowtype;beginopen c_account;fetch c_accounto v_account; if c_account%notfound thendbms_output.put_line(no account); else
44、close c_account; for i in c_account loopdbms_output.put_line(:|i.real_name|:|i.idcard_no);end loop; end if;close c_account;declarecursor c_account iect real_name,idcard_no from account;beginfor i in c_account loopdbms_output.put_line(:|i.real_name|:|i.idcard_no);dbms_output.put_line(c_account%rowcou
45、nt); end loop;end;beginfor i in(select real_name,idcard_no from account) loopdbms_output.put_line(:|i.real_name|:|i.idcard_no);-dbms_output.put_line(c_account%rowcount);无法打印,因为拿不到 cursor 的名字end loop;end;close c_account;end;方式二:declarecursor c_account iect real_name,idcard_no from account where 1=1;
46、t binary_eger := 0;beginfor i in c_account loopdbms_output.out_linad(i.real_name,12, )| |i.idcard_no); t := 1;end loop;ift = 0 thendbms_output.put_line(account not exists!); end if;end;end;六、集合collection 是按某种顺序排列的一组元素,所有的元素有相同的数据类型,每个元素有唯一一个下标标识其在这一组元素中的位置。分类:1)Assotive arrays(关联数组)又称 index-by table
47、,使用键值。Nested table 嵌套表(本课程不讲解)。Varray 数据,变长数组,定义时需要指定数组大小(本课程不讲解)。关联数组关联数组就是键值对的集合,其中键是唯一的,用于确定数组中对应的值。键可以是整数或字符串。第一次使用键来指派一个对应的值就是添加元素,而后续这样的操作就是更新元素。3)关联数组能帮存放任意大小的数据集合,快速查找数组中的元素。它像一个简单的 SQL 表,可以按主键来检索数据。 的定 义1)同种类型的一维、无边界的稀疏集合,只能用于 PL/SQL。 2)type_name 是关联数组的类型名,element_type 是关联数组中 3)index by 后面的
48、数据类型是下标的数据类型。注意事项:的元素类型。关联数组和下标不要求连续,不要求从 0、从 1 开始。集合对下标是自动排序的,按元素排序要自己写算法。两个下标一样,则是覆盖操作!eg1:语法eg2:集合下标自动排序 类型和变量类型eg:eg:变量注意事项:v_account account%rowtype;type is table of v_account index by binary_eger;-报错 v_account 是变量,不是数据类型,改为 account%rowtype 才正确V1 assotive_array_type;V2 v1%type;type assotive_arr
49、ay_type is table of number index by binary_eger;dbms_output.put_line(index:|v_account.);-输出排序后的第一个下标 dbms_output.put_line(index:|v_account.last); -输出排序后的最后一个下标type type_name is table of element_type not nullindex by binary_egls_eger|varchar2(size_limit); 关联数组的操作eg:语法 的方 法1)exists 方法:exists(1),判断第 1
50、个元素是否存在。在使用count 方法前,建议先用exists 来判断一下,这样可以避免抛出异常。eg:语法2)count 方法:返回联合数组的元素个数,不包括被删除的元素。对于空的联合数组,返回值也是 0; eg:语法3)和 last:返回最小和最大下标号,如果 collection 为空,则返回 null。4)prior(n)和 next(n):返回第n 个元素的前一个和后一个,如果不存在,则返回 null。 5)trim(n):从最后一个元素删除 n 个元素。6)delete 方法:delete:删除所有元素delete(n):删除第 n 个元素delete(m,n):从第 m 个元素删
51、除到第 n 个元素eg:相关操作declaretype t_account_idxtab is table of varchar2(20)-元素的数据类型 index by binary_eger;-下标的数据类型cursor c_account iect id,real_name from account;-用 id 作下标v_account t_account_idxtab;beginfor i in c_account loopif projects.count = 25 then if courses.exists(i) then courses(i) := new_course;en
52、d if;declaretype t_indtab is table of number index by binary_eger; v_indtab t_indtab;beginv_indtab(1) :=1;v_indtab(5) :=5;v_indtab(6) :=6;v_indtab(10) :=10; dbms_output.put_line(v_indtab(10); dbms_output.put_line(v_indtab(7);end; 关联数组的遍历eg1:语法eg2:关联数组的遍历(用while 循环)eg3:关联数组的遍历(用for 循环)declaretype t_a
53、ccount_idxtab is table of varchar2(20)-元素的数据类型 index by binary_eger;-下标的数据类型cursor c_account iect id,real_name from account;-用 id 作下标v_account t_account_idxtab;beginfor i in c_account loop v_account(i.id) :=i.real_name;end loop;for i in v_account. v_account.last loopdeclaretype t_account_idxtab is t
54、able of varchar2(20)-元素的数据类型 index by binary_eger;-下标的数据类型cursor c_account iect id,real_name from account;-用 id 作下标v_account t_account_idxtab; v_index binary_eger;beginfor i in c_account loop v_account(i.id) :=i.real_name;end loop;v_index :=v_account.;while v_index = v_account.last loop dbms_output.
55、put_line(v_account(v_index);v_index := v_account.next(v_index);-找 1005 的下一个下标end loop;end;declare begin for i in v_indtab. v_indtab.last loop dbms_output.put_line(v_indtab(i);end loop;end;v_account(i.id) :=i.real_name; dbms_output.put_line(index:|i.id); dbms_output.put_line(element:|v_account(i.id);
56、end loop;dbms_output.put_line(element:|v_account(1005); dbms_output.put_line(index:|v_account.); dbms_output.put_line(index:|v_account.last);end;注意事项: 现象:对于不连续的下标,用 for 循环会空转,效率低。下标是连续的用 for 循环好。下标不连续的用 while 循环好(匹配集合中的next()方法)。 的异常 批量绑定1)通过 bulk collect 减少 loop 处理的开销。2)采用 bulk collect 可以将查询结果的加载到c
57、ollections 中。o 语句中使用 bulk collect。3)可以在 selecto、fetcho、returning注意事项:选择操作的几种方式:select、selecto、cursor fetcho、select bulkcollecto、fetch bulk collecto、fetch bulk collecto limit 10注意在使用 bulk collect 时,所有的注意事项:o 变量都必须是 collections。当返回多条时可用 bulk collect 和 cursor,但 cursor 是一条一条处理,bulk collect 是批量处理。集成度越高,可
58、控的内容越少,如下标不可控了。使用 bulk collect 时,下标自动生成从 1 开始。使用问题:如果内存空间不够,则将无法执行下去,所以要限制 limit 一次取出的数量。eg1:fetch bulk collectoeg2:打印每个客户的名字、方式一:、以及累计declaretype t_account_rec is record (real_name varchar2(20),age binary_eger); type t_account_idxtab is table of t_account_rec index by binary_eger;declarecursor is v
59、_account 集合变量beginopen c_account;fetch bulk collecto v_account limit 3; close c_account;declaretype numlist is table of number index by binary_eger; nums numlist;-自动初始化为 nullbeginnums(null) :=3;-触发 value_error,没下标,下标不能为空 if nums(1) =1 then -触发 no_data_found,下标有,但没元素if v_account.exists(i) then dbms_o
60、utput.put_line(v_account(i);end if; end loop;end;方式二:declarecursor c_account iect real_name,round(sysdate-birthdate)/365) age-想必须起别名from account;type t_account_indtab is table of c_account%rowtype index by binary_eger; v_account t_account_indtab;v_culage binary_eger :=0;beginselect real_name,round(s
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024版钢筋工程合同风险管理合同3篇
- 全国赛课一等奖人教版数学六年级上册《分数除法一个数除以分数》课件
- 八年级数学家长会课件
- 体育赛事承办合同协议书范本
- 2024版汽车零部件采购与销售合同2篇
- 资金监管的合同范本2024版
- 2024年度建筑工程渣土绿色运输合同3篇
- 基于2024年度的广告投放合同具体描述3篇
- 河北省劳动合同
- 实习合同范本
- 智能治理:提高政府决策的准确性和效率
- 2024年滴眼剂市场份额分析:全球滴眼剂市场销售额达到了4.89亿美元
- 2024-2030年中国铁皮石斛行业市场竞争策略及投资价值研究报告
- 融入人工智能的《语言学概论》教案设计
- 2024年信息技术基础考试题库
- 2024至2030年中国空气滤芯行业投资前景及策略咨询研究报告
- 罪犯心理危机干预专家讲座
- 2024-2025学年北师版八年级上册数学期末专项复习:一次函数(压轴34题)解析版
- 铁塔基础计算书
- 循环经济项目合作框架协议
- 2024版中国航天发展历程
评论
0/150
提交评论