函数Function

来源:互联网 发布:算法笔记 pdf 编辑:程序博客网 时间:2024/06/02 22:24
函数Function
创建和使用函数

1.函数基础
函数是另一种存储代码,非常类似于存储过程。两者之间的重要区别是,函数是能够返回单个值的PL/SQL语句块。函数可以接收一个或者多个参数,也可以不接收参数,但是函数的可执行部分必须有一个返回子句。必须在函数的头部声明返回值的数据类型。与过程一样,函数不是独立执行的,他必须在某些上下文中才能使用。可以把函数看做是一个语句段。函数的输出必须赋给一个变量,或者在select语句中使用。

2.函数语法
创建函数语法如下所示
  1. CREATE [OR REPLACE] FUNCTION function_name
  2. (parameter list)
  3. RETURN datatype
  4. IS
  5. BEGIN
  6. <body>
  7. RETURN (return_value);
  8. END;
函数未必使用参数,但是必须有一个return值(在函数头部声明该值的数据类型),必须在所有可能执行路径中都要返回一个值。return语句未必是主执行部分的最后一条语句,而且可能存在多个return语句(应该是每个异常都有一条return语句)。函数可能有IN、OUT或者IN OUT参数,但是一般只会看到IN参数,原因在于使用其他参数并不是一种很好的编程惯例。
  1. create or replace function show_description
  2. (i_course_no course.course_no%type)
  3. return varchar2
  4. as
  5. v_description varchar2(50);
  6. BEGIN
  7. select description into v_description from course
  8. where course_no=i_course_no;
  9. return v_description;
  10. exception
  11. when no_data_found then
  12. return('The Course is not in the database');
  13. WHEN OTHERS THEN
  14. RETURN('Error in running show_description');
  15. END;
  16. /
  1. SQL> col description for a50
  2. SQL> select show_description(145) as description from dual;
  3. DESCRIPTION
  4. --------------------------------------------------
  5. Internet Protocols
  6. declare
  7. v_description varchar2(50);
  8. BEGIN
  9. v_description := show_description(&number);
  10. dbms_output.put_line(v_description);
  11. end;
  12. /
  13. Enter value for number: 350
  14. Java Developer II
  15. PL/SQL procedure successfully completed.

Boolean返回值
  1. CREATE OR REPLACE FUNCTION id_is_good(i_student_id IN NUMBER)
  2.  RETURN BOOLEAN AS
  3.  v_id_cnt NUMBER;
  4. BEGIN
  5.  SELECT COUNT(*)
  6.    INTO v_id_cnt
  7.    FROM student
  8.   WHERE student_id = i_student_id;
  9.  RETURN 1 = v_id_cnt;
  10. EXCEPTION
  11.  WHEN OTHERS THEN
  12.    RETURN FALSE;
  13. END id_is_good;
  14. declare
  15. v_id number := &id;
  16. BEGIN
  17. if id_is_good(v_id)
  18. then
  19. dbms_output.put_line('vaild');
  20. else
  21. dbms_output.put_line('invaild');
  22. end if;
  23. end;
  24. /
  25. BEGIN
  26. if id_is_good(&v_id)
  27. then
  28. dbms_output.put_line('vaild');
  29. else
  30. dbms_output.put_line('invaild');
  31. end if;
  32. end;
  33. /

动手实验
  1. create or replace function new_studnet_id
  2. return student.student_id%type
  3. as
  4. v_student_id student.student_id%type;
  5. BEGIN
  6. select student_id_seq.nextval
  7. into v_student_id from dual;
  8. return v_student_id;
  9. end;
  10. /
  11. select new_studnet_id() from dual;
  12. NEW_STUDNET_ID()
  13. ----------------
  14.             407
  1. create or replace function zipcode_does_not_exist(i_zipcode in zipcode.zip%type)
  2. return BOOLEAN
  3. as
  4. v_count number;
  5. BEGIN
  6. select count(zip) into v_count from zipcode where zip=i_zipcode;
  7. return 0=v_count;
  8. exception
  9. when others then
  10. return false;
  11. end zipcode_does_not_exist;
  12. /
  1. DECLARE
  2.  cons_zip CONSTANT zipcode.zip%TYPE := '&sv_zipcode';
  3.  e_zipcode_is_not_valid EXCEPTION;
  4. BEGIN
  5.  IF zipcode_does_not_exist(cons_zip) THEN
  6.    RAISE e_zipcode_is_not_valid;
  7.  ELSE
  8.    -- An insert of an instructor's record which
  9.    -- makes use of the checked zipcode might go here.
  10.    NULL;
  11.  END IF;
  12. EXCEPTION
  13.  WHEN e_zipcode_is_not_valid THEN
  14.    RAISE_APPLICATION_ERROR(-20003,
  15.                            'Could not find zipcode ' || cons_zip || '.');
  16. END;
  17. /
  18. Enter value for sv_zipcode: 00911
  19. DECLARE
  20. *
  21. ERROR at line 1:
  22. ORA-20003: Could not find zipcode 00911.
  23. ORA-06512: at line 14
  24. -----------------------------------------------------
  25. Enter value for sv_zipcode: 00914
  26. PL/SQL procedure successfully completed.


书上的方法
  1. CREATE OR REPLACE FUNCTION zipcode_does_not_exist(i_zipcode IN zipcode.zip%TYPE)
  2.  RETURN BOOLEAN AS
  3.  v_dummy char(1);
  4. BEGIN
  5.  SELECT NULL INTO v_dummy FROM zipcode WHERE zip = i_zipcode;
  6.  -- Meaning the zipcode does exit
  7.  RETURN FALSE;
  8. EXCEPTION
  9.  WHEN OTHERS THEN
  10.    -- The select statement above will cause an exception
  11.    -- to be raised if the zipcode is not in the database.
  12.    RETURN TRUE;
  13. END zipcode_does_not_exist;

SELECT NULL INTO v_dummy FROM zipcode WHERE zip = i_zipcode;
这句
如果zipcode有值,那么
SQL> select null from zipcode where zip=00914;

N
-

如果zipcode没有值,那么
SQL> select null from zipcode where zip=00911;

no rows selected
返回的是no rows selected,而v_dummy是char(1)类型的


  1. sys_refcursor 函数返回表
  2. create or replace function f_get_emp return sys_refcursor
  3.  is
  4.  v_emp sys_refcursor;
  5. BEGIN
  6.  open v_emp for 'select * from emp';
  7.  return v_emp;
  8. end;
  9. /
  10. SQL> select f_get_emp from dual;
  11. F_GET_EMP
  12. --------------------
  13. CURSOR STATEMENT : 1
  14. CURSOR STATEMENT : 1
  15.     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO DNAME
  16. ---------- ---------- --------- ---------- --------- ---------- ---------- ---------- --------------------------------------------------
  17.      7369 SMITH      CLERK           7902 17-DEC-80        800                    20 RESEARCH
  18.      7499 ALLEN      SALESMAN        7698 20-FEB-81       1600        300         30 noname
  19.      7521 WARD       SALESMAN        7698 22-FEB-81       1250        500         30 noname
  20.      7566 JONES      MANAGER         7839 02-APR-81       2975                    20 RESEARCH
  21.      7654 MARTIN     SALESMAN        7698 28-SEP-81       1250       1400         30 noname
  22.      7698 BLAKE      MANAGER         7839 01-MAY-81       2850                    30 noname
  23.      7782 CLARK      MANAGER         7839 09-JUN-81       2450                    10 ACCOUNTING
  24.      7788 SCOTT      ANALYST         7566 19-APR-87       3000                    20 RESEARCH
  25.      7839 KING       PRESIDENT            17-NOV-81       5000                    10 ACCOUNTING
  26.      7844 TURNER     SALESMAN        7698 08-SEP-81       1500          0         30 noname
  27.      7876 ADAMS      CLERK           7788 23-MAY-87       1100                    20 RESEARCH
  28.      7900 JAMES      CLERK           7698 03-DEC-81        950                    30 noname
  29.      7902 FORD       ANALYST         7566 03-DEC-81       3000                    20 RESEARCH
  30.      7934 MILLER     CLERK           7782 23-JAN-82       1300                    10 ACCOUNTING
  31.      1111 YODA       JEDI                 17-NOV-81       5000                       noname
  32. 15 rows selected.
  33. 函数返回集合
  34. create or replace type varchar2_tt as table of varchar2(1000);
  35.  /
  36. create or replace function f_str2list(in_str in varchar2,
  37.                           in_delimiter in varchar2 default ',')
  38.  return varchar2_tt
  39. /**
  40. ||程序说明:将按指定分隔符分隔的字符串转为嵌套表类型变量返回
  41. ||输入变量:
  42. ||        in_str 字符串,如'a,b,c'
  43. ||        in_delimiter 分隔符,默认是逗号
  44. ||输出变量:
  45. ||        varchar2_tt类型,嵌套表
  46. **/
  47.  as
  48.      v_str     varchar2(32767) default in_str||in_delimiter;
  49.      v_result  varchar2_tt := varchar2_tt();
  50.      i number;
  51. begin
  52.  loop
  53.      exit when v_str is null;
  54.      i := instr(v_str,in_delimiter);
  55.      v_result.extend;
  56.      v_result(v_result.count) := trim(substr(v_str,1,i-1));
  57.      v_str := substr(v_str,i+1);
  58.  end loop;
  59.  return v_result;
  60. end;
  61. /
  62. var str varchar2(100);
  63. exec :str := 'XY,YZ';
  64. select count(*) from emp where ename in (
  65.  select column_value from table(cast(f_str2list(:str) as varchar2_tt))
  66.  );








0 0
原创粉丝点击