By WebNest Studio Engineering Team
Database and SQL Tutorial
Stored Procedures and Functions Concepts
A stored procedure (or function) is a named block of SQL and procedural logic that is saved inside the database itself and can be executed by calling its name, rather than sending the full SQL text from the application every time. Most major databases support them, though the exact syntax varies — PostgreSQL uses PL/pgSQL, SQL Server uses T-SQL, and Oracle uses PL/SQL.
Stored procedures and functions bring logic closer to the data, which can reduce network round trips and let the database enforce rules consistently no matter which application or tool is writing to it.
Why it matters
Stored procedures and functions put logic inside the database, where it runs next to the data. Banks and large enterprises use them heavily, so you are likely to read and maintain them. They can cut network round trips and centralise rules, at the cost of logic that is harder to version and test than application code.
CREATE PROCEDURE and CREATE FUNCTION
CREATE PROCEDURE defines a named routine that performs an action — it can run multiple statements, including transactions, and is invoked with CALL procedure_name(...). CREATE FUNCTION defines a named routine that computes and returns a value, and can typically be used directly inside a SQL expression, such as in a SELECT list or WHERE clause. The key practical difference: a function must return a value and is used as part of a larger query, while a procedure is invoked on its own and does not have to return anything.
When Server-Side Logic Makes Sense
Stored procedures are a good fit when: the same multi-step logic needs to run identically from several different applications or tools, and you want to guarantee consistency rather than reimplementing it in each one; the operation involves many round trips between the application and database that could instead happen in one call, reducing network latency; or you need to enforce a business rule at the database level so it applies no matter what connects to the database. They are usually a poor fit when the logic changes frequently (stored procedures are harder to version-control and deploy than application code), when the team's tooling and expertise are centered on the application layer, or when portability across different database vendors matters, since procedural SQL dialects are not standardized.
- Good fit: shared logic across multiple applications, reducing round trips, enforcing rules centrally.
- Poor fit: rapidly changing logic, teams without strong database tooling, needing to stay portable across database vendors.
Examples
A stored procedure that performs a transfer as a single callable unit
CREATE PROCEDURE transfer_funds(
sender_id INT,
receiver_id INT,
amount DECIMAL
)
LANGUAGE plpgsql
AS $$
BEGIN
UPDATE accounts SET balance = balance - amount WHERE account_id = sender_id;
UPDATE accounts SET balance = balance + amount WHERE account_id = receiver_id;
END;
$$;
CALL transfer_funds(1, 2, 100.00);
CREATE PROCEDURE
CALL
(Both balance updates run as one server-side unit; any application that calls
transfer_funds gets the same guaranteed behavior without duplicating the logic.)
A function that computes and returns a value for use inside a query
CREATE FUNCTION order_total(order_id INT)
RETURNS DECIMAL
LANGUAGE plpgsql
AS $$
DECLARE
total DECIMAL;
BEGIN
SELECT SUM(price * quantity) INTO total
FROM order_items
WHERE order_items.order_id = order_id;
RETURN total;
END;
$$;
SELECT id, order_total(id) AS total FROM orders WHERE id = 501;
id: 501 | total: 149.99
Common Mistakes
- Putting all business logic into stored procedures by default, making it hard to unit test, version, and review compared to logic kept in application code.
- Confusing a function (must return a value, usable inside SELECT/WHERE) with a procedure (invoked with CALL, not usable inline in an expression).
- Writing stored procedures full of vendor-specific syntax and then expecting easy migration to a different database engine later.
- Forgetting that stored procedure changes need their own review and deployment process, just like application code — they are not exempt from change management.
Exercise
This exercise uses PostgreSQL's function syntax, so it cannot run in the playground. Write a function order_total that takes an order id and returns the total value of that order, calculated as the sum of quantity multiplied by unit price over its rows in order_items. Then call it for order 1.
Expected result: the SELECT returns one row with the total for order 1.
-- order_items(order_id, quantity, unit_price)
-- TODO: create the function order_total(p_order_id) returning a numeric total
-- TODO: call it for order 1
Show hints
- A simple function can be written in SQL:
CREATE FUNCTION name(args) RETURNS type LANGUAGE sql AS $$ ... $$. - A function is called inside a query:
SELECT order_total(1).
Show solution
-- order_items(order_id, quantity, unit_price)
CREATE FUNCTION order_total(p_order_id INTEGER)
RETURNS NUMERIC
LANGUAGE sql
AS $$
SELECT COALESCE(SUM(quantity * unit_price), 0)
FROM order_items
WHERE order_id = p_order_id;
$$;
SELECT order_total(1);
Quick quiz
1. What is the main difference between a function and a procedure?
- A. There is none
- B. A function returns a value and can be used in a query; a procedure is run with CALL and need not return one
- C. A procedure must return a value
- D. A function cannot take parameters
Show answer
B. In PostgreSQL a procedure can also commit or roll back inside its body, which a function cannot.
2. What is a benefit of a stored procedure?
- A. It makes the database smaller
- B. It removes the need for indexes
- C. It replaces transactions
- D. Several statements run on the server in one call, saving network round trips
Show answer
D. It can also be the only way an account is allowed to change certain data.
3. What is a drawback of putting business logic in stored procedures?
- A. The logic is harder to version, test and move to another database
- B. They cannot use SQL
- C. They are always slower
- D. They cannot take parameters
Show answer
A. Procedure languages differ between database products.
Interview questions
What is a stored procedure and why would you use one?
Show answer
A stored procedure is a named routine saved in the database that runs a sequence of statements, with parameters and control flow. Reasons to use one: several statements execute in a single call, which reduces network traffic; rules implemented there apply to every application that uses the database; and access can be granted to the procedure without granting it on the tables. The costs are that the logic is separate from the application code and is specific to one database product.
What is a trigger?
Show answer
A trigger is a routine the database runs automatically when a specified event occurs on a table: before or after an insert, update or delete. Triggers are used for audit logs, for keeping derived values in step, and for enforcing rules too complex for a constraint. Because they run invisibly, they can make behaviour hard to follow and slow down writes, so they are used sparingly.
Key Points to Remember
- A stored procedure is a named, saved routine invoked with CALL; a stored function returns a value and can be used inside SQL expressions.
- Server-side logic reduces network round trips and centralizes rules so every application gets consistent behavior.
- Procedural SQL dialects (PL/pgSQL, T-SQL, PL/SQL) are vendor-specific and not portable across database engines.
- Reserve stored procedures for stable, shared, or performance-critical logic rather than rapidly changing business rules.
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs your SQL on SQLite in your browser. Standard SQL works; a few features that exist only in PostgreSQL or MySQL do not. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
These examples need a project environment on your computer, so they can be copied but not run here. Codelab runs Python, FastAPI backends with SQLite, plain Java 17 and HTML/CSS/JavaScript.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering