Oracle 函数

一:编写

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模式的实参可以是常量或变量,但对于OUTIN OUT模式的实参必须是变量。


--无参数

scott@ORCL> 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  /

--

--使用全局变量接收函数的返回值

scott@ORCL>var v1 varchar2(20)
            scott@ORCL>exec:v1:=get_user
            PL/SQL procedure successfully completed.
            scott@ORCL>print v1;
            V1
--------------------------------
            SCOTT

--使用本地变量接收函数的返回值

scott@ORCL>set serveroutput on;
            scott@ORCL>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语句中直接调用函数

scott@ORCL>select get_user from dual;
            GET_USER
---------------------
            SCOTT


--使用dbms_output调用函数(此调用作为存储过程的一个参数来进行调用)  

scott@ORCL>set serveroutput on;
            scott@ORCL>exec dbms_output.put_line('Current user: '||get_user);
Currentuser: SCOTT

--带in参数

scott@ORCL> 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.
                                                                     
        scott@ORCL> select sal,raise_sal('SCOTT') from emp where ename='SCOTT';
                                                                     
               SAL RAISE_SAL('SCOTT')
        ---------- ------------------
              3100               3720
                                                                     
        scott@ORCL> 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参数

scott@ORCL> 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参数和函数的返回值。
       调用如下
       scott@ORCL> var job varchar2(20);
       scott@ORCL> var dname varchar2(20);
       scott@ORCL> exec :dname:=get_info('scott',:job);
       PL/SQL procedure successfully completed.
       scott@ORCL> print dname job;
       DNAME
       --------------------------------
       RESEARCH
       JOB
       --------------------------------
       ANALYST


--带有in out 参数

scott@ORCL> 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.
                                                    
        scott@ORCL> var result1 number;
        scott@ORCL> var result2 number;
        scott@ORCL> exec :result2:=10
                                                    
        PL/SQL procedure successfully completed.
                                                    
        scott@ORCL> exec :result1:=comp(16,:result2);
                                                    
        PL/SQL procedure successfully completed.
                                                    
        scott@ORCL> 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:现在文件中编写,然后@执行脚本

[oracle@centos-fuwenchao ~]$ 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;
/
[oracle@centos-fuwenchao ~]$ pwd
/home/oracle
[oracle@centos-fuwenchao ~]$

然后登录到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
/

wKiom1MNlvuBHYPYAAHkPKxu7EE693.jpg

四:查看

查看内容的几种方法:

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=函数名;

五:授权

wKioL1MNne7xm9rYAASnylWO9B4000.jpg

wKiom1MNnhTAnGcMAAN_5lWrc-A666.jpg


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>

六:删除

wKiom1MNnwjTjM_xAAGj8nZHpAE765.jpg

七:注意事项

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



你可能感兴趣的:(oracle,function,注意事项)