Creating Stored Procedures in SQL Server: SET NOCOUNT ON and the Basics

Written by

in

Creating Stored Procedures in SQL Server: SET NOCOUNT ON and the Basics

Chapter 2’s function types kept hitting the same wall: none of them can modify data or manage a transaction. A stored procedure is precompiled, reusable, parameterized T-SQL logic that removes that wall entirely — it can perform INSERT/UPDATE/DELETE, manage transactions, use full TRY/CATCH, return multiple result sets, and doesn’t have to return anything at all. This is where the procedural half of T-SQL really begins.

Functions hit a wall. Procedures walk through it.FUNCTIONtries: INSERT/UPDATE/DELETEtries: TRY/CATCH, BEGIN TRAN✗ Msg 443 errorBLOCKEDSTORED PROCEDURE✓ INSERT / UPDATE / DELETE    ✓ BEGIN TRAN … COMMIT / ROLLBACK✓ full TRY/CATCH    ✓ multiple result sets    ✓ return nothing at allcompiled ONCE, plan reusedfirst EXEC compiles the plan;later calls skip straight to running it→ this is where parameter sniffing comes fromALTER PROCEDURE keepsEXECUTE grants. DROP + CREATEsilently wipes them — they don’tcome back automatically. ⚠️

Your First Procedure

CREATE PROCEDURE dbo.usp_GetCustomersByTier
    @tier NVARCHAR(20)
AS
BEGIN
    SET NOCOUNT ON; -- near-universal best practice, see below
    SELECT customer_id, name, email FROM dbo.Customer WHERE tier = @tier;
END;
GO

EXEC dbo.usp_GetCustomersByTier @tier = 'premium';
-- Equivalent, positional call — works but is fragile if parameter order ever changes:
EXEC dbo.usp_GetCustomersByTier 'premium';

The usp_ prefix is a long-standing naming convention (“user stored procedure”) — avoid the older sp_ prefix specifically, since SQL Server always checks the system master database first for anything named sp_*, adding a small but real, entirely avoidable lookup cost to every call.

Why SET NOCOUNT ON Matters More Than It Looks

Without it: every DML statement sends an extra “(N rows affected)” message to the client This measurably slows procedures with loops or many statements

Without SET NOCOUNT ON, this extra network chatter can measurably slow down procedures that loop or run many statements, and can actively interfere with some client libraries and reporting tools that misinterpret the extra “rows affected” messages as additional result sets. Put it at the top of every procedure by default — there is essentially never a reason not to.

A Procedure Precompiles — What That Actually Means

Unlike an ad-hoc query sent fresh from an application each time, a stored procedure’s execution plan is compiled once (on first call, or after certain invalidating events like a statistics update) and reused on subsequent calls. This is a real, measurable performance advantage for frequently-run logic — but it’s also the exact mechanism behind parameter sniffing, a real gotcha covered fully once you reach the Performance Tuning course: the plan compiled for the first parameter value seen gets reused for every subsequent call, even ones with very differently-shaped data.

ALTER, DROP, and Modifying Procedures Safely

-- Change the body without dropping and losing permissions granted on it
ALTER PROCEDURE dbo.usp_GetCustomersByTier
    @tier NVARCHAR(20)
AS
BEGIN
    SET NOCOUNT ON;
    SELECT customer_id, name, email, tier FROM dbo.Customer WHERE tier = @tier; -- added tier column
END;
GO

DROP PROCEDURE IF EXISTS dbo.usp_GetCustomersByTier;
Common mistake: Using DROP + CREATE to “update” a procedure in a production script. If any user or role was explicitly granted EXECUTE permission on that specific procedure, dropping it removes those grants entirely — they don’t automatically come back when you recreate it. ALTER PROCEDURE preserves permissions and is the safer choice for modifying an existing procedure.
Practice tip: Create the example procedure above, then run EXEC sp_helptext 'dbo.usp_GetCustomersByTier' to see SQL Server hand back the exact source text it stored. This is a genuinely useful habit for inspecting procedures on a server where you don’t have the original script handy.

Enjoyed this?

Subscribe to get every new SQL Server lesson as soon as it’s published, and share it with a developer who’d find it useful.

📡 Subscribe via RSS  | 
Share on X  | 
Share on LinkedIn  | 
Share on Facebook

Want the full structured course with quizzes, projects, and 10+ exercises per chapter? Check out SQL Server for Developers & DBAs, coming soon on this site.