练习 1:
--创建package header
CREATE OR REPLACE PACKAGE emp_pack
IS
PROCEDURE new_emp
(v_ename emp.ename%TYPE,
v_job emp.job%TYPE DEFAULT 'SALESMAN',
v_mgr emp.mgr%TYPE DEFAULT 7839,
v_sal emp.sal%TYPE DEFAULT 1000,
v_comm emp.comm%TYPE DEFAULT 0,
v_deptno emp.deptno%TYPE DEFAULT 30);
END emp_pack;
/
--创建package body
CREATE OR REPLACE PACKAGE BODY emp_pack
IS
FUNCTION valid_deptno --私有函数
(v_deptno IN dept.deptno%TYPE)
RETURN BOOLEAN
IS
v_dummy VARCHAR2(1);
BEGIN
SELECT 'x'
INTO v_dummy
FROM dept
WHERE deptno = v_deptno;
RETURN (TRUE);
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN(FALSE);
END valid_deptno;
PROCEDURE new_emp
(v_ename emp.ename%TYPE,
v_job emp.job%TYPE DEFAULT 'SALESMAN',
v_mgr emp.mgr%TYPE DEFAULT 7839,
v_sal emp.sal%TYPE DEFAULT 1000,
v_comm emp.comm%TYPE DEFAULT 0,
v_deptno emp.deptno%TYPE DEFAULT 30)
IS
BEGIN
IF valid_deptno(v_deptno) THEN
INSERT INTO emp
VALUES (seq_empno.NEXTVAL, v_ename, v_job, v_mgr,
TRUNC (SYSDATE, 'DD'), v_sal, v_comm, v_deptno);
ELSE
DBMS_OUTPUT.PUT_LINE('Invalid department number. Try again.');
END IF;
END new_emp;
END emp_pack;
/
****
HR@prod> l
1 create or replace package pack_sal
2 is
3 procedure add_sal (v_id in employees.employee_id%type,v_raise_sal in number);
4 function get_tax(v_id in employees.employee_id%type) return number;
5* end pack_sal;
HR@prod> /
Package created.
HR@prod> get pack_body.sql
1 create or replace package body pack_sal
2 is
3 procedure add_sal(v_id in employees.employee_id%type,
4 v_raise_sal in number)
5 is
6 begin
7 update employees set salary=salary+ v_raise_sal
8 where employee_id=v_id;
9 end add_sal;
10 function get_tax(v_id in employees.employee_id%type)
11 return number
12 is
13 v_sal number;
14 v_tax number;
15 begin
16 select salary into v_sal from employees
17 where employee_id=v_id;
18 if v_sal >= 5000 then
19 v_tax := (v_sal - 5000)*0.2;
20 return v_tax;
21 else
22 return v_sal*0.1;
23 end if;
24 end get_tax;
25* end;
HR@prod> /
Package body created.
HR@prod> desc pack_sal;
PROCEDURE ADD_SAL
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
V_ID NUMBER(6) IN
V_RAISE_SAL NUMBER IN
FUNCTION GET_TAX RETURNS NUMBER
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
V_ID NUMBER(6) IN
HR@prod> select salary from employees where employee_id=100;
SALARY
----------
26400
HR@prod> exec pack_sal.add_sal(100,600);
PL/SQL procedure successfully completed.
HR@prod> select salary from employees where employee_id=100;
SALARY
----------
27000
HR@prod> select pack_sal.get_tax(100) from dual;
PACK_SAL.GET_TAX(100)
---------------------
4400
----------------------------------------------------------------------
练习 2:重载
--创建package header
CREATE OR REPLACE PACKAGE over_load is
FUNCTION print_it(v_arg date)
RETURN VARCHAR2;
FUNCTION print_it(v_arg NUMBER)
RETURN VARCHAR2;
END over_load;
/
--创建package body
CREATE OR REPLACE PACKAGE BODY over_load is
FUNCTION print_it(v_arg date)
RETURN VARCHAR2
IS
BEGIN
RETURN to_char(v_arg,'yyyy-mm-dd');
END print_it;
FUNCTION print_it(v_arg NUMBER) -----此处应该是NUMBER类型
RETURN VARCHAR2
IS
BEGIN
RETURN to_char(v_arg,'L99,999.00'); //L--->$
END print_it;
END over_load;
/
--包的调用
VARIABLE g_datevalue varchar2(40);
execute :g_datevalue := over_load.PRINT_IT(sysdate);
print g_datevalue
VARIABLE g_datevalue varchar2(40);
execute :g_datevalue := over_load.PRINT_IT(123);
print g_datevalue
select over_load.print_it(123) from dual;
select over_load.print_it(to_date('2013-11-19','yyyy-mm-dd'));
************************************************************************
SYS@prod> get pack1.sql
1 create or replace package over_load
2 is
3 function print_strings(v_date date) return VARCHAR2;
4 function print_strings(v_number number) return VARCHAR2;
5* end over_load;
SYS@prod> /
Package created.
SYS@prod> get pack2.sql
1 create or replace package body over_load
2 is
3 function print_strings(v_date date) return VARCHAR2
4 is
5 begin
6 return to_char(v_date,'yyyy-mm-dd hh24:mi:ss');
7 end print_strings;
8 function print_strings(v_number number) RETURN VARCHAR2
9 is
10 begin
11 return to_char(v_number,'L99,999,999,999.99');
12 end print_strings;
13* end over_load;
SYS@prod> /
Package body created.
SYS@prod> desc over_load;
FUNCTION PRINT_STRINGS RETURNS VARCHAR2
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
V_DATE DATE IN
FUNCTION PRINT_STRINGS RETURNS VARCHAR2
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
V_NUMBER NUMBER IN
SYS@prod> select over_load.print_strings(sysdate) from dual;
OVER_LOAD.PRINT_STRINGS(SYSDATE)
--------------------------------------------------------------------------------
2012-12-28 10:45:42
SYS@prod> select over_load.print_strings(123456789) from dual;
OVER_LOAD.PRINT_STRINGS(123456789)
--------------------------------------------------------------------------------
$123,456,789.00
----------------------------------------------------------------------
包与依赖:断开了依赖链
DROP TABLE T;
create table t (x int);
create view v as select * from t;
create procedure p
is
begin
for x in (select * from v)
loop
null;
end loop;
end;
/
create function f return number
is
l_cnt number;
begin
select count(*) into l_cnt from t;
return l_cnt;
end;
/
查看依赖关系:
select name,type,referenced_name,referenced_type
from user_DEPENDENCIES
where name IN ('F','P','T','V')
AND referenced_owner='SCOTT'
order by name;
查看对象有效状态:
select object_name,object_type,status
from user_objects
where object_name in ('F','P','T','V');
修改T表结构后,再看有效性:
alter table t add y number;
select object_name,object_type,status
from user_objects
where object_name in ('F','P','T','V');
V P F 无效
创建一个依赖P的过程后,再看有效性:
create procedure p2
is
begin
p;
end;
/
select object_name,object_type,status
from user_objects
where object_name in ('F','P','P2','T','V');
V P 重新有效!对P2的编译同时重新编译了V P!
使用包重做上面的实验:
create package pk1
is
procedure p;
end;
/
create package body pk1
is
procedure p
is
begin
for x in (select * from v)
loop
null;
end loop;
end;
end pk1;
/
create package pk2
is
procedure p;
end;
/
create package body pk2
is
procedure p
is
begin
pk1.p;
end;
end pk2;
/
select object_name,object_type,status
from user_objects
where object_name in ('F','P','P2','T','V','PK1','PK2');
再次修改T,再查看有效性!PK1 包体无效了!因为PK1 包体通过V依赖与T(依赖链)
而PK2仍然有效!PK2依赖与PK1而不是PK1包体(因而断开了依赖链)!
exec pk2.p;
select object_name,object_type,status
from user_objects
where object_name in ('F','P','P2','T','V','PK1','PK2');
-------------------------------------------------------------------------------