Documentation Index
Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
Creating a Stored Procedure
MySQL usesDELIMITER to change the statement terminator so the ; inside the procedure body doesn’t end the CREATE PROCEDURE statement early.
CALL:
Parameters
Procedures support three parameter modes:| Mode | Direction | Use case |
|---|---|---|
IN | Caller → procedure | Pass a value in |
OUT | Procedure → caller | Return a value out |
INOUT | Both | Pass in and modify |
OUT parameters:
Local Variables
Declare local variables withDECLARE at the top of the BEGIN...END block, before any other statements:
Control Flow
MySQL procedures support standard control flow constructs:Error Handling
UseDECLARE ... HANDLER to catch errors:
EXIT HANDLER stops the procedure when the condition fires. CONTINUE HANDLER lets the procedure keep running. RESIGNAL re-raises the error to the caller.
Raise your own errors with SIGNAL:
45000 is the SQLSTATE for “unhandled user-defined exception.”
Cursors
Cursors iterate over a result set row by row inside a procedure. Use them when you can’t express the logic as a set operation.NOT FOUND handler sets v_done when the cursor runs out of rows. Always close cursors before the procedure ends.
Stored Procedures vs Functions
| Stored Procedure | Stored Function | |
|---|---|---|
| Return value | Via OUT parameters or result sets | Single return value |
| Call syntax | CALL proc() | SELECT func() — used in expressions |
| Transactions | Can START TRANSACTION, COMMIT, ROLLBACK | Cannot modify transaction state |
| Result sets | Can return multiple result sets | Cannot return result sets |
| Use in SQL | Cannot be used in SELECT expressions | Can be used in SELECT, WHERE, etc. |
When to Use Stored Procedures
Stored procedures make sense when:- Enforcing business rules that must apply regardless of which application or user runs the query
- Reducing round trips for multi-step operations (complex batch jobs, data migrations)
- Granting users access to specific operations without exposing underlying tables (
GRANT EXECUTE ON PROCEDURE)
- The logic changes frequently — deployments require ALTER PROCEDURE or DROP/recreate
- Debugging is needed — no debugger, only SIGNAL-based logging
- Portability matters — stored procedure syntax is MySQL-specific
Frequently Asked Questions
Can a stored procedure return a result set?
Yes. AnySELECT inside a procedure that doesn’t use INTO sends a result set to the caller:
SELECT statements inside one procedure send multiple result sets. Most clients handle this but some ORMs don’t.
How do I see all stored procedures in a database?
Troubleshooting
| Problem | Solution |
|---|---|
ERROR 1064 on CREATE PROCEDURE | Missing DELIMITER change — the ; inside the body ended the statement early; wrap with DELIMITER $$ ... $$; DELIMITER ; |
ERROR 1172: Result consisted of more than one row | A SELECT ... INTO returned multiple rows — add a LIMIT 1 or fix the query to return a single row |
OUT parameter is NULL after CALL | The procedure didn’t assign to it — check all code paths reach the SET or SELECT INTO for that parameter |
ERROR 1193: Unknown system variable | Used SET @var (session variable) where DECLARE v_var (local variable) was needed, or vice versa |
| Procedure runs but returns no data | The result set SELECT is sending data through an extra layer (nested CALL) — bring the SELECT to the outermost procedure |
VillageSQL: Custom Extension Types in Stored Procedures
VillageSQL custom extension types (e.g.,COMPLEX, UUID, TVECTOR) can be used as
stored procedure parameter types and DECLARE variable types. Install the extension
first, then reference its types in your procedure definition:
See also
- MySQL Triggers — triggers call stored procedure logic or inline SQL
- Transactions in MySQL — stored procedures often wrap work in transactions
- Uninstalling Extensions — restrictions when stored procedures use extension types

