User-defined functions (UDFs) let you package SQL and PL/pgSQL logic into reusable, callable objects.
User-defined functions (UDFs) are database objects that encapsulate SQL or procedural logic and return a value or result set. They behave like Oracle functions but use PostgreSQL’s CREATE FUNCTION
syntax.
Teams migrating from Oracle keep business logic close to data. Re-implementing Oracle UDFs in PostgreSQL preserves familiar call patterns while leveraging open-source tooling.
Use CREATE OR REPLACE FUNCTION
, define parameters, return type, language, and body. LANGUAGE plpgsql
is closest to Oracle PL/SQL.
CREATE OR REPLACE FUNCTION get_customer_total(p_customer_id INT)
RETURNS NUMERIC AS $$
DECLARE
v_total NUMERIC;
BEGIN
SELECT COALESCE(SUM(total_amount),0)
INTO v_total
FROM Orders
WHERE customer_id = p_customer_id;
RETURN v_total;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
Parameters receive input, DECLARE reserves variables, BEGIN…END houses the logic, and RETURN outputs the value.
SELECT get_customer_total(42);
Calls work in SELECT lists, WHERE clauses, or FROM … CROSS JOIN LATERAL blocks.
Mark a UDF IMMUTABLE
when the same input always yields the same output (ideal for sums on static tables). Use STABLE
when reads but no writes occur. Default VOLATILE
if writes or nondeterministic logic exist.
Use CREATE OR REPLACE FUNCTION
to redeploy logic without dropping dependent objects. Ensure signature (name + arg types) stays constant to avoid breakage.
Run DROP FUNCTION IF EXISTS function_name(arg_types) [CASCADE]
. Add CASCADE
only when you’re certain dependent objects can also be removed.
p_
and variables with v_
for readability.SET search_path
at the top to avoid schema confusion.STRICT
to auto-return NULL when any argument is NULL.Yes. Remove the DECLARE
/BEGIN
/END
wrapper and place a single SQL expression after RETURNS
. Mark as IMMUTABLE or STABLE for planner benefits.
By default, yes (SECURITY INVOKER
). Use SECURITY DEFINER
to run with the creator’s rights—useful for controlled access.
Add RAISE NOTICE
statements, or install the plpgsql_check
extension for static analysis and runtime debugging.