您的位置:首页 > 数据库 > Oracle

oracle读书笔记-----PL/SQL编程

2016-05-30 11:02 453 查看
(一)之基本数据类型、程序结构

PL/SQL是一种高效的事物处理语言,它具有如下优点

1、支持SQL

2、支持面向对象的编程方法

3、更好的性能和更高的效率

4、编写方便

5、与Oracle高度集成

6、安全性好

一、PL/SQL变量和基本数据类型

1、PL/SQL变量的定义

基本数据类型变量的定义方法如下:

变量名 类型标识符 [:= 值];

如: Str varchar2[100] := '中国';

也可以使用关键字default来代替赋值符。

str varchar2[100] default '中国';

注意:赋值符合中的冒号和等号是不能分开的;

2、基本数据类型



三、PL/SQL程序的结构

首先看一个简单的例子:以下是一个完整的PL/SQL程序,用于求方程ax²+bx+c=0的根

[html] view
plain copy

print?

declare

a int := 3;

b int := 8;

c int := 2;

x1 number(8,2);

x2 number(8,2);

t number(8,2);

error exception;

begin

t := b**2-4*a*c;

if t<0 then

raise error;

end if;

x1 := (-b+sqrt(t)/(2*a));

x2 := (b+sqrt(t)/(2*a));

dbms_output.put_line('x1='||x1);

dbms_output.put_line('x2='||x2);

exception

when error then dbms_output.put_line('此方程无解');

end;

从上面可以看出一个PL/SQL程序分为3个部分:

1)、定义部分。在PL/SQL程序中,所用到的常量、变量、游标等必须在这一部分中定义。

但是这个部分的变量定义不能使用逗号分隔的办法来同时声明多个变量。

分号是每个变量声明和语句的结束符。

如果一个PL/SQL程序中没有变量需要定义,那么这个部分是可以去掉的。

2)、执行部分。这个部分是PL/SQL程序中的核心部分,包括赋值语句、对数据库的操作语句和流程控制语句等,构成 PL/SQL程序的基本块结构。

执行部分至少有一个可执行语句。

3)异常处理部分。当程序检测到错误情况时即产生异常。由exception标识的部分来处理程序过程产生的异常。

所以一个PL/SQL程序的基本结构可以是以下结构:

Declare

定义部分

Begin

执行部分

Exception

异常处理部分

End;

(二)之程序流程

一、PL/SQL程序流程控制



上面的结构与其他的高级语言程序一样,就不做介绍了。

下就条件结构和循环结构说明。

1)IF条件控制句

1.1 IF...THEN语句

其语法是:

IF p THEN

基本语句段;

END IF;

例如:

[html] view
plain copy

print?

declare

flag1 integer := 1;

flag2 integer := 2;

begin

if flag1 < flag 2 then

dbms_output.put_line('Flag1<flag2');

end if;

end;

注意:上面的IF 与END IF必须成对出现

1.2 IF...THEN...ELSE语句

该语句用于需要在两个语句段之间做出选择时。其语法如下:

IF P THEN

语句段1;

ELSE

语句段2;

EDN IF;

在该语句中,如果p的值为true,则执行语句段1,否则执行语句段2;实例:

[html] view
plain copy

print?

declare

flag1 integer := 5;

flag2 integer := 8;

begin

if flag1 <flag2 then

dbms_output.put_line('flag1<flag2');

else

dbms_output.put_line('flag1>flag2');

end if;

end;

1.3 IF...THEN...ELSIF语句

该语句用于在三个或者三个以上的语句段之间做出选择。其语法段为:

IF P1 THEN

语句段1;

ELSIF P2 THEN

语句段2;

ELSE

语句段3;

END IF;

实例:

[html] view
plain copy

print?

declare

grade number := 98;

results varchar2(10);

begin

if grade >=90 then

results := '优';

elsif grade >= 80 then

results :='良';

elsif grade >=70 then

results :='中';

elsif grade >= 60 then

results :='及格';

else

results :='差';

end if;

dbms_output.put_line(results);

end;

1.4 CASE选择控制

该语句用于控制多分支选择功能。其实 IF...THEN...ELSIF语句也可以实现这个功能,但是非常的麻烦。其语法结构为:

CASE E

WHEN e1: THEN 语句段1;

WHEN e2: THEN 语句段2 ;

WHEN e3: THEN 语句段3;

....................

WHEN en: THEN 语句段n ;

END CASE;

实例:

[html] view
plain copy

print?

declare

results varchar2(20) := 'B';

grade varchar2(20);

begin

case results

when 'A' then grade := '90-100';

when 'B' then grade := '80-89';

when 'C' then grade := '70-79';

when 'D' then grade := '60-69';

when 'E' then grade := '<60';

else grade := '不存在这个成绩等级';

end case;

dbms_output.put_line(grade);

end;

2)、循环控制

2.1 FOR...LOOP语句

该形式如下:

FOR I [REVERSE]IN lb..hb LOOP

语句段;

END LOOP;

其中,i为整型变量,一般称为循环计算器,lb和hb均为整型常量,分别代表了i的下限和上限,..为范围操作符。当没有使用参数REVERSE时,i的初值被设置为lb。实例:

[html] view
plain copy

print?

declare

i int := 0;

begin

for i in 1..3 loop

dbms_output.put_line('循环第'||to_char(i)||'次时'||to_char(i));

end loop;

end;

2.2 LOOP...EXIT循环控制

该语句用于控制死循环的。一般对于死循环的控制,有如下三种方式:

2.2.1 利用if语句

LOOP

语句段;

IF P THEN

EXIT;

END IF;

END LOOP;

实例:

[sql] view
plain copy

print?

declare

i int := 0;

results integer := 0;

begin

loop

results := results + i;

if i = 10 then

exit;

end if;

i : i+1;

end loop;

dbms_output.put_line('累加结果为:'||to_char(results));

end;

2.2.2 利用EXIT...WHEN

LOOP

.........

EXIT WHEN e;

.............

END LOOP;

其中e为布尔表达式,如果e的值为true则循环退出,否则继续执行循环语句。实例:

[sql] view
plain copy

print?

declare

i int := 1;

results integer := 0;

begin

loop

results := results+i;

exit when i = 10;

i := i+1;

end loop;

dbms_output.put_line('累加结果为:'||to_char(results));

end;

2.2.3: 利用标签

该语句的格式如下:

<<标签名>>

LOOP

.......

EXIT 标签名 WHEN e;

........

END LOOP;

当e为true时退出。注意,标签名必须在loop语句之前用“<<>>”定义实例:

[sql] view
plain copy

print?

declare

i integer := 1;

results integer := 0;

begin

<<my_label>>

loop

results := results + i;

exit my_label when i = 10;

i := i+1;

end loop;

dbms_output.put_line('累加的结果为:'||to_char(results));

end;

2.3 WHILE...LOOP循环控制

WHILE e LOOP

语句段;

END LOOP;

E为循环条件,当e的值为true时则执行循环体,否则退出循环。

实例:

[sql] view
plain copy

print?

declare

m integer := 100;

n integer := 7;

results integer;

begin

results := m;

while results >=n loop

results := results - n;

end loop;

dbms_output.put_line(to_char(m)||'除以'||to_char(n)||'的余数'||to_char(results));

end;

二、在PL/SQL程序中调用SQL语句

实际上在PL/SQL程序中i调用SQL语句,对于不同的SQL语句调用的方法是不一样的。在这里介绍常用的 几种语句的调用方法。

2.1调用SELECT语句

在调用这个语句之间,应该定义一个变量用来存储SELECT语句产生的结果,而且 这个变量的结果要与SELECT之后的字段列表相一致。实例:

[sql] view
plain copy

print?

declare

temp_emp scott.emp%rowtype;

begin

select * into temp_emp from emp where empno=7369;

dbms_output.put_line(to_char(temp_emp.empno||','||temp_emp.ename));

end;

注意:这种变量只能是一条记录,否则就会出错。而且如果SELECT语句无返回结果,同样会报错。

2.2调用INSERT语句

这条语句可以直接调用。实例:

[sql] view
plain copy

print?

declare

empno emp.empno%type;

ename emp.ename%type;

job emp.job%type;

mgr emp.mgr%type;

hiredate emp.hiredate%type;

sal emp.sal%type;

comm emp.comm%type;

deptno emp.deptno%type;

begin

empno := 6676;

ename := 'LILY';

job := 'CLERK';

mgr := 7899;

hiredate := to_date('1981-12-12','yyyy-mm-dd');

sal := 999.00;

comm := 433.00;

deptno := 20;

insert into emp values(empno,ename,job,mgr,hiredate,sal,comm,deptno);

end;

2.3调用UPDATE语句

同样可以之间调用。实例:

[sql] view
plain copy

print?

declare

tempno scott.emp.empno%type;

begin

tempno := 7677;

update emp set ename='AAA' where empno = tempno;

end;

2.4调用DELETE语句

直接调用。实例:

[sql] view
plain copy

print?

declare

tempno scott.emp.empno%type;

begin

tempno := 7677;

delete form emp where empno = tempno;

end;

(三)之游标

游标是从数据库中提取出来一临时表的形式存放在内存中的数据。可以把游标看作是内存的SQL工作区域,游标名称相当于该区域的句柄。通过该句柄可以有效地控制游标,从而实现对数据的操作。所以对游标的操作实际上就是对数据库库的间接操作。

1.1游标的定义

定义游标的格式如下:

CURSOR 游标 IS SELECT 语句;

例如:把数据表中emp中部门号为20的员工定义为游标:

[html] view
plain copy

print?

CURSOR exce_emp is select * from scott.emp where deptno=20;

定义游标后,我们就可以使用游标了。但是要对游标进行操作我们必须先打开游标:

Open 游标名;

打开游标实际上是从数据表中读取数据的过程,在这个过程中主要完成两件事:

1、把select查询结果读入内存工作区中。

2、将游标指针定位在第一条记录。

游标在使用后,要关闭:close 游标名;

1.2利用fetch命令从游标中提取数据

我们定义游标并且打开游标后,就可以利用fetch命令从游标中提取数据。

FETCH 游标名 INTO变量名1,变量名2......

或者

FFETCJ 游标名 INTO 纪录型变量名;

FETCH命令首先将当前游标指针所指的行读出来并且置于相应的变量中,然后把游标指针移到下一行。所以FETCH命令每一个执行的时候,只能提取一行或者部分的数据。

实例:

[sql] view
plain copy

print?

declare

cursor exce_emp is select * from emp where empno=6676; --定义游标

var_exce_emp exce_emp%rowtype; --定义变量

begin

open exce_emp; --打开游标

fetch exce_emp into var_exce_emp; --fetch提取数据

dbms_output.put_line('提取的数据为:员工的姓名:'||var_exce_emp.ename||',员工的工作为:'||var_exce_emp.job);

close exce_emp;

end;

存在这样一种情况,如果游标指针已经指到了游标的末尾,那么FETCH命令将读不到数据了,所以应该有这样一种机制,这种机制可以测出游标是否已经指到了游标的末尾。这种机制就是游标的属性。

1.3游标的属性

游标有四个属性:%FOUND、%ISOPEN、%NOTFOUND、%ROWCOUNT。

下面就分别这四个属性介绍:

1.3.1%FOUND

该属性用于测试在自己所在语句之前的最后一个FETCH命令是否提取到了数据。如果能够提取到数据就返回true,否则返回false。但是如果一个游标还没有被打开就运用%FOUND,那么将会产生INVALID_CURSOR异常。

实例:

[sql] view
plain copy

print?

declare

cursor exce_emp is select empno,ename from emp where deptno=20;

var_exce_emp exce_emp%rowtype;

i int := 1;

begin

open exce_emp;

loop

fetch exce_emp into var_exce_emp;

if exce_emp %found then --利用%found属性检测是否提取到了数据

dbms_output.put_line('第'||to_char(i)||'个员工的信息-------编号:'||var_exce_emp.empno||'员工姓名:'||var_exce_emp.ename);

i := i+1;

else

exit;

end if;

end loop;

close exce_emp;

end;

1.3.2%ISOPEN

该属性主要用于测试游标是否已经打开。

实例:

[sql] view
plain copy

print?

declare

cursor exce_emp is select empno,ename from emp;

var_exce_emp exce_emp%rowtype;

begin

if not exce_emp%isopen then --检测游标是否已经打开

dbms_output.put_line('游标没有打开');

open exce_emp;

else

dbms_output.put_line('游标已经打开了');

end if;

end;

1.3.3%NOFOUND

该属性与%FOUND相反。这里就不做介绍了。

1.3.4%ROWCOUNT

当刚刚打开游标时,%ROWCOUNT的值为0。每运行一次FETCH命令,%ROWCOUNT的值就会自增1。因此%ROWCOUNT的值可以看着是游标中当前被读取了的记录的条数,即游标循环中处理的当前行数。如果一个有游标在打开之前调用%ROWCOUNT属性,就会产生异常INVALID_CURSOR。

实例:

[sql] view
plain copy

print?

declare

cursor exce_emp is empno,ename from emp where deptno=20;

var_exce_emp exce_emp%rowtype;

n int := 5;

begin

open exce_emp;

loop

fetch exce_emp into var_exce_emp;

exit when exce_emp%notfound;

dbms_output.put_line('员工号:'||var_exce_emp.empno||',员工姓名:'||var_exce_emp.ename);

exit when exce_emp%rowcount=n;

end loop;

close exce_emp;

end;

1.4隐式游标

上面介绍的都是显示游标。其实Oracle还默认了一种游标,这个游标就是隐式游标。其被定义为SQL。它同时也具有4个属性。如下:

[sql] view
plain copy

print?

declare

tempdeptno := 20;

counts int := 0;

begin

update emp set job='CLERK' where deptno = tempdeptno;

if sql%found then

counts := sql%rowcount;

end if;

dbms_output.put_line('对'||to_char(counts)||'行语句做了修改');

end;

注意:隐式游标时不需要打开和关闭的。

下面就显示游标和隐式游标做一个比较

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: