sql 241 lines · 2 tabs

Stored procedures and functions in PostgreSQL

Maria Garcia Feb 2026
2 tabs
-- Simple function
CREATE OR REPLACE FUNCTION get_full_name(
  first_name VARCHAR,
  last_name VARCHAR
)
RETURNS VARCHAR AS $$
BEGIN
  RETURN first_name || ' ' || last_name;
END;
$$ LANGUAGE plpgsql;

-- Usage
SELECT get_full_name('John', 'Doe');

-- Function with complex logic
CREATE OR REPLACE FUNCTION calculate_discount(
  customer_id INT,
  order_total DECIMAL
)
RETURNS DECIMAL AS $$
DECLARE
  customer_tier VARCHAR;
  discount_pct DECIMAL := 0;
BEGIN
  -- Get customer tier
  SELECT tier INTO customer_tier
  FROM customers
  WHERE id = customer_id;

  -- Calculate discount based on tier and total
  discount_pct := CASE customer_tier
    WHEN 'gold' THEN 0.15
    WHEN 'silver' THEN 0.10
    WHEN 'bronze' THEN 0.05
    ELSE 0
  END;

  -- Additional discount for large orders
  IF order_total > 1000 THEN
    discount_pct := discount_pct + 0.05;
  END IF;

  RETURN order_total * discount_pct;
END;
$$ LANGUAGE plpgsql;

-- Table-returning function
CREATE OR REPLACE FUNCTION get_user_orders(user_id_param INT)
RETURNS TABLE (
  order_id INT,
  order_date TIMESTAMP,
  total DECIMAL,
  status VARCHAR
) AS $$
BEGIN
  RETURN QUERY
  SELECT id, created_at, amount, status::VARCHAR
  FROM orders
  WHERE user_id = user_id_param
  ORDER BY created_at DESC;
END;
$$ LANGUAGE plpgsql;

-- Usage in SELECT
SELECT * FROM get_user_orders(123);

-- Function with loops
CREATE OR REPLACE FUNCTION generate_monthly_report(
  year_param INT
)
RETURNS TABLE (
  month INT,
  total_sales DECIMAL,
  total_orders INT
) AS $$
DECLARE
  month_num INT;
BEGIN
  FOR month_num IN 1..12 LOOP
    RETURN QUERY
    SELECT
      month_num,
      COALESCE(SUM(amount), 0),
      COUNT(*)::INT
    FROM orders
    WHERE EXTRACT(YEAR FROM created_at) = year_param
      AND EXTRACT(MONTH FROM created_at) = month_num;
  END LOOP;
END;
$$ LANGUAGE plpgsql;

-- Exception handling
CREATE OR REPLACE FUNCTION safe_divide(
  numerator DECIMAL,
  denominator DECIMAL
)
RETURNS DECIMAL AS $$
BEGIN
  RETURN numerator / denominator;
EXCEPTION
  WHEN division_by_zero THEN
    RETURN NULL;
  WHEN OTHERS THEN
    RAISE NOTICE 'Error: %', SQLERRM;
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;
2 files · sql Explain with highlit

Stored procedures encapsulate business logic in database. Functions return values; procedures don't (PostgreSQL 11+). I use functions for reusable calculations, data transformations. PL/pgSQL provides procedural language—variables, loops, conditionals. Functions can be called in SELECT statements. Procedures support transaction control—COMMIT/ROLLBACK. Triggers execute functions automatically on data changes. User-defined functions enable complex aggregations. Understanding when to use database logic versus application code is key. Functions reduce network overhead for complex operations. Security-definer functions run with creator privileges. Stored procedures improve performance for data-intensive operations but reduce portability.


Related snips

sql
-- EXPLAIN ANALYZE (actual execution statistics)
EXPLAIN ANALYZE
SELECT u.username, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at >= '2024-01-01'

Advanced query optimization techniques

database optimization query-performance
by Maria Garcia 2 tabs
sql
-- Publisher: Send notification
NOTIFY new_order, 'Order #12345 created';

-- Subscriber: Listen for notifications
LISTEN new_order;

PostgreSQL LISTEN/NOTIFY for pub-sub messaging

postgresql listen-notify pub-sub
by Maria Garcia 2 tabs
sql
-- Logical backup with pg_dump
-- Single database
-- pg_dump -h localhost -U postgres -d mydb -F c -f mydb_backup.dump

-- All databases
-- pg_dumpall -h localhost -U postgres -f all_databases.sql

Database backup and recovery strategies

database backup recovery
by Maria Garcia 2 tabs
sql
-- Prepared statements basics
-- PostgreSQL syntax
PREPARE get_user (INT) AS
SELECT id, username, email
FROM users
WHERE id = $1;

Query plan caching and prepared statements

postgresql performance query-plans
by Maria Garcia 2 tabs
sql
-- Install PostGIS extension
CREATE EXTENSION IF NOT EXISTS postgis;

-- Create table with geometry column
CREATE TABLE locations (
  id SERIAL PRIMARY KEY,

Geospatial data with PostGIS

postgresql postgis geospatial
by Maria Garcia 2 tabs
sql
-- Pattern 1: Shared schema with tenant_id column

CREATE TABLE tenants (
  id SERIAL PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  slug VARCHAR(50) UNIQUE NOT NULL,

Multi-tenancy database patterns and strategies

multi-tenancy saas row-level-security
by Maria Garcia 2 tabs

Share this code

Here's the card — post it anywhere.

Stored procedures and functions in PostgreSQL — share card
Link copied