Welcome to Dream.In.Code
Getting Help is Easy!

Join 86,399 Programmers. There are 1,467 online right now! Ask your question and get quick answers from Dream.In.Code experts. Join the #1 programming help community on the internet! Registration is fast and FREE... Join Now!

Chat LIVE With a Expert
Powered by LivePerson.com

Register to Make This Box Go Away!

Optional Parameters in MSSQL

 
Reply to this topicStart new topic

> Optional Parameters in MSSQL

PsychoCoder
Group Icon



post 29 Aug, 2007 - 08:14 PM
Post #1


In this tutorial we'll look at using optional parameters in a SQL Stored Procedure. This is a question I get a lot, even at work. People want to know how they can have optional parameters in a stored procedure. Lets look at the scenario:

You have an application for the inventory/sales of your books for your bookstore. In your application you have a search form, there are several items a person can search by, lets they can search by Author, Title, ISDN, or Year. Now you have 2 options;
  • Option 1: You can write 4 different stored procedures, then based on what the user wants to search by call that stored procedure.
  • Option 2: You can write a single stored procedure and pass all the search parameters to your stored procedure and let your stored procedure decide what the user is searching by.

In the interest of maintainability and scalability I would go with Option 2, it is far easier to maintain a single stored procedure than 4 of them. So now we're going to look at how to do this, how to have a single procedure and call it no matter what option the user decides to search by. Before getting to the actual process of optional parameters, I would like to pass along what I feel are rules for good design.

First, when creating a stored procedure most people rush in and start CREATE PROCEDURE...., then run it. Next time they go to edit it, if they don't open it via Query Analyzer or Enterprise Manager, they have to change the CREATE PROCEDURE... to ALTER PROCEDURE... so Ive always found it best to address this right from the start.

In all Microsoft SQL Servers there exists a table called sysobjects, in here are all the objects within that server, the tables, stored procedures, user defined functions, etc. SO what I do is add a header (for the lack of a better term) that checks this table to see if this procedure exists, if it doesnt then I create a shell of the procedure, then right below I alter the same stored procedure.

Theres a catch though, either the words CREATE or ALTER must be the first word in a stored procedure, if its not then SQL will error out, so I do this with Dynamic SQL.

Dynamic SQL is a term used to mean SQL code that is generated programmatically (in part or fully) by your program before it is executed. As a result it is a very flexible and powerful tool. You can use Dynamic SQL to accomplish tasks such as adding where clauses to a search based on what fields are filled out on a form or to create tables with varying names.

This is how my header looks:

CODE

DECLARE @SQL_PROC VARCHAR(4000)
IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = 'YourProcedureName')
            BEGIN
                PRINT 'Creating Procedure YourProcedureName'
                SET @SQL_PROC = 'CREATE PROCEDURE dbo.YourProcedureName    
            @value1 CHAR(100) = NULL,@value2 CHAR(100) = NULL,@value3 CHAR(100) = NULL,@value4 CHAR(100) = NULL
                AS
            SELECT 1
            GO'
            EXEC(@SQL_PROC)
            END
GO


Here is a breakdown of what is happening here
  • I declare a variable named @SQL_PROC, this variable is holding the SQL code I wish to execute
  • I then search sysobjects for a procedure with this same name, if it don't exist then I create a shell version. By a shell version I mean I create the stored procedure with the parameters I want, but it only contains SELECT 1, this gives me a valid stored procedure.
  • I then call EXEC to execute the variable EXEC(@SQL_PROC). When this string is executed, its creating a stored procedure

Notice in the procedure declaration I have @value1 CHAR(100) = NULL , and I do this for all the parameters. This sets their default value to NULL, because all the parameters are optional, we don't know which ones the user is going to pass our procedure.

Now that we have out shell created, right after the last GO statement we then put the rest of our stored procedure, except this time instead of CREATE PROCEDURE we use ALTER PROCEDURE. We can do this because in the first block of code we create this stored procedure if it doesn't already exist. The rest of the stored procedure looks like this:

CODE

ALTER PROCEDURE dbo.YourProcedureName
@value1 CHAR(100) = NULL,
@value2 CHAR(100) = NULL,
@value3 CHAR(100) = NULL,
@value4 CHAR(100) = NULL
AS
SELECT
     column1,
     column2,
     column3,
     column4
FROM
     Table_Name
WHERE
     ((@value1 IS NULL) OR (column1 = @value1))
     AND ((@value2 IS NULL) OR (column2 = @value2))
     AND ((@value3 IS NULL) OR (column3 = @value3))
     AND ((@value4 IS NULL) OR (column4 = @value4))


In this procedure the first 3/4 of the procedure is absolutely normal, SELECT something FROM some table WHERE, its after the WHERE that things get different. As you can see we have 4 different items the user could have passed us, we just don't know which ones. To combat this, we have the where clause structured like so

CODE

((@value1 IS NULL) OR (column1 = @value1))
AND ((@value2 IS NULL) OR (column2 = @value2))
AND ((@value3 IS NULL) OR (column3 = @value3))
AND ((@value4 IS NULL) OR (column4 = @value4))


How does this work you ask? Well it hits the first line, if the parameter @value1 is NULL it does nothing, it skips to the next line. It does this until it reaches a parameter that isn't NULL, once it finds that, it jumps to the other side of the OR statement and executes column* = @value*. The way its structured, if the parameter is empty (NULL) then the first part of the statement is true, meaning that line is executed, until it finds a non-null parameter.

Now lets look at a different scenario, lets say (like above) you have several optional parameters, but the user can enter as many of either parameter they want, or multiples of all if they so choose to, how would you handle this? Well first you would have to use Dynamic SQL for the entire SELECT portion of the procedure. The above approach wouldn't work with multiples of a parameter, i.e: Koontz,King,Rice if they searched by those 3 authors, so how to get that into the procedure?

Transact-SQL has a clause, the IN clause, which allows for a statement like WHERE authors IN ('Koontz','King','Rice'), but with regular SQL you cannot just pass a delimited string into the procedure and expect it to understand what you're doing. But if you do the while thing in Dynamic SQL, when the string is executed it will execute as above, like you did the WHERE authors IN ('Koontz','King','Rice') from above.

So lets take a look at how you would create this stored procedure for this scenario (the header remains the same):

CODE

ALTER PROCEDURE dbo.YourProcedureName
@value1 CHAR(100) = '',
@value2 CHAR(100) = '',
@value3 CHAR(100) = '',
@value4 CHAR(100) = ''
AS
DECLARE @SQL VARCHAR(4000)
SET @SQL = 'SELECT
     column1,
     column2,
     column3,
     column4
FROM
     Table_Name
WHERE
     ((''' + @value1 + ''' = '''') OR (column1 IN(''' +  @value1 + ''')))
     AND ((''' + @value2 + ''' = '''') OR (column2 IN(''' + @value2 + ''')))
     AND ((''' + @value3 + ''' = '''') OR (column3 IN(''' + @value3 + ''')))
     AND ((''' + @value4 + ''' = '''') OR (column4 IN(''' + @value4 + ''')))'

EXEC(@SQL)


In this scenario we change a few things, the default values for the parameters is now '' (empty string) not NULL, then in the WHERE clause we check if the @value* parameter is equal to '' (empty string) instead of checking if its NULL.When the @SQL variable string is executed with the parameters in place, it looks just like you had WHERE authors IN ('Koontz','King','Rice') hard coded in your stored procedure, thus SQL knows what to do with it.

The downside of Dynamic SQL is twofold. First, and most importantly, your stored procedure can not cache the execution plan for this dynamic query. So, for complex queries you will lose the performance boost that you usually gain with stored procedures. The other downside is that you lose the nice formating you are able to achieve with stored procedures that you were not able to do when you were building queries in your application or website.

The advantage is, of course, that you are able to achieve a flexibility in your code that you can not get with standard SQL. I tend to use Dynamic SQL for scenarios such as the one above, it makes it simpler to accomplish what I'm looking for. Well thats how to use optional parameters in your SQL stored procedure. Thanks for reading smile.gif

Happy Coding!


Register to Make This Ad Go Away!

Louisda16th
Group Icon



post 30 Aug, 2007 - 07:07 AM
Post #2
First tutorial in databases. Nice work PsychoCoder smile.gif!
P.S. Anything about the advanced sheet for VB.NET?

This post has been edited by Louisda16th: 30 Aug, 2007 - 08:00 AM

PsychoCoder
Group Icon



post 30 Aug, 2007 - 08:03 AM
Post #3
Ill do some work on it tonight, been busy as hell. Had a LONG weekend (worked like 50+ hours between Thursday - Sunday moving our company to their new building)

Louisda16th
Group Icon



post 30 Aug, 2007 - 08:10 AM
Post #4
QUOTE(PsychoCoder @ 30 Aug, 2007 - 08:33 PM) *

Sunday moving our company to their new building

You had to work on a Sunday??? blink.gif

PsychoCoder
Group Icon



post 30 Aug, 2007 - 01:28 PM
Post #5
Oh yeah, Thursday = 14 hours (or so), Friday = 16 hours (or so), Saturday = 14 hours, Sunday = almost 8 hours

Louisda16th
Group Icon



post 13 Oct, 2007 - 02:11 AM
Post #6
mmm. Stored procedures in MSSQL look different from what I'd done in Oracle. Is MSSQL different from PLSQL?

PsychoCoder
Group Icon



post 13 Oct, 2007 - 06:27 AM
Post #7
PL-SQL and Transact-SQL are similar, but yes they are different


Fast ReplyReply to this topicStart new topic
2 User(s) are reading this topic (2 Guests and 0 Anonymous Users)
0 Members:

 

Lo-Fi Version Time is now: 5/17/08 06:16AM

Live Help!

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

Bye Bye Ads

Free DIC T-Shirt

T-Shirt Example

Related Sites

Monthly Drawing

Thumb Drive

Partners

Top Contributors

Top 10 Kudos This Month