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循环会自动打开游标和关闭游标