创建函数的基本语法如下:

  1. CREATE [OR REPLACE] FUNCTION function_name
  2. [ (argment [ { IN | IN OUT }] Type,
  3. argment [ { IN | OUT | IN OUT } ] Type ]
  4. [ AUTHID DEFINER | CURRENT_USER ]
  5. RETURN return_type
  6. { IS | AS }
  7. delarification_block
  8. BEGIN
  9. FUNCTION_body
  10. EXCEPTION
  11. exception_handler
  12. END;

示例如下:

  1. CREATE OR REPLACE FUNCTION get_salary_by_dept(
  2. v_in_dept_id NUMBER,
  3. v_out_emp_count OUT NUMBER)
  4. RETURN NUMBER
  5. IS
  6. v_sum NUMBER;
  7. BEGIN
  8. SELECT SUM(salary), count(*) INTO v_sum, v_out_emp_count
  9. FROM employees WHERE deptno=v_in_dept_id;
  10. RETURN v_sum;
  11. EXCEPTION
  12. WHEN NO_DATA_FOUND THEN
  13. DBMS_OUTPUT.PUT_LINE('Dept id '||v_in_dept_id||' not found');
  14. WHEN OTHERS THEN
  15. DBMS_OUTPUT.PUT_LINE('ERR: '||SQLCODE||': '||SQLERRM);
  16. END get_salary_by_dept;

参数的传递

向函数中传递参数有三种方法:

  • 第一种是位置表示法,即按照参数定义的顺序逐个传入,语法是:argument_value1[,argument_value2 …]

    示例如下:

  1. obclient> DECLARE
  2. -> V_num NUMBER;
  3. -> V_sum NUMBER;
  4. -> BEGIN
  5. -> V_sum :=get_salary_by_dept(30, v_num);
  6. -> DBMS_OUTPUT.PUT_LINE('Total salary: '||v_sum);
  7. -> DBMS_OUTPUT.PUT_LINE('Total amount of person: '||V_num);
  8. -> END;
  9. -> /
  10. Query OK, 0 rows affected (0.06 sec)
  11. Total salary: 24900
  12. Total amount of person: 6
  • 第二种参数传递的方法是名称表示法,即显式地指定参数名和传入值,不必按照参数定义的顺序,语法是:argument1 => parameter1 [, argument2 => parameter2[, …]]

    示例如下:

  1. obclient> DECLARE
  2. -> V_num NUMBER;
  3. -> V_sum NUMBER;
  4. -> BEGIN
  5. -> V_sum :=get_salary_by_dept(v_out_emp_count => V_num, v_in_dept_id => 30 );
  6. -> DBMS_OUTPUT.PUT_LINE('Total salary: '||v_sum);
  7. -> DBMS_OUTPUT.PUT_LINE('Total amount of person: '||V_num);
  8. -> END;
  9. -> /
  10. Query OK, 0 rows affected (0.06 sec)
  11. Total salary: 24900
  12. Total amount of person: 6
  • 第三种方法为混合表示法,即同时使用位置表示法和名称表示法为函数传递参数。采用这种参数传递方法时,使用位置表示法所传递的参数必须放在名称表示法所传递的参数前面。也就是说,无论函数具有多少个参数,只要其中有一个参数使用名称表示法,其后所有的参数都必须使用名称表示法。

    示例如下:

  1. obclient> DECLARE
  2. -> V_num NUMBER;
  3. -> V_sum NUMBER;
  4. -> BEGIN
  5. -> V_sum :=get_salary_by_dept(30, v_out_emp_count => V_num );
  6. -> DBMS_OUTPUT.PUT_LINE('Total salary: '||v_sum);
  7. -> DBMS_OUTPUT.PUT_LINE('Total amount of person: '||V_num);
  8. -> END;
  9. -> /
  10. Query OK, 0 rows affected (0.06 sec)
  11. Total salary: 24900
  12. Total amount of person: 6

参数默认值

CREATE OR REPLACE FUNCTION语句中声明函数参数时可以使用 DEFAULT 关键字为输入参数指定默认值。示例如下:

  1. CREATE OR REPLACE FUNCTION demo_def_args(
  2. name VARCHAR2,
  3. age INTEGER,
  4. -- 如果gender不传入值,则默认为male
  5. gender VARCHAR2 DEFAULT 'Male')
  6. RETURN VARCHAR2
  7. AS
  8. V_var VARCHAR2(32);
  9. BEGIN
  10. V_var := name||', '||gender||', '||TO_CHAR(age)||' years old.';
  11. RETURN v_var;
  12. END;

具有默认值的函数创建后,在函数调用时,如果没有为具有默认值的参数提供实际参数值,函数将使用该参数的默认值。但当调用者为默认参数提供实际参数时,函数将使用实际参数值。在创建函数时,只能为输入参数设置默认值,而不能为输入/输出参数设置默认值。

  1. obclient> DECLARE
  2. -> Var VARCHAR(32);
  3. -> BEGIN
  4. -> Var := demo_def_args('Roger', 30);
  5. -> DBMS_OUTPUT.PUT_LINE(var);
  6. ->
  7. -> Var := demo_def_args('Allen', age => 40);
  8. -> DBMS_OUTPUT.PUT_LINE(var);
  9. ->
  10. -> Var := demo_def_args('Tracy', gender => 'Female', age => 20);
  11. -> DBMS_OUTPUT.PUT_LINE(var);
  12. -> END;
  13. -> /
  14. Query OK, 0 rows affected (0.05 sec)
  15. Roger, Male, 30 years old.
  16. Allen, Male, 40 years old.
  17. Tracy, Female, 20 years old.