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