body
{
font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI",Tahoma,Helvetica,Sans-Serif,"Microsoft YaHei", Georgia,Helvetica,Arial,sans-serif,宋体, PMingLiU,serif;
font-size: 10.5pt;
line-height: 1.5;
}
html, body
{

}
h1 {
font-size:1.5em;
font-weight:bold;
}
h2 {
font-size:1.4em;
font-weight:bold;
}
h3 {
font-size:1.3em;
font-weight:bold;
}
h4 {
font-size:1.2em;
font-weight:bold;
}
h5 {
font-size:1.1em;
font-weight:bold;
}
h6 {
font-size:1.0em;
font-weight:bold;
}
img {
border:0;
max-width: 100%;
}
blockquote {
margin-top:0px;
margin-bottom:0px;
}
table {
border-collapse:collapse;
border:1px solid #bbbbbb;
}
td {
border-collapse:collapse;
border:1px solid #bbbbbb;
}

pl/sql编程

pl/sql编程

一、什么是pl/sql

pl/sql(procedural language/sql)是Oracle在标准的sql语言上的扩展,pl/sql不仅允许嵌入Sql语言,还可以定义变量和常量,允许使用条件语句和循环语句,允许使用例外处理各种错误,这样使得它的功能变得更加强大。

二、pl/sql学习的必要性

1、提高应用程序的运行性能。

2、模块化的设计思想。

3、减少网络传输量。

4、提高安全性。

三、编写规范

单行注释--

sql>select * from emp where empno=7788; --取得员工信息

/*....................*/

2、标识符号的命名规范

(1)当定义变量时,建议用v_作为前缀 v_sal。

(2)当定义常量时,建议用c_作为前缀 c_rate。

(3)当定义游标时,建议用_cursor作为后缀emp_cursor。

(4)当定义例外时,建议用e_作为前缀 e_error。

块(block)是pl/sql的基本程序单元,编写pl/sql程序实际上 就是编写pl/sql块。要完成相对简单的应用功能,可能只需要编写一个pl/sql快;但是如果想要实现复杂的功能,可能需要在一个pl/sql块中嵌套其他的pl/sql快。

1、块结构示意图

pl/sql块由三个部分构成:定义部分、执行部分、例外处理部分。

declear:定义部分是从declare开始的,这部分是可选的。定义常量、变量、游标例外、复杂数据类型。

begin:执行部分是从begin开始的,这部分是必须的。

exception:例外处理部分是exception开始的,该部分可选的。

A、包含定义部分和执行部分的pl/sql块

declare

v_ename varchar2(5); --定义字符串变量

begin

select ename int o v_ename from emp where empno=&no;

dbms_output.put_line('雇员名:' || v_ename);

相关说明:

& 表示要接收从控制台输入的变量

B、包含定义部分、执行部分和例外处理部分

为了避免pl/sql程序的运行错误,提高pl/sql的健壮性,应该对可能的错误今夕处理,这个很有必要。

declare

v_ename varchar2(5); --定义字符串变量

begin

select ename int o v_ename from emp where empno=&no;

dbms_output.put_line('雇员名:' || v_ename);

exception

when no_data_found then

dbms_output.put_line('输入有误');

过程用于执行特定的操作,当建立过程时,即可以指定输入参数(in),也可以指定输出参数(out),通过在过程中使用输入参数,可以将数据传递到执行部分,通过使用输出参数,可以将执行部分的数据传递到应用环境。在sqlplus中可以使用create procedure命令来建立过程。

请考虑编写一个过程,可以输入雇员们,新工资,可修改雇员的工资。

create procedure Update_Sal(spName varchar2,new sal number) is

begin

update emp set sal = newSal where ename = spName;

如何调用过程有两种方法:

A、exec Update_Sa('Scott',4678);

B、call Update_Sal'Scott',4567);

函数用于返回特定的数据,当建立函数时,在函数头部必须包含return子句,而在函数体内必须包含return语句返回的数据,我们可以使用create function 来建立函数。

create function annual_income(name varchar2)

return numeber is annual_salary number(7,2);

begin

select sal*12+nvl(comm,0)*12 into annual_salary from emp where ename=name;

return annual_salary;

在sqlplus中调用函数

sql>var income number

sql>call annual_income('SCOTT') into: income;

sql>print income;

包用于在逻辑上组合过程和函数,它由包规范和包体两部分组成

1、我们可以使用create package命令来创建包。

create package sp_package as

procedure update_sal(name varchar2,new sal number);

function annual_income(name varchar2) return number;

包的规范只包含了过程和函数的说明,但是没有过程和函数的实现代码。包体用于实现包规范中的过程和函数。

2、建立包体可以使用create package body命令

create package body sp_package as

procedure Update_Sal(spName varchar2,new sal number) is

begin

update emp set sal = newSal where ename = spName;

function annual_income(name varchar2)

return numeber is annual_salary number(7,2);

begin

select sal*12+nvl(comm,0)*12 into annual_salary from emp where ename=name;

return annual_salary;

3、如何调用包的过程或是函数

当调用包的过程或是函数时,在过程和函数前需要带有包名,如果要访问其他方案的包,还需要在包名前加方案名。

sql>call sp_package.update_sal('SCOTT',1500);

八、定义并使用变量

概述:在编写pl/sql程序时,可以定义变量和常量。在pl/sql程序中包括有标量类型(scalar)、复合类型(composite)、参照类型(references)、lob(large object)。

1、标量(scalar)

在编写pl/sql块时,如果要使用变量,需要在定义部分定义变量。

pl/sql中定义变量和常量的语法如下:

identifier [constant] datatype [not null] [:=| default expr]

identifier:名称

constant:指定常量。需要指定它的初始值,其其值是不能改变的。

datatype:数据类型

not null:指定变量值不能为NULL

:=:给变量或是常量指定初始值

default:用于指定初始值

expr:指定初始值pl/sql表达式,可是文本值、其他变量、函数等。

标量定义的案例

(1)定义一个变长字符串

v_ename varchar2(10);

(2)定义一个小数,范围-9999.99~9999.99

v_sal number(6,2);

(3)定义一个小数并给一个初始值为5.4 :=是pl/sql的赋值号

v_sal2 number(6,2):=5.3;

(4)定义一个日期类型的数据

v_hiredate date;

(5)定义一个布尔变量,不能为空,初始值为false

v_valid boolean not null default false;

A、使用标量

在定义好变量后,就可以使用这些变量。这里需要 说明的是pl/sql块为变量赋值不同于其他的编程语言,需要在等号前面加冒号(:=)。

下面以输入员工号,显示雇员姓名、工资、个人所得税(税率为0.03)为例,说明变量的使用,看看如何编写。

declare

c_tax_rate number(3,2):=0.03;

v_ename varchar2(5);

v_sal number(7,2);

v_tax number(7,2);

begin

select ename,sal into v_ename,v_sal from emp where empno=&no;

v_tax:=v_sal*c_tax_rate;

dbms_output.put_line('姓名是:'||v_ename||' 工资是:'||v_sal||' 所得税是:'||v_tax);

B、使用%type类型

对于上面的pl/sql块有一个问题:

就是如果员工的姓名超过了5字符的话,就会有错误,为了降低pl/sql程序的维护工作量,可以使用%type属性定义变量,这样它会按照数据库列来确定你定义的变量的类型和长度。

语法:标识符名 表名.列名%type;

declear

c_tax_rate number(3,2):=0.03;

v_ename emp.ename%type;

v_sal emp.sal%type;

v_tax number(7,2);

begin

select ename,sal into v_ename,v_sal from emp where empno=&no;

v_tax:=v_sal*c_tax_rate;

dbms_output.put_line('姓名是:'||v_ename||' 工资是:'||v_sal||' 所得税是:'||v_tax);

2、复合变量(composite)

用于存储多个值的变量。主要包括这几种pl/sql记录、pl/sql表、嵌套表、varray。

1、pl/sql记录

类似于高级语言中的结构体,需要注意的是,当引用pl/sql记录成员时,必须要加记录变量作为前缀(记录变量.记录成员)。

declare

type emp_record_type is record(name emp.ename%type, salary emp.sal%type,title emp.job%type);

sp_record emp_record_type;

begin

select ename,sal,job into sp_record from emp where empno=7788;

dbms_output.put_line('员工名:'||sp_record.name);

2、pl/sql表

相当于高级语言中的数组,但是需要注意的是在高级语言中数组的下标不能为负数,而pl/sql是可以为负数的,并且表元素的下标没有限制。

declare

type sp_table_type is table of emp.ename%type index by binary_integer;

sp_table sp_table_type;

begin

select ename into sp_table(0) from emp where empno=7788;

dbms_output.put_line('员工名:'||sp_table(0));

sp_table_type:是pl/sql表类型

emp.ename%type:指定了表的元素的类型和长度

sp_table:是pl/sql表变量

sp_table(0):表示下标为0的元素

3、参照变量

概述:参照变量是指用于存放数值指针的变量,通过使用参照变量,可以使得应用程序共享相同对象,从而降低占用空间。在编写pl/sql程序时,可以使用游标变量(ref cursor)和对象类型变量(ref obj_type)两种参照变量类型。

1、游标变量(ref cursor)

使用游标时,当定义游标时不需要指定相应的select语句,但是当使用游标时(open时)需要指定select语句,这样一个游标就与一个select 语句结合了。

请使用pl/sql编写一个块,可以输入部门号,并显示该部门所有员工姓名和他的工资

declare

type sp_emp_cursor is ref cursor;

test_cursor sp_emp_cursor;

v_ename emp.ename%type;

v_sal emp.sal%type

begin

opent test_cursor for select ename,sal from emp where deptno=&no;

fetch test_cursor into v_ename,v_sal;

exit when test_cursor%notfound

dbms_output.putline('姓名:'||v_ename||' 工资:'||v_sal);

endloop;

close test_cursor;

九、控制结构

概述:在任何计算机语言(C、Java、Pascal)都有各种控制语句(条件语句、循环结构、顺序控制结构),在pl/sql中也存在这样的控制结构。

1、条件分支语句

pl/sql中提供了三种条件分支语句。if-then、if-then-else、if-then-elsif-else。

(1)简单的条件判断if-then

案例:编写一个过程,可以输入一个雇员名,如果该雇员的工资低于2000,就给该雇员工资增加10%。

create procedure IncreaseSal(spName varchar2) is

v_sal emp.sal%type;

begin

select sal into v_sal from emp where ename=spName;

if v_sal<2000 then

update emp sal=sal+sal*10% where ename=spName;

end if;

(2)二重条件分支if-then-else

案例:编写一个过程,可以输入一个雇员名,如果该雇员的补助不是0,就在原来的基础上增加100;如果补助为0就把补助设为200。

create procedure IncreaseComm(spName varchar2) is

v_comm emp.comm%type;

begin

select comm into v_comm from emp where ename=spName;

if v_comm<>0 then

update emp set comm=comm+100 where ename=spName;

update emp set comm=200 where ename=spName;

end if;

(3)多重条件分支if-then-elsif-else

案例:编写一个过程,可以输入一个雇员编号,如果该雇员的职位是PRESIDENT就给他的工资增加1000,如果该雇员的职位是MANAGER就给他的工资增加500,其他职位的雇员工资增加200。

create procedure IncreaseSal(spNo number) is

v_job emp.job%type;

begin

select job into v_job from emp where empno=spNo;

if v_job='PRESIDENT' then

update emp set sal=sal+1000 where empno=spNo;

elsif v_job='MANAGER'

update emp set sal=sal+500 where empno=spNo;

update emp set sal=sal+200 where empno=spNo;

end if;

2、循环语句

(1)基本循环

loop是pl/sql中最简单的循环语句,这种循环语句以loop开头,以end loop结尾,这种循环至少会被执行一次。

案例:编写一个过程,可输入用户名,并循环添加10个用户到Users表中,用户编号从1开始增加。

create procedure AddUser(spName varchar2) is

v_num number(2):=1;

begin

insert into Users values(v_num,spName);

exit when v_num=10;

v_num:=v_num+1;

endloop;

(2)While循环

基本循环至少要执行循环体一次,而对于while循环来说,只有条件为true时,才会执行循环体语句,while循环以while 条件 loop开始,以end loop结束。

编写一个过程,可输入用户名,并循环添加10个用户到Users表中,用户编号从11开始增加

create procedure AddUser(spName varchar2) is

v_num number(3):=11;

begin

while v_num<=20 loop

insert into Users values(v_num,spName);

v_num:=v_num+1;

endloop;

(3)for循环

基本for循环的基本结构如下

begin

for i in reverse 1..10 loop

insert into Users values(i,'Kevin');

end loop;

3、顺序控制语句

(1)goto语句

goto语句用于跳转到特定标号去执行有车,注意由于使用goto语句会增加程序的复杂度,并使得应用程序可读性变差,所以在一般应用开发时,建议大家不要使用goto语句

基本语法如下:

goto label:其中label是已经定义好的标号名。

declare

i number(4):=1;

begin

dbms_output.put_line("输出i='||i");

if i=10 then

goto end_loop

end if;

i:=i+1;

endloop;

<<end_loop>>

dbms_output.put_line("循环结束");

(2)null

null语句不会执行任何操作,并且会直接将控制传递到下一条语句。使用null语句的主要好处是可以提高pl/sql的可读性。

declare

v_sal emp.sal%type;

begin

select sal into v_sal from emp where ename=spName;

if v_sal<2000 then

update emp sal=sal+sal*10% where ename=spName;

null;

end if;

十、编写分页过程

概述:分页时任何一个网站(bbs、网上商城、Blog)都会使用到的技术,因此学习pl/sql编程开发就一定要掌握该技术。

案例:编写一个过程完成分页。

--创建一个包,存放游标。

create package ListPackage as

type page_cursor is ref cursor;

--开始编写分页的过程

create procedure PagedList(

tableName in varchar2, --要查询的表名

sortColumn in varchar2, --欲排序的列名

pagesize in number, --每页显示的记录数

currentPage in number, --当前页号

myRowCount out number, --表中总共的记录数

myPageCount out number, --共有多少页

p_cursor out ListPackage.page_cursor --游标变量

v_sql varchar2(1000);

v_begin number:=(currentPage-1)*pagesize+1;

v_end number:=currentPage*pagesize;

begin

v_sql:='select * from(select *, rownum rn from (select * from '||tableName||' order by '||sortColumn||') t1 where rownum<='||v_end||') where rn>='||v_begin;

open p_cursor for v_sql;

--计算myRowCount和myPageCount

v_sql:='select count(*) from '||tableName;

execute immediate v_sql into myRowCount;

if mod(myRowCount,pagesize)=0 then

myPageCount:=myRowCount/pagesize;

myPageCount:=myRowCount/pagesize+1;

end if;

close p_cursor;

十一、例外处理

1、例外的分类

Oracle将例外分为预定义例外、非预定义例外和自定义例外三种。

预定义例外:用于处理常见的Oracle错误。

非预定义例外:用于处理预定义例外不能处理的例外。

自定义例外:用于处理与Oracle错误无关的其他情况。

2、处理预定义例外

预定义例外时由pl/sql所提供的系统例外。当pl/sql应用程序违反了Oracle规定的限制时,则会隐含的触发一个内部例外。pl/sql为开发人员提供了二十多个预定义例外。我们给大家介绍常用的例外。

(1)预定义例外case_not_found

在开发pl/sql块中编写case语句时,如果在when子句中没有包含必须的条件分支,就会触发case_not_found的例外。

create procedure sp_pro6(spno number) is

v_sal emp.sal%type;

begin

select sal into v_sal from emp where empno=spno;

when v_sal<1000 then

update emp set sal=sal+100 where empno=spno;

when v_sal<2000 then

update emp set sal=sal+200 where empno=spno;

end case;

exception

when case_not_found then

dbms_output.put_line('case语句没有与'||v_sal||'相匹配的条件');

(2)预定义例外cursor_already_open

当从新打开已经打开的游标时,会隐含的触发例外cursor_already_open。

declare

cursor emp_cursor is select ename,sal from emp;

begin

open emp_cursor;

for emp_record1 in emp_cursor loop

dbms_output.put_line(emp_record1.ename);

end loop;

exception

when cursor_already_open then

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

(3)预定义例外dup_val_on_index

在唯一索引所对应的列上插入重复的值时,会隐含的触发例外dup_val_on_index例外。

begin

insert into dept values(10.'公关部','北京');

exception

when dup_val_on_index then

dbms_output.put_line('在deptno列上不能出现重复值');

(4)预定义例外invalid_cursor

当试图在不合法的游标上执行操作时,会触发该例外。

例如:视图从没有打开的游标提取数据,或是关闭没有打开的游标。则会触发该例外。

declare

cursor emp_cursor is select ename,sal from emp;

emp_record emp_cursor%rowtype;

begin

fetch emp_cursor into emp_record;

dbms_output.put_line(emp_record.ename);

close emp_cursor;

exception

when invalid_cursor then

dbms_output.put_line('请检查游标是否打开');

(5)预定义例外invalid_number

当输入的数据有误时,会触发该例外。

案例:数字100写成了1oo就会触发该例外

begin

update emp set sal=sal+'1oo';

exception

when invalid_number then

dbms_output.put_line('输入数字不正确');

(6)预定义例外no_data_found

下面是一个pl/sql块,当执行select into没有返回行,就会触发该例外。

declare

v_sal emp.sal%type;

begin

select sal into v_sal from emp where ename='&name';

exception

when no_data_found then

dbms_output.put_line('不存在该员工');

(7)预定义例外too_many_rows

当执行select into语句时,如果返回超过了一行,则会触发该例外。

declare

v_ename emp.ename%type;

begin

select ename into v_ename from emp;

exception

when too_many_rows then

dbms_output.put_line('返回了多行');

(8)预定义例外zero_divide

当执行除0操作时,则会触发给例外。

(9)预定义例外value_error

当在执行赋值操作时,如果变量的长度不足以容纳实际数据,则会触发该例外value_error。

declare

v_ename varchar2(5);

begin

select ename into v_ename from emp where empno=&no;

dbms_output.put_line(v_ename);

exception

when value_error then

dbms_output.put_line('变量尺寸不足');

(10)其它预定义例外

A、login_denide

当用户非法登录时,会触发该例外。

B、not_logged_on

如果用户没有登录就执行dml操作,就会触发该例外。

C、storage_error

如果超出了内存空间或是内存被损坏,就触发该例外。

D、timeout_on_resourece

如果Oracle在等待资源时,出现超时就触发该例外。

3、非预定义例外

非预定义例外用于处理与预定义例外无关的Oracle错误,使用预定义例外只能处理21个Oracle错误,而当使用pl/sql开发应用程序时,可能会遇到其他的一些Oracle错误。比如在pl/sql快中执行dml语句时,违反了约束规定等等。在这样的情况下,也可以处理Oracle的各种例外。

4、处理自定义例外

预定义例外和非预定义例外都是Oracle错误相关的,并且处在的Oracle错误会隐含的触发相应的例外。而自定义例外与Oracle错误没有任何关联,它是由开发人员为特定情况所定义的例外。

案例:请编写一个pl/sql块,接收一个雇员的编号,并给该雇员工资增加1000元,如果该雇员不存在请提示。

create procedure IncreaseSal(spno number) is

myException exception;

begin

update emp set sal=sal+100 where empno=spno;

if sql%not_found then

raise myException;

end if;

exception

when myException then

dbms_output.put_line('没有更新任何用户');

十二、Oracle视图

概述:视图是一个虚拟表,其内容由查询定义,同真实表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在,行和列数据来自有定义视图的查询所引用的表,并且在引用视图时动态生成。

1、视图与表的区别

A、表需要占用磁盘空间,视图不需要。

B、视图不能添加索引。

C、使用视图可以简化复杂查询。

D、视图有利于提高安全性。

2、创建视图

create view 视图名 as select语句[with read only]

3、创建或修改视图

create or replace view 视图名 as select语句[with read only]

4、删除视图

drop view 视图名

文章优化有问题?点击这里反馈URL给我们么是pl/sql

pl/sql(procedural language/sql)是Oracle在标准的sql语言上的扩展,pl/sql不仅允许嵌入Sql语言,还可以定义变量和常量,允许使用条件语句和循环语句,允许使用例外处理各种错误,这样使得它的功能变得更加强大。

二、pl/sql学习的必要性

1、提高应用程序的运行性能。

2、模块化的设计思想。

3、减少网络传输量。

4、提高安全性。

三、编写规范

单行注释--

sql>select * from emp where empno=7788; --取得员工信息

/*....................*/

2、标识符号的命名规范

(1)当定义变量时,建议用v_作为前缀 v_sal。

(2)当定义常量时,建议用c_作为前缀 c_rate。

(3)当定义游标时,建议用_cursor作为后缀emp_cursor。

(4)当定义例外时,建议用e_作为前缀 e_error。

块(block)是pl/sql的基本程序单元,编写pl/sql程序实际上 就是编写pl/sql块。要完成相对简单的应用功能,可能只需要编写一个pl/sql快;但是如果想要实现复杂的功能,可能需要在一个pl/sql块中嵌套其他的pl/sql快。

1、块结构示意图

pl/sql块由三个部分构成:定义部分、执行部分、例外处理部分。

declear:定义部分是从declare开始的,这部分是可选的。定义常量、变量、游标例外、复杂数据类型。

begin:执行部分是从begin开始的,这部分是必须的。

exception:例外处理部分是exception开始的,该部分可选的。

A、包含定义部分和执行部分的pl/sql块

declare

v_ename varchar2(5); --定义字符串变量

begin

select ename int o v_ename from emp where empno=&no;

dbms_output.put_line('雇员名:' || v_ename);

相关说明:

& 表示要接收从控制台输入的变量

B、包含定义部分、执行部分和例外处理部分

为了避免pl/sql程序的运行错误,提高pl/sql的健壮性,应该对可能的错误今夕处理,这个很有必要。

declare

v_ename varchar2(5); --定义字符串变量

begin

select ename int o v_ename from emp where empno=&no;

dbms_output.put_line('雇员名:' || v_ename);

exception

when no_data_found then

dbms_output.put_line('输入有误');

过程用于执行特定的操作,当建立过程时,即可以指定输入参数(in),也可以指定输出参数(out),通过在过程中使用输入参数,可以将数据传递到执行部分,通过使用输出参数,可以将执行部分的数据传递到应用环境。在sqlplus中可以使用create procedure命令来建立过程。

请考虑编写一个过程,可以输入雇员们,新工资,可修改雇员的工资。

create procedure Update_Sal(spName varchar2,new sal number) is

begin

update emp set sal = newSal where ename = spName;

如何调用过程有两种方法:

A、exec Update_Sa('Scott',4678);

B、call Update_Sal'Scott',4567);

函数用于返回特定的数据,当建立函数时,在函数头部必须包含return子句,而在函数体内必须包含return语句返回的数据,我们可以使用create function 来建立函数。

create function annual_income(name varchar2)

return numeber is annual_salary number(7,2);

begin

select sal*12+nvl(comm,0)*12 into annual_salary from emp where ename=name;

return annual_salary;

在sqlplus中调用函数

sql>var income number

sql>call annual_income('SCOTT') into: income;

sql>print income;

包用于在逻辑上组合过程和函数,它由包规范和包体两部分组成

1、我们可以使用create package命令来创建包。

create package sp_package as

procedure update_sal(name varchar2,new sal number);

function annual_income(name varchar2) return number;

包的规范只包含了过程和函数的说明,但是没有过程和函数的实现代码。包体用于实现包规范中的过程和函数。

2、建立包体可以使用create package body命令

create package body sp_package as

procedure Update_Sal(spName varchar2,new sal number) is

begin

update emp set sal = newSal where ename = spName;

function annual_income(name varchar2)

return numeber is annual_salary number(7,2);

begin

select sal*12+nvl(comm,0)*12 into annual_salary from emp where ename=name;

return annual_salary;

3、如何调用包的过程或是函数

当调用包的过程或是函数时,在过程和函数前需要带有包名,如果要访问其他方案的包,还需要在包名前加方案名。

sql>call sp_package.update_sal('SCOTT',1500);

八、定义并使用变量

概述:在编写pl/sql程序时,可以定义变量和常量。在pl/sql程序中包括有标量类型(scalar)、复合类型(composite)、参照类型(references)、lob(large object)。

1、标量(scalar)

在编写pl/sql块时,如果要使用变量,需要在定义部分定义变量。

pl/sql中定义变量和常量的语法如下:

identifier [constant] datatype [not null] [:=| default expr]

identifier:名称

constant:指定常量。需要指定它的初始值,其其值是不能改变的。

datatype:数据类型

not null:指定变量值不能为NULL

:=:给变量或是常量指定初始值

default:用于指定初始值

expr:指定初始值pl/sql表达式,可是文本值、其他变量、函数等。

标量定义的案例

(1)定义一个变长字符串

v_ename varchar2(10);

(2)定义一个小数,范围-9999.99~9999.99

v_sal number(6,2);

(3)定义一个小数并给一个初始值为5.4 :=是pl/sql的赋值号

v_sal2 number(6,2):=5.3;

(4)定义一个日期类型的数据

v_hiredate date;

(5)定义一个布尔变量,不能为空,初始值为false

v_valid boolean not null default false;

A、使用标量

在定义好变量后,就可以使用这些变量。这里需要 说明的是pl/sql块为变量赋值不同于其他的编程语言,需要在等号前面加冒号(:=)。

下面以输入员工号,显示雇员姓名、工资、个人所得税(税率为0.03)为例,说明变量的使用,看看如何编写。

declare

c_tax_rate number(3,2):=0.03;

v_ename varchar2(5);

v_sal number(7,2);

v_tax number(7,2);

begin

select ename,sal into v_ename,v_sal from emp where empno=&no;

v_tax:=v_sal*c_tax_rate;

dbms_output.put_line('姓名是:'||v_ename||' 工资是:'||v_sal||' 所得税是:'||v_tax);

B、使用%type类型

对于上面的pl/sql块有一个问题:

就是如果员工的姓名超过了5字符的话,就会有错误,为了降低pl/sql程序的维护工作量,可以使用%type属性定义变量,这样它会按照数据库列来确定你定义的变量的类型和长度。

语法:标识符名 表名.列名%type;

declear

c_tax_rate number(3,2):=0.03;

v_ename emp.ename%type;

v_sal emp.sal%type;

v_tax number(7,2);

begin

select ename,sal into v_ename,v_sal from emp where empno=&no;

v_tax:=v_sal*c_tax_rate;

dbms_output.put_line('姓名是:'||v_ename||' 工资是:'||v_sal||' 所得税是:'||v_tax);

2、复合变量(composite)

用于存储多个值的变量。主要包括这几种pl/sql记录、pl/sql表、嵌套表、varray。

1、pl/sql记录

类似于高级语言中的结构体,需要注意的是,当引用pl/sql记录成员时,必须要加记录变量作为前缀(记录变量.记录成员)。

declare

type emp_record_type is record(name emp.ename%type, salary emp.sal%type,title emp.job%type);

sp_record emp_record_type;

begin

select ename,sal,job into sp_record from emp where empno=7788;

dbms_output.put_line('员工名:'||sp_record.name);

2、pl/sql表

相当于高级语言中的数组,但是需要注意的是在高级语言中数组的下标不能为负数,而pl/sql是可以为负数的,并且表元素的下标没有限制。

declare

type sp_table_type is table of emp.ename%type index by binary_integer;

sp_table sp_table_type;

begin

select ename into sp_table(0) from emp where empno=7788;

dbms_output.put_line('员工名:'||sp_table(0));

sp_table_type:是pl/sql表类型

emp.ename%type:指定了表的元素的类型和长度

sp_table:是pl/sql表变量

sp_table(0):表示下标为0的元素

3、参照变量

概述:参照变量是指用于存放数值指针的变量,通过使用参照变量,可以使得应用程序共享相同对象,从而降低占用空间。在编写pl/sql程序时,可以使用游标变量(ref cursor)和对象类型变量(ref obj_type)两种参照变量类型。

1、游标变量(ref cursor)

使用游标时,当定义游标时不需要指定相应的select语句,但是当使用游标时(open时)需要指定select语句,这样一个游标就与一个select 语句结合了。

请使用pl/sql编写一个块,可以输入部门号,并显示该部门所有员工姓名和他的工资

declare

type sp_emp_cursor is ref cursor;

test_cursor sp_emp_cursor;

v_ename emp.ename%type;

v_sal emp.sal%type

begin

opent test_cursor for select ename,sal from emp where deptno=&no;

fetch test_cursor into v_ename,v_sal;

exit when test_cursor%notfound

dbms_output.putline('姓名:'||v_ename||' 工资:'||v_sal);

endloop;

close test_cursor;

九、控制结构

概述:在任何计算机语言(C、Java、Pascal)都有各种控制语句(条件语句、循环结构、顺序控制结构),在pl/sql中也存在这样的控制结构。

1、条件分支语句

pl/sql中提供了三种条件分支语句。if-then、if-then-else、if-then-elsif-else。

(1)简单的条件判断if-then

案例:编写一个过程,可以输入一个雇员名,如果该雇员的工资低于2000,就给该雇员工资增加10%。

create procedure IncreaseSal(spName varchar2) is

v_sal emp.sal%type;

begin

select sal into v_sal from emp where ename=spName;

if v_sal<2000 then

update emp sal=sal+sal*10% where ename=spName;

end if;

(2)二重条件分支if-then-else

案例:编写一个过程,可以输入一个雇员名,如果该雇员的补助不是0,就在原来的基础上增加100;如果补助为0就把补助设为200。

create procedure IncreaseComm(spName varchar2) is

v_comm emp.comm%type;

begin

select comm into v_comm from emp where ename=spName;

if v_comm<>0 then

update emp set comm=comm+100 where ename=spName;

update emp set comm=200 where ename=spName;

end if;

(3)多重条件分支if-then-elsif-else

案例:编写一个过程,可以输入一个雇员编号,如果该雇员的职位是PRESIDENT就给他的工资增加1000,如果该雇员的职位是MANAGER就给他的工资增加500,其他职位的雇员工资增加200。

create procedure IncreaseSal(spNo number) is

v_job emp.job%type;

begin

select job into v_job from emp where empno=spNo;

if v_job='PRESIDENT' then

update emp set sal=sal+1000 where empno=spNo;

elsif v_job='MANAGER'

update emp set sal=sal+500 where empno=spNo;

update emp set sal=sal+200 where empno=spNo;

end if;

2、循环语句

(1)基本循环

loop是pl/sql中最简单的循环语句,这种循环语句以loop开头,以end loop结尾,这种循环至少会被执行一次。

案例:编写一个过程,可输入用户名,并循环添加10个用户到Users表中,用户编号从1开始增加。

create procedure AddUser(spName varchar2) is

v_num number(2):=1;

begin

insert into Users values(v_num,spName);

exit when v_num=10;

v_num:=v_num+1;

endloop;

(2)While循环

基本循环至少要执行循环体一次,而对于while循环来说,只有条件为true时,才会执行循环体语句,while循环以while 条件 loop开始,以end loop结束。

编写一个过程,可输入用户名,并循环添加10个用户到Users表中,用户编号从11开始增加

create procedure AddUser(spName varchar2) is

v_num number(3):=11;

begin

while v_num<=20 loop

insert into Users values(v_num,spName);

v_num:=v_num+1;

endloop;

(3)for循环

基本for循环的基本结构如下

begin

for i in reverse 1..10 loop

insert into Users values(i,'Kevin');

end loop;

3、顺序控制语句

(1)goto语句

goto语句用于跳转到特定标号去执行有车,注意由于使用goto语句会增加程序的复杂度,并使得应用程序可读性变差,所以在一般应用开发时,建议大家不要使用goto语句

基本语法如下:

goto label:其中label是已经定义好的标号名。

declare

i number(4):=1;

begin

dbms_output.put_line("输出i='||i");

if i=10 then

goto end_loop

end if;

i:=i+1;

endloop;

<<end_loop>>

dbms_output.put_line("循环结束");

(2)null

null语句不会执行任何操作,并且会直接将控制传递到下一条语句。使用null语句的主要好处是可以提高pl/sql的可读性。

declare

v_sal emp.sal%type;

begin

select sal into v_sal from emp where ename=spName;

if v_sal<2000 then

update emp sal=sal+sal*10% where ename=spName;

null;

end if;

十、编写分页过程

概述:分页时任何一个网站(bbs、网上商城、Blog)都会使用到的技术,因此学习pl/sql编程开发就一定要掌握该技术。

案例:编写一个过程完成分页。

--创建一个包,存放游标。

create package ListPackage as

type page_cursor is ref cursor;

--开始编写分页的过程

create procedure PagedList(

tableName in varchar2, --要查询的表名

sortColumn in varchar2, --欲排序的列名

pagesize in number, --每页显示的记录数

currentPage in number, --当前页号

myRowCount out number, --表中总共的记录数

myPageCount out number, --共有多少页

p_cursor out ListPackage.page_cursor --游标变量

v_sql varchar2(1000);

v_begin number:=(currentPage-1)*pagesize+1;

v_end number:=currentPage*pagesize;

begin

v_sql:='select * from(select *, rownum rn from (select * from '||tableName||' order by '||sortColumn||') t1 where rownum<='||v_end||') where rn>='||v_begin;

open p_cursor for v_sql;

--计算myRowCount和myPageCount

v_sql:='select count(*) from '||tableName;

execute immediate v_sql into myRowCount;

if mod(myRowCount,pagesize)=0 then

myPageCount:=myRowCount/pagesize;

myPageCount:=myRowCount/pagesize+1;

end if;

close p_cursor;

十一、例外处理

1、例外的分类

Oracle将例外分为预定义例外、非预定义例外和自定义例外三种。

预定义例外:用于处理常见的Oracle错误。

非预定义例外:用于处理预定义例外不能处理的例外。

自定义例外:用于处理与Oracle错误无关的其他情况。

2、处理预定义例外

预定义例外时由pl/sql所提供的系统例外。当pl/sql应用程序违反了Oracle规定的限制时,则会隐含的触发一个内部例外。pl/sql为开发人员提供了二十多个预定义例外。我们给大家介绍常用的例外。

(1)预定义例外case_not_found

在开发pl/sql块中编写case语句时,如果在when子句中没有包含必须的条件分支,就会触发case_not_found的例外。

create procedure sp_pro6(spno number) is

v_sal emp.sal%type;

begin

select sal into v_sal from emp where empno=spno;

when v_sal<1000 then

update emp set sal=sal+100 where empno=spno;

when v_sal<2000 then

update emp set sal=sal+200 where empno=spno;

end case;

exception

when case_not_found then

dbms_output.put_line('case语句没有与'||v_sal||'相匹配的条件');

(2)预定义例外cursor_already_open

当从新打开已经打开的游标时,会隐含的触发例外cursor_already_open。

declare

cursor emp_cursor is select ename,sal from emp;

begin

open emp_cursor;

for emp_record1 in emp_cursor loop

dbms_output.put_line(emp_record1.ename);

end loop;

exception

when cursor_already_open then

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

(3)预定义例外dup_val_on_index

在唯一索引所对应的列上插入重复的值时,会隐含的触发例外dup_val_on_index例外。

begin

insert into dept values(10.'公关部','北京');

exception

when dup_val_on_index then

dbms_output.put_line('在deptno列上不能出现重复值');

(4)预定义例外invalid_cursor

当试图在不合法的游标上执行操作时,会触发该例外。

例如:视图从没有打开的游标提取数据,或是关闭没有打开的游标。则会触发该例外。

declare

cursor emp_cursor is select ename,sal from emp;

emp_record emp_cursor%rowtype;

begin

fetch emp_cursor into emp_record;

dbms_output.put_line(emp_record.ename);

close emp_cursor;

exception

when invalid_cursor then

dbms_output.put_line('请检查游标是否打开');

(5)预定义例外invalid_number

当输入的数据有误时,会触发该例外。

案例:数字100写成了1oo就会触发该例外

begin

update emp set sal=sal+'1oo';

exception

when invalid_number then

dbms_output.put_line('输入数字不正确');

(6)预定义例外no_data_found

下面是一个pl/sql块,当执行select into没有返回行,就会触发该例外。

declare

v_sal emp.sal%type;

begin

select sal into v_sal from emp where ename='&name';

exception

when no_data_found then

dbms_output.put_line('不存在该员工');

(7)预定义例外too_many_rows

当执行select into语句时,如果返回超过了一行,则会触发该例外。

declare

v_ename emp.ename%type;

begin

select ename into v_ename from emp;

exception

when too_many_rows then

dbms_output.put_line('返回了多行');

(8)预定义例外zero_divide

当执行除0操作时,则会触发给例外。

(9)预定义例外value_error

当在执行赋值操作时,如果变量的长度不足以容纳实际数据,则会触发该例外value_error。

declare

v_ename varchar2(5);

begin

select ename into v_ename from emp where empno=&no;

dbms_output.put_line(v_ename);

exception

when value_error then

dbms_output.put_line('变量尺寸不足');

(10)其它预定义例外

A、login_denide

当用户非法登录时,会触发该例外。

B、not_logged_on

如果用户没有登录就执行dml操作,就会触发该例外。

C、storage_error

如果超出了内存空间或是内存被损坏,就触发该例外。

D、timeout_on_resourece

如果Oracle在等待资源时,出现超时就触发该例外。

3、非预定义例外

非预定义例外用于处理与预定义例外无关的Oracle错误,使用预定义例外只能处理21个Oracle错误,而当使用pl/sql开发应用程序时,可能会遇到其他的一些Oracle错误。比如在pl/sql快中执行dml语句时,违反了约束规定等等。在这样的情况下,也可以处理Oracle的各种例外。

4、处理自定义例外

预定义例外和非预定义例外都是Oracle错误相关的,并且处在的Oracle错误会隐含的触发相应的例外。而自定义例外与Oracle错误没有任何关联,它是由开发人员为特定情况所定义的例外。

案例:请编写一个pl/sql块,接收一个雇员的编号,并给该雇员工资增加1000元,如果该雇员不存在请提示。

create procedure IncreaseSal(spno number) is

myException exception;

begin

update emp set sal=sal+100 where empno=spno;

if sql%not_found then

raise myException;

end if;

exception

when myException then

dbms_output.put_line('没有更新任何用户');

十二、Oracle视图

概述:视图是一个虚拟表,其内容由查询定义,同真实表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在,行和列数据来自有定义视图的查询所引用的表,并且在引用视图时动态生成。

1、视图与表的区别

A、表需要占用磁盘空间,视图不需要。

B、视图不能添加索引。

C、使用视图可以简化复杂查询。

D、视图有利于提高安全性。

2、创建视图

create view 视图名 as select语句[with read only]

3、创建或修改视图

create or replace view 视图名 as select语句[with read only]

4、删除视图

drop view 视图名

收藏于 2013-12-16
文章优化有问题?点击这里反馈URL给我们

pl/sql编程的更多相关文章

  1. ORACLE PL/SQL编程详解

    ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...

  2. Oracle数据库编程:PL/SQL编程基础

    2.PL/SQL编程基础: PL/SQL块:        declare        定义部分        begin        执行部分        exception        异 ...

  3. [强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)

    原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天 ...

  4. ORACLE PL/SQL编程之八:把触发器说透

    原文:ORACLE PL/SQL编程之八:把触发器说透 ORACLE PL/SQL编程之八: 把触发器说透 大家一定要评论呀,感谢!光发表就花了我将近一个下午. 本篇主要内容如下: 8.1 触发器类型 ...

  5. [推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼、百战不殆)

    原文:[推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼.百战不殆) [推荐]ORACLE PL/SQL编程之五: 异常错误处理(知已知彼.百战不殆) 继上三篇:ORACLE PL/S ...

  6. ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)

    原文:ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) ORACLE PL/SQL编程之六: 把过程与函数说透(穷追猛打,把根儿都拔起!)   继上篇:ORACLE P ...

  7. [推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆)

    原文:[推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆) [推荐]ORACLE PL/SQL编程详解之三: PL/SQL流程控制语句(不给规则,不成方圆) ...

  8. [推荐]ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不到)

    原文:[推荐]ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不到) [推荐]ORACLE PL/SQL编程之四: 把游标说透(不怕做不到,只怕想不到) 继上两篇:ORACLE PL ...

  9. 【强烈强烈推荐】《ORACLE PL/SQL编程详解》全原创(共八篇)--系列文章导航

    原文:[强烈强烈推荐]<ORACLE PL/SQL编程详解>全原创(共八篇)--系列文章导航 <ORACLE PL/SQL编程详解> 系列文章目录导航 ——通过知识共享树立个人 ...

随机推荐

  1. 开源cms

    提起开源cms,大家第一想到的是php的cms,因为php开源的最早,也最为用户和站长们认可,随着各大cms系统的功能的不断完善和各式各样的开源cms的出现,.net和java的高端的cms系统也逐渐 ...

  2. SublimeText3使用技巧总结

    Ctrl + R : 查找函数和变量 Ctrl + P: 查找当前工程下面的文件 Ctrl + ":" : 查找变量 Ctrl + "g" : 输入行数跳转到指 ...

  3. 【问题】Win7 系统下 Firefox hostadmin插件无法修改Host

    今天遇到一个奇葩问题:win 7系统,firefox hostAdmin插件无法修改Host了,提示“ write hosts file failed check permissions”,肯定是哪里 ...

  4. Linux Foundation Secure Boot System Released

    As promised, here is the Linux Foundation UEFI secure boot system.  This was actually released to us ...

  5. iOS中SQLite知识点总结2

    数据库(SQLite) 01-多表查询 格式:select 字段1,字段2,... from 表名1,表名2; 别名:select 别名1.字段1 as 字段别名1,别名2.字段2 as 字段别名2, ...

  6. 【bzoj3172】 [Tjoi2013]单词

    题目描述 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. 输入 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个 ...

  7. find job

    处于找工作的状态... 优秀求职者的5个问题: 1.在刚进来2-3个月里,你希望我可以完成哪些工作? 2.公司的优秀员工共同特征是什么? 3.业余时间,公司的员工一般在干什么?

  8. JAVA中toString方法的作用(转)

    因为它是Object里面已经有了的方法,而所有类都是继承Object,所以“所有对象都有这个方法”. 它通常只是为了方便输出,比如System.out.println(xx),括号里面的“xx”如果不 ...

  9. 字符串右移n位(C++实现)

    字符串右移n位(C++实现): // ShiftNString.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <i ...

  10. 在Nginx中搭建Nagios监控平台

    本文只做Nginx下Nagiox安装的说明,其它关于Nagios监控的详细配置请参考我的另一篇文章[Ubuntu 10.04下构建Nagios监控平台] Nagios依赖PHP环境和perl环境.由于 ...