Creating A Simple Stored Procedure
Creating A Simple Stored Procedure
(CREATE PROCEDURE)
Overview
As mentioned in the tutorial overview a stored procedure is nothing more than stored SQL
code that you would like to use over and over again. In this example we will look at
creating a simple stored procedure.
Explanation
Before you create a stored procedure you need to know what your end result is, whether
you are selecting data, inserting data, etc..
In this simple example we will just select all data from the Person.Address table that is
stored in the AdventureWorks database.
So the simple T-SQL code would be as follows which will return all rows from this table.
SELECT * FROM AdventureWorks.Person.Address
To create a stored procedure to do this the code would look like this:
CREATE PROCEDURE uspGetAddress
AS
SELECT * FROM AdventureWorks.Person.Address
GO
To call the procedure to return the contents from the table specified, the code would be:
EXEC uspGetAddress
--or just simply
uspGetAddress
When creating a stored procedure you can either use CREATE PROCEDURE or CREATE
PROC. After the stored procedure name you need to use the keyword "AS" and then the
rest is just the regular SQL code that you would normally execute.
On thing to note is that you cannot use the keyword "GO" in the stored procedure. Once
the SQL Server compiler sees "GO" it assumes it is the end of the batch.
Also, you can not change database context within the stored procedure such as using "USE
dbName" the reason for this is because this would be a separate batch and a stored
procedure is a collection of only one batch of statements
Explanation
Just like you have the ability to use parameters with your SQL code you can also setup your
stored procedures to except one or more parameter values.
One Parameter
In this example we will query the Person.Address table from the AdventureWorks database,
but instead of getting back all records we will limit it to just a particular city. This example
assumes there will be an exact match on the City value that is passed.
CREATE PROCEDURE uspGetAddress @City nvarchar(30)
AS
SELECT *
FROM AdventureWorks.Person.Address
WHERE City = @City
GO
To call this stored procedure we would execute it as follows:
EXEC uspGetAddress @City = 'New York'
We can also do the same thing, but allow the users to give us a starting point to search the
data. Here we can change the "=" to a LIKE and use the "%" wildcard.
CREATE PROCEDURE uspGetAddress @City nvarchar(30)
AS
SELECT *
FROM AdventureWorks.Person.Address
WHERE City LIKE @City + '%'
GO
In both of the proceeding examples it assumes that a parameter value will always be
passed. If you try to execute the procedure without passing a parameter value you will get
an error message such as the following:
Multiple Parameters
Setting up multiple parameters is very easy to do. You just need to list each parameter and
the data type separated by a comma as shown below.
CREATE PROCEDURE uspGetAddress @City nvarchar(30) = NULL, @AddressLine1
nvarchar(60) = NULL
AS
SELECT *
FROM AdventureWorks.Person.Address
WHERE City = ISNULL(@City,City)
AND AddressLine1 LIKE '%' + ISNULL(@AddressLine1 ,AddressLine1) + '%'
GO
Overview
In a previous topic we discussed how to pass parameters into a stored procedure, but
another option is to pass parameter values back out from a stored procedure. One option
for this may be that you call another stored procedure that does not return any data, but
returns parameter values to be used by the calling stored procedure.
Explanation
Setting up output paramters for a stored procedure is basically the same as setting up input
parameters, the only difference is that you use the OUTPUT clause after the parameter
name to specify that it should return a value. The output clause can be specified by either
using the keyword "OUTPUT" or just "OUT".
Simple Output
CREATE PROCEDURE uspGetAddressCount @City nvarchar(30), @AddressCount int
OUTPUT
AS
SELECT @AddressCount = count(*)
FROM AdventureWorks.Person.Address
WHERE City = @City
Or it can be done this way:
CREATE PROCEDURE uspGetAddressCount @City nvarchar(30), @AddressCount int
OUT
AS
SELECT @AddressCount = count(*)
FROM AdventureWorks.Person.Address
Overview
A great new option that was added in SQL Server 2005 was the ability to use the Try..Catch
paradigm that exists in other development languages. Doing error handling in SQL Server
has not always been the easiest thing, so this option definitely makes it much easier to code
for and handle errors.
Explanation
If you are not familiar with the Try...Catch paradigm it is basically two blocks of code with
your stored procedures that lets you execute some code, this is the Try section and if there
are errors they are handled in the Catch section.
Let's take a look at an example of how this can be done. As you can see we are using a
basic SELECT statement that is contained within the TRY section, but for some reason if this
fails it will run the code in the CATCH section and return the error information.
CREATE PROCEDURE uspTryCatchTest
AS
BEGIN TRY
SELECT 1/0
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH
Anything
/*
-this procedure gets a list of addresses based
on the city value that is passed
-this procedure is used by the HR system
*/
CREATE PROCEDURE uspGetAddress @City nvarchar(30)
AS
SELECT *
FROM AdventureWorks.Person.Address
WHERE City = @City
GO
Combining Line and Block Comments
You can also use both types of comments within a stored procedure.
/*
-this procedure gets a list of addresses based
on the city value that is passed
-this procedure is used by the HR system
*/
CREATE PROCEDURE uspGetAddress @City nvarchar(30)
AS
SELECT *
FROM AdventureWorks.Person.Address
WHERE City = @City -- the @City parameter value will narrow the search
criteria
GO
Overview
One good thing to do for all of your SQL Server objects is to come up with a naming
convention to use. There are not any hard and fast rules, so this is really just a guideline on
what should be done.
Explanation
SQL Server uses object names and schema names to find a particular object that it needs to
work with. This could be a table, stored procedure, function ,etc...
It is a good practice to come up with a standard naming convention for you objects
including stored procedures.
Standardize on a Prefix
It is a good idea to come up with a standard prefix to use for your stored procedures. As
mentioned above do not use "sp_", so here are some other options.
usp_
sp
usp
etc...
To be honest it does not really matter what you use. SQL Server will figure out that it is a
stored procedure, but it is helpful to differentiate the objects, so it is easier to manage.
So a few examples could be:
spInsertPerson
uspInsertPerson
usp_InsertPerson
InsertPerson
Again this is totally up to you, but some standard is better than none.
Insert
Delete
Update
Select
Get
Validate
etc...
uspInsertPerson
uspGetPerson
spValidatePerson
SelectPerson
etc...
Another option is to put the object name first and the action second, this way all of the
stored procedures for an object will be together.
uspPersonInsert
uspPersonDelete
uspPersonGet
etc...
Again, this does not really matter what action words that you use, but this will be helpful to
classify the behavior characteristics.
Schema Names
A
schema is the a collection of objects, so basically just a
container. This is useful if you want to keep all utility like objects together or have
Another thing to consider is the schema that you will use when saving the objects.
HR.uspGetPerson
HR.uspInsertPerson
UTIL.uspGet
UTIL.uspGetLastBackupDate
etc...
Schema
Prefix
Action
Object
Take the time to think through what makes the most sense and try to stick to your
conventions.
from a query window, this may be useful, but most end users that run stored procedures
through an application would never see these messages.
You can still use @@ROWCOUNT to get the number of rows impacted by a SQL statement,
so turning SET NOCOUNT ON will not change that behavior.
Not using SET NOCOUNT ON
Here is an example without using SET NOCOUNT ON:
-- not using SET NOCOUNT ON
CREATE PROCEDURE uspGetAddress @City nvarchar(30)
AS
SELECT *
FROM AdventureWorks.Person.Address
WHERE City = @City
GO
The messages that are returned would be similar to this:
(23 row(s) affected)
Using SET NOCOUNT ON
This example uses the SET NOCOUNT ON as shown below. It is a good practice to put this
at the beginning of the stored procedure.
-- using SET NOCOUNT ON
CREATE PROCEDURE uspGetAddress @City nvarchar(30)
AS
SET NOCOUNT ON
SELECT *
FROM AdventureWorks.Person.Address
WHERE City = @City
GO
The messages that are returned would be similar to this:
Command(s) completed successfully.
Using SET NOCOUNT ON and @@ROWCOUNT
This example uses SET NOCOUNT ON, but will still return the number of rows impacted by
the previous statement. This just shows that this still works.
-- not using SET NOCOUNT ON
CREATE PROCEDURE uspGetAddress @City nvarchar(30)
AS
SET NOCOUNT ON
SELECT *
FROM AdventureWorks.Person.Address
WHERE City = @City
PRINT @@ROWCOUNT
GO
The messages that are returned would be similar to this:
23
SET NOCOUNT OFF
If you wanted to turn this behavior off, you would just use the command "SET NOCOUNT
OFF".
To drop multiple stored procedures with one command you specify each procedure
separated by a comma as shown below.
DROP PROCEDURE uspGetAddress, uspInsertAddress, uspDeleteAddress
GO
-- or
DROP PROC uspGetAddress, uspInsertAddress, uspDeleteAddress
GO
AS
SELECT *
FROM AdventureWorks.Person.Address
WHERE City LIKE @City + '%'
GO
Now the next time that the stored procedure is called by an end user it will use this new
logic.