How to CREATE FUNCTION (UDFs) in PostgreSQL

Galaxy Glossary

How do I create and use user-defined functions (UDFs) in PostgreSQL?

CREATE FUNCTION lets you define reusable user-defined functions (UDFs) in SQL or PL/pgSQL, extending PostgreSQL with custom logic.

Sign up for the latest in SQL knowledge from the Galaxy Team!
Welcome to the Galaxy, Guardian!
You'll be receiving a confirmation email

Follow us on twitter :)
Oops! Something went wrong while submitting the form.

Description

Table of Contents

What is a PostgreSQL UDF?

A user-defined function (UDF) is an SQL or PL/pgSQL block you store in the database and call like any built-in function. UDFs encapsulate business logic, reduce duplication, and speed up complex calculations.

When should I create a function instead of a view or query?

Create a UDF when you need parameters, conditional logic, loops, or the ability to return scalars, rows, or sets on demand. Views are static SELECTs and cannot accept parameters.

How do I write a simple SQL UDF?

Use CREATE FUNCTION, declare parameters and the return type, then wrap a single SQL statement in $$ delimiters using LANGUAGE sql.

Example: total spent by customer

This SQL UDF returns the lifetime spend of one customer from the Orders table.

CREATE OR REPLACE FUNCTION total_spent(customer_id INT)
RETURNS NUMERIC(12,2) AS $$
SELECT COALESCE(SUM(total_amount),0)
FROM Orders
WHERE customer_id = $1;
$$ LANGUAGE sql IMMUTABLE;

How do I create a PL/pgSQL UDF with control flow?

Choose LANGUAGE plpgsql. You can declare variables, use IF, loops, and raise notices. Useful for multi-step procedures.

Example: restock a product

CREATE OR REPLACE FUNCTION restock_product(p_id INT, add_qty INT)
RETURNS VOID AS $$
BEGIN
UPDATE Products SET stock = stock + add_qty WHERE id = p_id;
INSERT INTO InventoryLog(product_id, qty_added, logged_at)
VALUES (p_id, add_qty, NOW());
END;
$$ LANGUAGE plpgsql;

How do I call a UDF?

Invoke it in any SELECT, INSERT, UPDATE, or as a standalone statement: SELECT total_spent(42);

Best practices for UDFs

Mark functions IMMUTABLE or STABLE when possible for planner optimizations. Add STRICT to auto-return NULL on any NULL parameter. Version functions with OR REPLACE to avoid drop/recreate downtime.

How do I debug or modify a function?

Use CREATE OR REPLACE FUNCTION to update logic. Add RAISE NOTICE statements in PL/pgSQL for logging. pgAdmin and psql -E help inspect compiled source.

Can a function return a table?

Yes, declare RETURNS TABLE(col1 type, ...) or RETURNS SETOF. Query it like a regular table: SELECT * FROM top_customers();

Why How to CREATE FUNCTION (UDFs) in PostgreSQL is important

How to CREATE FUNCTION (UDFs) in PostgreSQL Example Usage


-- Show each customer’s total spend using the UDF defined above
SELECT c.id, c.name, total_spent(c.id) AS lifetime_value
FROM Customers c
ORDER BY lifetime_value DESC;

How to CREATE FUNCTION (UDFs) in PostgreSQL Syntax


CREATE [OR REPLACE] FUNCTION name ( [ [argname] argtype [DEFAULT default_expr] [, ...] ] )
RETURNS rettype
[ LANGUAGE { sql | plpgsql | c | internal | ... } ]
[ IMMUTABLE | STABLE | VOLATILE ]
[ STRICT ]
[ SECURITY { DEFINER | INVOKER } ]
AS $$
    -- SQL or PL/pgSQL body referencing parameters as $1, $2, ...
$$;

-- Ecommerce example: return order items for one order
CREATE FUNCTION list_order_items(p_order INT)
RETURNS TABLE(product_name TEXT, qty INT, line_total NUMERIC) AS $$
  SELECT p.name, oi.quantity, oi.quantity * p.price
  FROM OrderItems oi
  JOIN Products p ON p.id = oi.product_id
  WHERE oi.order_id = $1;
$$ LANGUAGE sql STABLE;

Common Mistakes

Frequently Asked Questions (FAQs)

Can I drop a function without breaking dependencies?

Add IF EXISTS to avoid an error, or use CREATE OR REPLACE so callers stay intact.

What languages can I use besides SQL and PL/pgSQL?

PostgreSQL supports PL/Python, PL/Perl, PL/V8, and more after installing extensions.

Do UDFs hurt performance?

SQL UDFs are inlined by the planner when possible. Marking functions IMMUTABLE and STRICT helps the optimizer. PL/pgSQL incurs minimal overhead for most workloads.

Want to learn about other SQL terms?

Trusted by top engineers on high-velocity teams
Aryeo Logo
Assort Health
Curri
Rubie Logo
Bauhealth Logo
Truvideo Logo
Welcome to the Galaxy, Guardian!
You'll be receiving a confirmation email

Follow us on twitter :)
Oops! Something went wrong while submitting the form.