Create or Alter a SQL Server Stored Procedure Safely

Use CREATE OR ALTER PROCEDURE instead of a separate conditional drop. The statement creates the procedure when it is missing and changes the existing definition when it is present. Keep it as the first statement in its batch.

Last updated: October 8, 2026.

CREATE OR ALTER PROCEDURE dbo.ExpensesByMonth
    @Year smallint,
    @Month tinyint
AS
BEGIN
    SET NOCOUNT ON;

    SELECT ExpenseDate, Amount, Description
    FROM dbo.Expenses
    WHERE ExpenseDate >= DATEFROMPARTS(@Year, @Month, 1)
      AND ExpenseDate < DATEADD(month, 1, DATEFROMPARTS(@Year, @Month, 1))
    ORDER BY ExpenseDate;
END;
GO

EXEC dbo.ExpensesByMonth @Year = 2026, @Month = 10;

GO ends the batch in SSMS and sqlcmd; it is not a Transact-SQL statement sent to the database engine. The procedure definition therefore begins a clean batch, while the test execution runs in the next one.

Why IF and CREATE can produce confusing errors

CREATE PROCEDURE has special batch rules. Placing IF before it means the procedure statement is no longer first in the batch. A following unconditional CREATE can then report that the object already exists, even though the intended DROP branch did not compile or run as expected.

Microsoft documents both the syntax and the batch restriction in CREATE PROCEDURE (Transact-SQL). OR ALTER is available in SQL Server 2016 SP1 and later, Azure SQL Database, and current related platforms.

Deploy procedures without dropping permissions

Changing a procedure preserves the object rather than deleting and recreating it. That matters when permissions, dependencies, or deployment tooling refer to the existing object. Use a schema-qualified name, keep deployment scripts in source control, and run them with an account that has the required schema permissions.

If an application executes the script directly, do not send the word GO through the database driver. Split batches in the deployment tool or send the procedure definition as one command. Microsoft explains the client-side separator in its GO command reference. For related patterns, see stored procedure output parameters, SQL Server parameter placeholders, and grouping procedure results.

Related Web Cheat Sheet guides

Sergey Kornilov

Sergey Kornilov