Functions
A function is a named PL/SQL block that returns a value. Unlike procedures, functions use the RETURN keyword to send a result back to the caller. Functions can be called from SQL statements — a capability procedures do not have.
Creating a Function
CREATE OR REPLACE FUNCTION function_name(
param1 IN datatype,
param2 IN datatype DEFAULT default_value
)
RETURN return_datatype IS
-- local variable declarations
BEGIN
-- logic
RETURN some_value;
EXCEPTION
WHEN ... THEN
RETURN fallback_value; -- or RAISE
END function_name;
/
Simple Scalar Function
CREATE OR REPLACE FUNCTION full_name(
p_first IN employees.first_name%TYPE,
p_last IN employees.last_name%TYPE
)
RETURN VARCHAR2 IS
BEGIN
RETURN TRIM(p_first) || ' ' || TRIM(p_last);
END full_name;
/
-- Call from PL/SQL
DECLARE
v_name VARCHAR2(100);
BEGIN
v_name := full_name(' Steven ', 'King ');
DBMS_OUTPUT.PUT_LINE(v_name); -- Steven King
END;
/
-- Call directly from SQL
SELECT full_name(first_name, last_name) AS name, salary
FROM employees
WHERE department_id = 90;
Function with Business Logic
CREATE OR REPLACE FUNCTION get_annual_comp(
p_salary IN employees.salary%TYPE,
p_comm_pct IN employees.commission_pct%TYPE DEFAULT 0
)
RETURN NUMBER IS
v_commission NUMBER;
BEGIN
v_commission := NVL(p_salary * NVL(p_comm_pct, 0), 0);
RETURN ROUND((p_salary + v_commission) * 12, 2);
END get_annual_comp;
/
-- Use in SQL
SELECT first_name,
salary,
commission_pct,
get_annual_comp(salary, commission_pct) AS annual_comp
FROM employees
WHERE department_id = 80
ORDER BY annual_comp DESC
FETCH FIRST 5 ROWS ONLY;
| first_name | salary | commission_pct | annual_comp |
|---|---|---|---|
| John | 14000 | .40 | 234720.00 |
| Karen | 13500 | .30 | 193752.00 |
| Alberto | 12000 | .30 | 170928.00 |
RETURN in Exception Handler
Functions must always return a value or raise an exception on every code path:
CREATE OR REPLACE FUNCTION get_dept_budget(
p_dept_id IN departments.department_id%TYPE
)
RETURN NUMBER IS
v_budget NUMBER;
BEGIN
SELECT SUM(salary) * 12
INTO v_budget
FROM employees
WHERE department_id = p_dept_id;
RETURN NVL(v_budget, 0);
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 0; -- department has no employees
WHEN OTHERS THEN
-- Log error and re-raise
DBMS_OUTPUT.PUT_LINE('Error in get_dept_budget: ' || SQLERRM);
RAISE;
-- No RETURN needed here — RAISE exits the function
END get_dept_budget;
/
If a function reaches
END without executing a RETURN, Oracle raises FUNCTION_RETURNED_NULL (ORA-06503) or returns NULL depending on context. Always ensure every code path returns a value or raises an exception.
Purity Rules — Calling Functions from SQL
Functions called from SQL must obey purity constraints to avoid side effects:
| Constraint | Meaning |
|---|---|
DETERMINISTIC |
Same inputs always produce same output — enables function-based indexes and result caching |
RESULT_CACHE |
Oracle caches the result in the SGA; reuses for repeated calls with same args |
| Reads DB state | Allowed in queries |
| Writes DB state (DML) | Forbidden in SELECT; raises ORA-14551 |
| Calls non-pure function | Inherits its impurity |
-- DETERMINISTIC: safe for function-based indexes, query caching
CREATE OR REPLACE FUNCTION format_salary(p_salary IN NUMBER)
RETURN VARCHAR2 DETERMINISTIC IS
BEGIN
RETURN '$' || TO_CHAR(p_salary, 'FM999,999.00');
END format_salary;
/
-- Create a function-based index using a deterministic function
CREATE INDEX idx_salary_fmt ON employees (format_salary(salary));
-- RESULT_CACHE: result cached in SGA — very fast for expensive lookups
CREATE OR REPLACE FUNCTION dept_headcount(p_dept_id IN NUMBER)
RETURN NUMBER RESULT_CACHE IS
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count
FROM employees WHERE department_id = p_dept_id;
RETURN v_count;
END dept_headcount;
/
SELECT department_id, dept_headcount(department_id) AS headcount
FROM departments;
Function vs Procedure
| Feature | Function | Procedure |
|---|---|---|
| Returns a value | Yes (RETURN) |
Via OUT parameters only |
| Called from SQL | Yes (with purity rules) | No |
| Called from PL/SQL | Yes | Yes |
| Can perform DML | Yes (in PL/SQL) | Yes |
| DML in SQL context | No (ORA-14551) | — |
Calling a Function from Another PL/SQL Block
DECLARE
v_budget NUMBER;
v_headcount NUMBER;
BEGIN
-- Call in assignment
v_budget := get_dept_budget(80);
v_headcount := dept_headcount(80);
DBMS_OUTPUT.PUT_LINE(
'Sales: ' || v_headcount || ' employees, $' ||
TO_CHAR(v_budget, 'FM999,999,999') || ' total annual salary'
);
-- Call in IF condition
IF get_dept_budget(90) > 500000 THEN
DBMS_OUTPUT.PUT_LINE('Executive budget exceeds threshold.');
END IF;
END;
/
Table Function (Returning a Collection)
Functions can return collections usable in SQL's TABLE() operator:
CREATE TYPE t_emp_name_list AS TABLE OF VARCHAR2(100);
/
CREATE OR REPLACE FUNCTION dept_employee_names(p_dept_id IN NUMBER)
RETURN t_emp_name_list IS
v_names t_emp_name_list := t_emp_name_list();
BEGIN
SELECT first_name || ' ' || last_name
BULK COLLECT INTO v_names
FROM employees
WHERE department_id = p_dept_id
ORDER BY last_name;
RETURN v_names;
END dept_employee_names;
/
-- Use in SQL with TABLE()
SELECT COLUMN_VALUE AS employee_name
FROM TABLE(dept_employee_names(60));
When to use a function vs a procedure?
Use a function when:
- You need to return a single value.
- You want to call the logic from SQL queries.
- The logic computes something without modifying state (ideal for
DETERMINISTIC). - The result can benefit from
RESULT_CACHE.
Use a procedure when:
- You need to return multiple values via
OUTparameters. - The subprogram performs DML that must be called, not embedded in a SELECT.
- You are managing transactions (
COMMIT,ROLLBACK) inside the subprogram. - You have side effects (logging, sending emails) that should not appear in SQL.
Summary
- Functions return a value via
RETURN— every code path must return or raise. - Call functions from SQL, PL/SQL assignments, conditions, and expressions.
DETERMINISTICenables result caching and function-based indexes.RESULT_CACHEstores results in the SGA — ideal for expensive, frequently called lookups.- Functions in SQL must not perform DML (ORA-14551) — move DML to procedures.
- Table functions return collections usable with
TABLE()in SQL queries.