Most developers interact with databases through individual SQL statements sent from application code. But databases also support server-side programming: named blocks of SQL and procedural logic that live inside the database. Stored procedures, functions, triggers, and views are the main tools. Each solves a different problem, and each has real trade-offs.

What Are Stored Procedures?#

A stored procedure is a named, reusable block of SQL (and procedural logic) stored in the database itself. You call it by name, passing parameters.

sql

The entire logic executes on the database server. One network round-trip instead of four.

Benefits#

BenefitExplanation
Reduced network round-tripsLogic runs server-side; app sends one call
Reusable logicMultiple apps / services call the same procedure
SecurityGrant EXECUTE on procedure, not direct table access
EncapsulationBusiness rules enforced at the data layer
Partial performance gainParsed and compiled once, not every call

Security Model#

sql

Stored Procedure Syntax: PostgreSQL (PL/pgSQL)#

PostgreSQL uses PL/pgSQL, a procedural extension of SQL with variables, loops, conditionals, and exception handling.

Basic Structure#

sql

Example: Process an Order#

sql

IN / OUT / INOUT Parameters#

sql

Stored Procedures: MySQL Syntax#

MySQL stored procedures use a slightly different syntax.

sql

Functions vs Procedures#

The key difference: functions return a value and can be used in SQL expressions. Procedures are called with CALL and are used for side effects.

FeatureProcedureFunction
Return valueOUT parameters onlySingle value or table
Use in SELECTNoYes
Called withCALLSELECT, WHERE, etc.
Transaction controlYes (can COMMIT/ROLLBACK inside)No (in PostgreSQL)
Side effectsYesIdeally no (but possible)

Create Function Example: Compute Loyalty Points#

sql

Table-Returning Functions#

sql

Triggers#

Triggers automatically execute a function before or after a data-modification event (INSERT, UPDATE, DELETE) on a table.

Event: INSERT INTO orders VALUES (...)BEFORE trigger← can modify or reject rowWrite to tableAFTER trigger← insert audit log, update aggregates

Audit Log Trigger#

A common use case: record every change to sensitive data.

sql

BEFORE Trigger: Validate and Transform Data#

sql

Trigger Special Variables#

text

Views#

A view is a saved query with a name. You query it like a table, but it always runs the underlying query at execution time.

Creating Views#

sql

Updatable vs Read-Only Views#

A view is updatable if it maps one-to-one to a single base table (no aggregates, no DISTINCT, no GROUP BY, no joins).

sql

For non-updatable views that you still want to support DML, use INSTEAD OF triggers:

sql

Materialised Views#

A regular view runs its query every time you query it. A materialised view stores the query result on disk like a table. It's fast to read but must be refreshed to reflect new data.

sql

Refresh Strategies#

sql

Regular View vs Materialised View#

Regular ViewMaterialised View
StorageNo (query only)Yes (data on disk)
Query speedRuns query every timeInstant (pre-computed)
Data freshnessAlways currentStale until refreshed
DML supportSometimesNo
Use caseSimplify complex joinsPre-aggregate expensive queries

When NOT to Use Stored Procedures#

Stored procedures are not always the right answer. Know when to avoid them.

Tight Coupling to Database#

Stored procedures embed business logic inside the database. If you switch from PostgreSQL to MySQL, every procedure must be rewritten. The application and database become tightly coupled.

text

Hard to Test and Debug#

Python

Version Control Challenges#

SQL files don't integrate naturally into git workflows. Migrations are one-directional. Rolling back a stored procedure change while keeping data intact is non-trivial.

The Rule of Thumb#

Use stored procedures forAvoid stored procedures for
Audit triggersCore application business logic
Complex multi-step transactions that must be atomicSimple CRUD operations
Security-sensitive operations (prevent SQL injection)Logic that changes frequently
Database-level data validationLogic that needs unit testing
Performance-critical operations with complex SQLMicroservice boundaries

Putting It All Together#

A realistic example using multiple features together:

sql

Summary#

  • Stored procedures: server-side named SQL blocks. Use for multi-step transactions, audit logic, and security isolation. Avoid for core application business logic.
  • Functions: like procedures but return values. Can be used in SELECT, WHERE, and JOIN. Use for reusable calculations.
  • Triggers: automatically run code before/after data modifications. Use for audit logging and data validation. Keep triggers simple; complex trigger logic is hard to debug.
  • Views: named saved queries. Simplify complex joins. Updatable if they map to a single table without aggregation.
  • Materialised views: pre-computed query results stored on disk. Fast reads, must be refreshed. Use for expensive aggregations queried frequently.
  • When to avoid procedures: when you need testability, portability, or frequent business logic changes. Keep that logic in the application layer.