A Stored Procedure (often called SP or Stored Proc) is a set of T-SQL instructions saved in the database under a name.
They are the foundation of database development. Think of them as the functions or methods in languages like Java or Python, but living inside SQL Server.
Why use a stored procedure?
- Code Reuse: Write the logic once, execute it a thousand times.
- Security: You can grant a user permission to execute the procedure without giving them permission to see the underlying tables.
- Performance: SQL Server compiles and optimizes the execution plan the first time it runs and reuses it afterwards.
- Reduce Network Traffic: Instead of sending 500 lines of code from your application to the server, you only send
EXEC MyProcedure.
Creating a Procedure: CREATE PROCEDURE
To create a procedure, we use the CREATE PROCEDURE statement (or its abbreviation CREATE PROC), followed by the name, parameters (if any), and the code body.
CREATE PROCEDURE ProcedureName
AS
BEGIN
-- Your T-SQL code goes here
SELECT * FROM MyTable;
END
- ProcedureName: The unique name that identifies the stored procedure.
- AS: Indicates the start of the code block containing the SQL instructions.
- BEGIN…END: Delimits the body of the procedure.
For example, let’s create a procedure that returns the list of all active products.
CREATE PROCEDURE usp_GetActiveProducts
AS
BEGIN
SET NOCOUNT ON; -- Good practice (we'll see why below)
SELECT ProductID, Name, Price
FROM Products
WHERE Active = 1;
END
Never name your procedures starting with sp_ (e.g., sp_GetCustomers). That prefix is reserved for System Procedures from Microsoft.
If you use sp_, SQL Server will first look in the system master database, which hurts performance and can cause conflicts. Use prefixes like usp_ (User Stored Procedure) or proc_.
Executing a Procedure: EXEC
Once created, the procedure lives in the database. To invoke it, we use the EXEC keyword.
In our example we would do,
EXEC usp_GetActiveProducts;
Procedures with Parameters
A procedure that always does exactly the same thing is not very useful. The real power comes when we pass it data to work with dynamically.
Parameters are defined after the procedure name, starting with @ and their data type.
For example, if we want to filter by category,
CREATE PROCEDURE usp_ProductsByCategory
@CategoryID INT -- Input parameter
AS
BEGIN
SET NOCOUNT ON;
SELECT Name, Price, Stock
FROM Products
WHERE CategoryID = @CategoryID; -- We use the parameter in the WHERE clause
END
To execute it, we must pass the value:
-- Option 1: By position
EXEC usp_ProductsByCategory 5;
-- Option 2: By name (Safer and more readable)
EXEC usp_ProductsByCategory @CategoryID = 5;
Modifying and Deleting: ALTER and DROP
Of course, we can modify or delete a procedure.
- To delete it:
DROP PROCEDURE usp_Name; - To modify it:
ALTER PROCEDURE usp_Name ...
Logically, if you delete or modify a procedure, you will affect all queries that use it.
You will have to analyze the effects before modifying it.
