1.认识PL/SQL的函数
2.创建包和包体,使用包
3.PL/SQL变量的类型
——1、认识PL/SQL的函数
--输入雇员姓名,返回年薪
create or replace function sp_func(spName varchar2) return number is
yearSal number(7,2);
begin
select sal*12+nvl(comm,0)*12 into yearSal from emp where ename=spName;
return yearSal;
end;
——总结语法:
/* create【or replace】function 函数名(参数1 类型1,参数2 类型2,...) return 返回值类型 is
--变量、常量和游标的定义;
begin
--执行部分;
return 返回值;
exception
--异常处理部分
end;
*/
——调用函数
var income number; //定义全局变量:var 变量名 变量
类型
call sp_func('SCOTT') into:income; //全局变量赋值:call 函数 into:
全局变量
print income; //打印全局变量:print 全局变量名
——调用函数2
select sp_func('SCOTT') from dual;
--包:组织管理过程和函数的一种机制,主要有两部分组成,包规范和包体
--包里面主要是声明一下过程和函数,过程和函数的实现放在包体里面
--问题:创建一个包,包含一个过程,包含一个函数,过程:输入员工姓名,新的工资,更新员工工资;函数:输入员工姓名,计算该员工的年收入
--创建包:只是声明过程和函数
create or replace package sp_package is
procedure update_sal(name emp.ename%type,newSal emp.sal%type);
function annual_income(name emp.ename%type) return number;
end;
——总结语法:
/*
create [or replace] package 包名 is
过程1声明;
过程2声明;
...
函数1声明;
函数2声明;
...
end;
*/
——创建包体:过程和函数的实现
create or replace package body sp_package is
procedure update_sal(name emp.ename%type,newSal emp.sal%type) is
begin
update emp set sal=newSal where ename=name;
end;
function annual_income(name emp.ename%type) return number is
yearSal number(7,2);
begin
select sal*12+nvl(comm,0)*12 into yearSal from emp where ename=name;
return yearSal;
end;
end;
——创建包体的语法:
/*
create [or replace] package body 包名 is
过程1实现体
过程2实现体
...
函数1实现体
函数2实现体
...
end;
*/
——包中的过程和函数的调用:包名.过程名 或者 包名.函数名
exec sp_package.update_sal('SCOTT',4500);
var income number;
call sp_package.annual_income('SCOTT') into:income;
print income;
select sp_package.annual_income('SCOTT') from dual;
——触发器:触发器是指隐含执行的存储过程,当定义触发器时,必须指定触发事件和触发操作。
——常用的触发事件包括:insert,update,delete语句
——触发器时一个PL/SQL块,可以通过create trigger来创建
——PL/SQL变量:标量类型,复合类型,参照类型,lob(large object)类型
——标量类型:变量名 【constant】 数据类型 【not null】【:=值】| 【default 值】;
——案例:
定义一个变长的字符串:v_ename varchar2(20);
定义一个小数:v_yearsal number(7,2);
定义一个小数,给初始值为3.14:v_sal number(3,2):=3.14;
定义一个常量PI给默认值为3.14:PI constant number(3,2):=3.14;
定义一个日期类型:v_hiredate date
定义一个布尔类型:v_invid boolean not null default false;
—编写一个PL/SQL块,输入员工编号,显示雇员的姓名和工资,以及个人所得税(税率为0.05)
declare
v_tax_rate constant number(3,2):=0.05;
v_ename emp.ename%type;
v_sal emp.sal%type;
v_personal_tax number(7,2);
begin
select ename,sal into v_ename,v_sal from emp where empno=&no;
v_personal_tax:=v_sal*v_tax_rate;
dbms_output.put_line('姓名:'||v_ename||' 工资:'||v_sal||' 个人所得税:'||v_personal_tax);
end;
——%type:标量类型的一种,比较灵活。
——复合类型:(1)PL/SQL的记录类型;(2)PL/SQL的表类型;(3)嵌套表类型;(4)varray类型
——PL/SQL记录类型:%rowtype
--输入一个员工编号,显示该员工的所有信息
declare
v_emp emp%rowtype;
begin
select * into v_emp from emp where empno=&no;
dbms_output.put_line('姓名:'||v_emp.ename||' 工作:'||v_emp.job||' 工资'||v_emp.sal||' 奖金:'||v_emp.comm);
end;
——记录类型
declare
type emp_record_type is record(name emp.ename%type,salary emp.sal%type,dept emp.deptno%type);
sp_record emp_record_type;
begin
select ename,sal,deptno into sp_record from emp where empno=&no;
dbms_output.put_line('姓名:'||sp_record.name||';工资:'||sp_record.salary||';部门:'||sp_record.dept);
end;
——记录类型语法:
/*
type 类型名 is record(变量1 数据类型1,变量2 数据类型2,...);
变量名 类型名;
*/
——PL/SQL的表类型
——表类型:类似于高级语言中的数组
——定义表类型时,不定义表的大小
——定义表类型,需要指定表中每个数据的类型
——表类型下表可以为负,也可以为正
declare
type emp_table_type is table of emp.ename%type index by binary_integer;
sp_table emp_table_type;
begin
select ename into sp_table(-1) from emp where empno=&no;
dbms_output.put_line('姓名:'||sp_table(-1));
end;
——表类型语法:
/*
type 类型名 is table of 数据类型 index by binary_integer
变量名 类型名;
*/
——参照类型:游标
——案例:输入一个部门名称,显示该部门所有员工的姓名和工资
declare
type sp_emp_cursor is ref cursor;
test_cursor sp_emp_cursor;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open test_cursor for select ename,sal from emp where deptno=&no;
loop
fetch test_cursor into v_ename,v_sal;
exit when test_cursor%notfound;
dbms_output.put_line('姓名:'||v_ename||';工资:'||v_sal);
end loop;
close test_cursor;
end;
/*总结:
(1)type sp_emp_cursor is ref cursor:表明sp_emp_cursor是一个游标类型
(2)test_cursor sp_emp_cursor;定义一个游标变量test_cursor,是sp_emp_cursor类型
(3)open test_cursor for 查询语句;
(4) fetch 游标变量名 into 变量1,变量2;
(5)exit when test_cursor%notfound:定义循环退出的条件
(6)close test_cursor:关闭游标
*/
——写法2:
declare
cursor v_cursor is select ename,sal from emp where deptno=&no;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open v_cursor;
loop
fetch v_cursor into v_ename,v_sal;
exit when v_cursor%notfound;
dbms_output.put_line('姓名:'||v_ename||';工资:'||v_sal);
end loop;
close v_cursor;
end;
/*
cursor 游标变量名 is select语句;
open 游标变量
fetch 游标变量 into 变量1,变量2,...
close 游标变量
*/
——写法3:用for循环使用游标
declare
cursor v_cursor is select ename,sal from emp where deptno=&no;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
for v_cursor in v_cursor loop
v_ename:=v_cursor.ename;
v_sal:=v_cursors.sal;
dbms_output.put_line('姓名:'||v_ename||';工资:'||v_sal);
end loop;
end;
——for循环会自动打开游标和关闭游标