一定要返回值并且只能返回一个值
一个OUT的过程 完全可以使用FUNCTION来改写
函数可以建立函数索引 ,函数建立时有deterministic
练习 1:
CREATE OR REPLACE FUNCTION get_sal
(p_id IN emp.empno%TYPE)
RETURN NUMBER
IS
v_salary emp.sal%TYPE :=0;
BEGIN
SELECT sal
INTO v_salary
FROM emp
WHERE empno = p_id;
RETURN v_salary;
END get_sal;
/
function调用
VARIABLE g_salary NUMBER
EXECUTE :g_salary := get_sal(7369);
PRINT g_salary
declare
v_sal number;
begin
v_sal:=get_sal(7788);
dbms_output.put_line(v_sal);
end;
/
select get_sal(7369) from dual;
***
create or replace function get_sal
(v_id in number)
return NUMBER
is
v_sal number;
begin
select salary into v_sal from employees
where employee_id=v_id;
return v_sal;
end;
/
HR@prod> variable g_salary number;
HR@prod> execute :g_salary := get_sal(100);
PL/SQL procedure successfully completed.
HR@prod> print g_salary;
G_SALARY
----------
26400
HR@prod> set serveroutput on
HR@prod> l
1 declare
2 o_salary number;
3 begin
4 o_salary := get_sal(100);
5 dbms_output.put_line(o_salary);
6* end;
HR@prod> /
26400
PL/SQL procedure successfully completed.
HR@prod> select get_sal(100) from dual;
GET_SAL(100)
------------
26400
练习 2:
CREATE OR REPLACE FUNCTION tax(p_value IN NUMBER)
RETURN NUMBER
IS
BEGIN
RETURN (p_value * 0.08);
END tax;
/
SELECT empno, ename, sal, tax(sal)
FROM emp
WHERE deptno = 10;
练习 3:
create or replace FUNCTION valid_deptno
(v_deptno IN d.deptno%TYPE)
RETURN BOOLEAN
IS
v_dummy VARCHAR2(1);
BEGIN
SELECT 'x'
INTO v_dummy
FROM d
WHERE deptno = v_deptno;
RETURN (TRUE);
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN(FALSE);
END valid_deptno;
/
*****
drop table test purge;
create table test (id number,name varchar2(20));
INSERT INTO TEST VALUES(101,'MARY');
COMMIT;
CREATE OR REPLACE FUNCTION VALID_ID
(v_id in number)
return boolean
is
temp_id number;
begin
select id into temp_id
from test
where id=v_id;
return (true);
exception
when no_data_found then
return (false);
end valid_id;
declare
v_id number := &id;
v_name varchar2(20) := '&name';
begin
if valid_id(v_id) then
dbms_output.put_line(v_id||'exists.');
else
insert into test values(v_id,v_name);
commit;
end if;
end;
/
*************************讲完包之后做为综合练习***********************************************
练习 4:确定返回值函数与效率(可以减少函数调用次数,出现在where条件中更有利!)
准备实验用表:
create table t1 (id varchar2(10));
begin
for i in 1..10 loop
insert into t1 values ('A');
end loop;
commit;
end;
/
创建包声明全局变量,用来做函数调用次数的计数器
create or replace package p
as
g_no number default 0;
end;
/
显示全局变量的值
exec dbms_output.put_line(chr(10)||p.g_no);
在函数中使全局变量自增
conn / as sysdba
@?/rdbms/admin/dbmslock
grant execute on dbms_lock to public;
conn scott/tiger
创建一个普通函数
create or replace function wait_row(i_v in varchar2,
i_sec in number default 5)
return varchar2
parallel_enable
as
begin
p.g_no := p.g_no+1;--函数每调用一次计数器加1
sys.dbms_lock.sleep(i_sec);--休眠的时间值
return i_v;
end;
/
调用函数:
select wait_row(id,0.1) from t1;
通过显示全局变量的当前值查看普通函数的工作次数
exec dbms_output.put_line(chr(10)||p.g_no);
10 --> 函数调用10次
将全局变量归零:
exec p.g_no := 0;
创建确定返回值函数:
create or replace function wait_row(i_v in varchar2,
i_sec in number default 5)
return varchar2 deterministic
parallel_enable
as
begin
p.g_no := p.g_no+1;
sys.dbms_lock.sleep(i_sec);
return i_v;
end;
/
再次调用函数:
select wait_row(id,0.1) from t1;
通过显示全局变量的当前值查看确定返回值函数的工作次数
exec dbms_output.put_line(chr(10)||p.g_no);
2 --> 函数调用2次,
说明在形式参数取值相同的时候确定
返回值函数的调用次数比普通函数少!意味着确定返回值
函数的效率会高于普通函数!
练习 5:确定返回值函数与基于函数的索引
create or replace function format_date (v_date date)
return varchar2
is
begin
return to_char(v_date,'yyyymmdd');
end;
/
orcl@ SCOTT> create index i_emp_hdate on emp(format_date(hiredate));
create index i_emp_hdate on emp(format_date(hiredate))
*
ERROR at line 1:
ORA-30553: The function is not deterministic
create or replace function format_date (v_date date)
return varchar2 deterministic
is
begin
return to_char(v_date,'yyyymmdd');
end;
/
orcl@ SCOTT> create index i_emp_hdate on emp(format_date(hiredate));
Index created.