一:编写
CREATE [ OR REPLACE ] FUNCTION function_name
(argument1 [mode1] datatype1,
argument2 [mode2] datetype2,
...)
RETURN datatype
IS | AS
[local_variable_declarations;...]
BEGIN
--actions;
RETURN expression;
END [function_name];
建立函数的几点注意事项
1.指定参数数据类型时(argument),不能指定其长度
2.函数头部必须指定return子句,函数体内至少要包含一条return语句
3.可以指定in参数,也可以指定out参数,以及in out 参数
4.可以为参数指定缺省值。指定缺省值时使用default关键字。如arg1 varchar2 default 'SCOTT'
演示几个函数
IN,OUT,IN OUT是形参的模式。若省略,则为IN模式。IN模式的形参只能将实参传递给形参,进入函数内部,但只能读不能写,函数返回时实参的值不变。OUT模式的形参会忽略调用时的实参值(或说该形参的初始值总是NULL),但在函数内部可以被读或写,函数返回时形参的值会赋予给实参。IN OUT具有前两种模式的特性,即调用时,实参的值总是传递给形参,结束时,形参的值传递给实参。调用时,对于IN模式的实参可以是常量或变量,但对于OUT和IN OUT模式的实参必须是变量。
--无参数
[email protected]> create or replace function get_user 2 return varchar2 3 is 4 v_user varchar2(20); 5 begin 6 select username into v_user from user_users; 7 return v_user; 8 end; 9 /
--
--使用全局变量接收函数的返回值
[email protected]>var v1 varchar2(20) [email protected]>exec:v1:=get_user PL/SQL procedure successfully completed. [email protected]>print v1; V1 -------------------------------- SCOTT
--使用本地变量接收函数的返回值
[email protected]>set serveroutput on; [email protected]>declareuser_name varchar2(20); 2 begin 3 user_name:=get_user(); 4 dbms_output.put_line('Current user: '||user_name); 5 end; 6 / Currentuser: SCOTT PL/SQL procedure successfully completed.
--在SQL语句中直接调用函数
[email protected]>select get_user from dual; GET_USER --------------------- SCOTT
--使用dbms_output调用函数(此调用作为存储过程的一个参数来进行调用)
[email protected]>set serveroutput on; [email protected]>exec dbms_output.put_line('Current user: '||get_user); Currentuser: SCOTT
--带in参数
[email protected]> create or replace function raise_sal(name in varchar2) --注意此处定义时参数并为指定类型的长度 2 return number 3 as 4 v_sal emp.sal%type; 5 begin 6 select sal*1.2 into v_sal from emp 7 where upper(ename)=upper(name); 8 return v_sal; 9 exception 10 when no_data_found then 11 raise_application_error(-20000,'Current Employee is not exists'); 12 end; 13 / Function created. [email protected]> select sal,raise_sal('SCOTT') from emp where ename='SCOTT'; SAL RAISE_SAL('SCOTT') ---------- ------------------ 3100 3720 [email protected]> select raise_sal('Robinson') from dual; select raise_sal('Robinson') from dual * ERROR at line 1: ORA-20000: Current Employee is not exists ORA-06512: at "SCOTT.GET_SAL", line 11
--带out参数
[email protected]> create or replace function get_info 2 (name varchar2,title out varchar2) 3 return varchar2 4 as 5 deptname dept.dname%type; 6 begin 7 select e.job,d.dname into title,deptname 8 from emp e inner join dept d 9 on e.deptno=d.deptno 10 where upper(e.ename)=upper(name); 11 return deptname; 12 exception 13 when no_data_found then 14 raise_application_error(-20000,'Current Employee is not exists'); 15 end; 16 / Function created. 注意对于使用out参数的函数,不能使用SQL语句来调用。而必须定义变量接收out参数和函数的返回值。 调用如下 [email protected]> var job varchar2(20); [email protected]> var dname varchar2(20); [email protected]> exec :dname:=get_info('scott',:job); PL/SQL procedure successfully completed. [email protected]> print dname job; DNAME -------------------------------- RESEARCH JOB -------------------------------- ANALYST
--带有in out 参数
[email protected]> create or replace function comp 2 (num1 number,num2 in out number) 3 return number 4 as 5 v_result number(6); 6 v_remainder number; 7 begin 8 v_result:=num1*num2; 9 v_remainder:=mod(num1,num2); 10 num2:=v_remainder; 11 return v_result; 12 exception 13 when zero_divide then 14 raise_application_error(-20000,'Divison by zero'); 15 end; 16 / Function created. [email protected]> var result1 number; [email protected]> var result2 number; [email protected]> exec :result2:=10 PL/SQL procedure successfully completed. [email protected]> exec :result1:=comp(16,:result2); PL/SQL procedure successfully completed. [email protected]> print result1 result2; RESULT1 ---------- 160 RESULT2 ---------- 6
二:创建方式
有几种方式可以创建函数
1:直接在sqlplus中编写创建
SQL> CREATE OR REPLACE FUNCTION wordcount (str IN VARCHAR2) 2 RETURN PLS_INTEGER 3 AS 4 words PLS_INTEGER := 0; 5 len PLS_INTEGER := NVL (LENGTH (str), 0); 6 inside_a_word BOOLEAN; 7 BEGIN 8 FOR i IN 1 .. len + 1 9 LOOP 10 IF ASCII (SUBSTR (str, i, 1)) < 33 OR i > len 11 THEN 12 IF inside_a_word 13 THEN 14 words := words + 1; 15 inside_a_word := FALSE; 16 END IF; 17 ELSE 18 inside_a_word := TRUE; 19 END IF; 20 END LOOP; 21 22 RETURN words; 23 END; 24 / Function created. SQL>
2:现在文件中编写,然后@执行脚本
[[email protected] ~]$ more save.sql CREATE OR REPLACE FUNCTION wordcount (str IN VARCHAR2) RETURN PLS_INTEGER AS words PLS_INTEGER := 0; len PLS_INTEGER := NVL (LENGTH (str), 0); inside_a_word BOOLEAN; BEGIN FOR i IN 1 .. len + 1 LOOP IF ASCII (SUBSTR (str, i, 1)) < 33 OR i > len THEN IF inside_a_word THEN words := words + 1; inside_a_word := FALSE; END IF; ELSE inside_a_word := TRUE; END IF; END LOOP; RETURN words; END; / [[email protected] ~]$ pwd /home/oracle [[email protected] ~]$
然后登录到sqlplus中@执行(注意此时文件路径需在当前路径下,或者使用全路径,或者设置sqlpath环境变量)
SQL> @save.sql Function created. SQL>
如果想看源代码
SQL> set echo on
三:调用
BEGIN
DBMS_OUTPUT.put_line (
'There are ' || wordcount (fuwenchao) || ' words in a tab'
);
END;
/
---
SELECT isbn, wordcount (description)
FROM books
/
四:查看
查看内容的几种方法:
1:
SQL> select line,text from user_source where name='WORDCOUNT';
LINE
----------
TEXT
--------------------------------------------------------------------------------
1
FUNCTION wordcount (str IN VARCHAR2)
2
RETURN PLS_INTEGER
3
AS
LINE
----------
TEXT
--------------------------------------------------------------------------------
4
words PLS_INTEGER := 0;
可以看到,显示界面不是很友好
2:
SQL> exec dbms_output.put_line(dbms_metadata.get_ddl(object_type => 'FUNCTION',name => 'WORDCOUNT'));
CREATE OR REPLACE FUNCTION "SYS"."WORDCOUNT" (str IN VARCHAR2)
RETURN
PLS_INTEGER
AS
words PLS_INTEGER := 0;
len
PLS_INTEGER := NVL (LENGTH (str), 0);
inside_a_word BOOLEAN;
BEGIN
FOR i
IN 1 .. len + 1
LOOP
IF ASCII (SUBSTR (str, i, 1)) < 33 OR i > len
THEN
IF inside_a_word
THEN
words := words + 1;
inside_a_word := FALSE;
END IF;
ELSE
inside_a_word :=
TRUE;
END IF;
END LOOP;
RETURN words;
END;
PL/SQL procedure successfully completed.
SQL>
3:这种显示很奇怪,只有一行
SQL> SELECT * FROM ALL_SOURCE where TYPE='FUNCTION' AND TEXT LIKE '%WORDCOUNT%';
no rows selected
SQL> c/WORDCOUNT/wordcount
1* SELECT * FROM ALL_SOURCE where TYPE='FUNCTION' AND TEXT LIKE '%wordcount%'
SQL> /
OWNER NAME TYPE
------------------------------ ------------------------------ ------------
LINE
----------
TEXT
--------------------------------------------------------------------------------
SYS WORDCOUNT FUNCTION
1
FUNCTION wordcount (str IN VARCHAR2)
SQL>
--但是这样的话就行了
SQL> c/*/text
1* SELECT text FROM ALL_SOURCE where TYPE='FUNCTION' AND name LIKE '%WORDCOUNT%'
SQL> /
TEXT
--------------------------------------------------------------------------------
FUNCTION wordcount (str IN VARCHAR2)
RETURN PLS_INTEGER
AS
words PLS_INTEGER := 0;
len PLS_INTEGER := NVL (LENGTH (str), 0);
inside_a_word BOOLEAN;
BEGIN
FOR i IN 1 .. len + 1
LOOP
IF ASCII (SUBSTR (str, i, 1)) < 33 OR i > len
THEN
TEXT
--------------------------------------------------------------------------------
IF inside_a_word
THEN
words := words + 1;
inside_a_word := FALSE;
END IF;
ELSE
inside_a_word := TRUE;
END IF;
END LOOP;
RETURN words;
TEXT
--------------------------------------------------------------------------------
END;
23 rows selected.
4:显示调用接口概要信息
SQL> desc wordcount FUNCTION wordcount RETURNS BINARY_INTEGER Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- STR VARCHAR2 IN SQL>
5:小总结:
查看自定义函数名的话,用
select OBJECT_NAME FROM USER_OBJECTS WHERE OBJECT_TYPE=’FUNCTION’;
或者select OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_TYPE=’FUNCTION’;
或者select OBJECT_NAME FROM ALL_OBJECTS WHERE OBJECT_TYPE=’FUNCTION’;
函数的具体内容的话:
select TEXT FROM USER_SOURCE WHERE NAME=函数名;
select TEXT FROM ALL_SOURCE WHERE NAME=函数名;
select TEXT FROM DBA_SOURCE WHERE NAME=函数名;
五:授权
SQL> grant execute on wordcount to hr; Grant succeeded. SQL> SELECT table_name, grantee, privilege 2 FROM user_tab_privs_made 3 WHERE table_name = 'WORDCOUNT' 4 / TABLE_NAME GRANTEE ------------------------------ ------------------------------ PRIVILEGE ---------------------------------------- WORDCOUNT HR EXECUTE SQL>
六:删除
七:注意事项
1.函数的调用(其具体调用方法参照上面的演示)
a.使用全局变量接收函数的返回值
b.使用本地变量接受函数的返回值
c.在SQL语句中直接调用函数
d.使用dbms_output调用函数
注:函数在调用的时候需要按位置指定参数,没有存储过程参数传递灵活
必须具有execute 函数的权限
2.函数在SQL中调用的主要场合
由于函数必须要返回数据,因此只能作为表达式的一部分调用。此外函数可以在SQL语句的以下部分调用
a. select 命令的选择列表或子查询中
b. 条件表达式where, having子句中
c. connect by , start with ,order by 以及group by 子句中
d. insert 命令的values子句中
f. update 命令的set 子句中
3.函数在SQL中调用的限制
a. SQL语句中只能调用存储在服务器端的函数,而不能调用存储于客户端的函数
b. SQL语句中调用的函数只能带有输入参数IN,而不能带有输出参数OUT 以及输入输出参数IN OUT
c. SQL语句中调用的函数只能使用SQL支持的标准数据类型,不能使用PL/SQL特有的类型,如boolean,table,record等
d. SQL语句中调用的函数不能包含insert,update和delete 语句(注意理解,这里的DML指的是函数中使用DML,非外部调用SQL语句@20130905)
参考:
乐沙弥:http://blog.csdn.net/leshami/article/details/6069531
穷追猛打:http://www.cnblogs.com/huyong/archive/2011/04/28/2031541.html
转载于:https://blog.51cto.com/fuwenchao/1363860