Passing the ORDER BY to a stored procedure

I use stored procedures for a lot of the data access I do within the applications I develop.  Overall I like using stored procedures for data access, however, at times it makes “things” more difficult. 

One of the “things“ that it makes more difficult is using optional parameters.  In dynamic SQL we can handle optional parameters easily, simple don't append parameters that aren't needed.  With stored procedures it isn't quite as straight-forward.  My Optional Parameters in SQL Server Search queries post provides a solution.

Another task that is more difficult when using stored procedures is sorting.  In many instances we want to be able to pass in the field that the records should be sorted on.  Often times this is accomplished by using nested IF/ELSE statements.  Although nested IFs do address the problem it also introduces a lot of duplication which we all know is bad.  Fortunately there is a better way.  Rather then introducing nested IF/ELSE statements to control the ORDER BY of your query use a CASE statement in the ORDER BY of your query.

CREATE  PROCEDURE ap_OrderSearch
(
@SortBy varchar(50)
)
AS
select * from orders
ORDER BY
CASE
 WHEN @SortBy = 'customerid' THEN CustomerID
 WHEN @SortBy = 'shipname' THEN ShipName
 WHEN @SortBy = 'shipaddress' THEN ShipAddress
END,
CASE
 WHEN @SortBy = 'orderdate' THEN OrderDate
 WHEN @SortBy = 'shippeddate' THEN ShippedDate
END,
CASE
 WHEN @SortBy = 'orderid' THEN OrderID
 WHEN @SortBy = 'employeeid' THEN EmployeeID
END


The above query returns records from the Orders table in the Northwind database.  It accepts one parameter which is used to specify the field to sort the results by.  The fields are grouped into 3 separate CASE statements by their data type to avoid conversion errors during the execution of the query.

# Passing the ORDER BY to a stored procedure

Tuesday, April 20, 2004 5:32 AM by Dewayne and Shadow his Webdog    
Source: Steve Eichert Passing the ORDER BY to a stored procedure I use stored procedures for a lot of the data access I do within the applications I develop. Overall I like using stored procedures for data access, however, at

# re: Passing the ORDER BY to a stored procedure

Wednesday, April 21, 2004 5:08 AM by Jeff Gonzalez    
Steve, I was wondering why you wouldn't use sp_executesql for an instance like this?

Here is how we accomplished the same sort of thing...

Create proc dbo.ap_OrderSearch_Correct
(@SortBy varchar(50) = Null)
As
Declare @sql nvarchar(4000)
Set @sql = 'select * from orders'
If @SortBy Is Not Null
Begin
Set @sql = @sql + ' Order By ' + @SortBy
End

Execute sp_executesql @sql, N'@SortBy varchar(50)', @SortBy

ap_OrderSearch_Correct 'CustomerId'


btw, your blog is required reading where I work.

# re: Passing the ORDER BY to a stored procedure

Wednesday, April 21, 2004 5:09 AM by Jeff Gonzalez    
ROFL, I don't mean to insinuate MY code is more correct than yours with my procedure name.

# re: Passing the ORDER BY to a stored procedure

Wednesday, April 21, 2004 6:30 AM by Steve    
Jeff,
The reason we don't usually use the method you mentioned is that it requires the user to have SELECT permissions on the table. Most of the time we lock down our apps so that the user only has Execute permissions on the procs. When the SELECT permissins aren't locked down your approach works just as well. Heck and you've declared mine less correct then your's so I guess your's is the way to go ;-)

# re: Passing the ORDER BY to a stored procedure

Wednesday, April 21, 2004 6:31 AM by Steve    
"btw, your blog is required reading where I work."

WOOHOOO!

:)

# re: Passing the ORDER BY to a stored procedure

Wednesday, April 21, 2004 7:09 AM by Jeff Gonzalez    
Steve, fair enough.

I hate to be the source of a possible "religion" war, but if you protect yourself from sql injection (I am not aware of a way to do sql injection using stored procs or parameterized queries) I don't think locking down table permissions is worth the maintanence pain.

A coworker of mine says....

Shannon says:
so, once again you have to give eichert credit for being a good guy

You seem to deal with "confrontation" remarkably well.

# re: Passing the ORDER BY to a stored procedure

Wednesday, April 21, 2004 7:43 AM by Steve    
Jeff, Yeah you might be right regarding it being more painful then its worth. My thoughts are that if somehow our web box got compromised and the user that we're using to connect was found at least the "attacker" would be limited in what he could do. If our get proc for selecting credit card information never returns the full credit card number (just as a really simple example), and the attacker can only run our procs then we don't expose the credit card numbers of a bunch of customers. If on the other hand the user has select permissions the attacker can get at everything.

It really isn't all that painful if you manage it correctly. We have a stored proc that takes a user account and rips through the objects in the database and sets the proper permissions. So we say adm_SetPermission 'our_user' and it loops over all the procs in the database and grants execute permission and all the tables and revokes any SELECT, INSERT, DELETE perms.

Thanks for the "good guy" remark Shannon, you are clearly a very intelligent and wise individual! My experience is that usually people aren't out to "get you" with what they're confronting you on, just challenging your viewpoints, which isn't all that bad. If no one ever challenged me on my viewpoints how would I ever learn anything :)

Cheers!

# re: Passing the ORDER BY to a stored procedure

Wednesday, April 21, 2004 1:22 PM by Jeff Gonzalez    
I can see your point, I guess it is true what they say, you can have peace or freedom.

# re: Passing the ORDER BY to a stored procedure

Thursday, May 13, 2004 9:07 PM by Joe    
I often want to specify more than one field for sorting, and date fields I often want to sort them descending.

How can I do this using your CASE structure. The following is ideally what I want but it doesn't work:

ORDER BY
CASE
WHEN @SortBy = 0 THEN releaseDate DESC, title ASC
WHEN @SortBy = 1 THEN releaseDate ASC, title ASC
WHEN @SortBy = 2 THEN title ASC, releaseDate DESC
END


# re: Passing the ORDER BY to a stored procedure

Thursday, January 06, 2005 2:02 AM by Steve    
Use multiple case statements. One case for each set of columns of a given "type". In your example you could actually just do something like:

ORDER BY
CASE
WHEN @SortBy = 0 THEN releaseDate DESC
WHEN @SortBy = 1 THEN releaseDate ASC
END, title ASC


# re: Passing the ORDER BY to a stored procedure

Thursday, January 06, 2005 2:08 AM by Joe    
Thanks Steve. I tried this but it doesn't seem to compile. I'm getting the following error:

"Incorrect syntax near the keyword 'DESC'."

Any suggestions?

# re: Passing the ORDER BY to a stored procedure

Thursday, January 06, 2005 2:40 AM by Steve    
My bad, you can't have the DESC following the column name. In order to do what you want you'd have to do something like:

ORDER BY
CASE
WHEN @SortBy = 0 THEN releaseDate
END DESC,
CASE
WHEN @SortBy = 1 THEN releaseDate
END ASC, title ASC

Not working directly in sql since I don't have your DB but something along those lines should give you what you want.

# re: Passing the ORDER BY to a stored procedure

Thursday, January 06, 2005 4:08 AM by Joe    
Got it. Thanks a lot.

# re: Passing the ORDER BY to a stored procedure

Monday, January 10, 2005 12:18 AM by Trotski    
How about taking this one further... I'm working on a query that also needs to set the ASC and DESC dynamically. How would I incorporate this into the CASE statement you have set above?

# re: Passing the ORDER BY to a stored procedure

Monday, January 10, 2005 12:23 AM by Trotski    
How about taking this one further... I'm working on a query that also needs to set the ASC and DESC dynamically. How would I incorporate this into the CASE statement you have set above?

# re: Passing the ORDER BY to a stored procedure

Friday, February 17, 2006 12:45 AM by John Shore    
Great solution. I spent much time looking for a solution for this particular problem on the internet, and it was at this site that I found my solution. Thanks.

# re: Passing the ORDER BY to a stored procedure

Friday, February 17, 2006 12:45 AM by John Shore    
Great solution. I spent much time looking for a solution for this particular problem on the internet, and it was at this site that I found my solution. Thanks.

# re: Passing the ORDER BY to a stored procedure

Tuesday, May 09, 2006 3:37 AM by Moeen Ahmad    
u can pass dynamic sort direction too. just add one case statement for each sort direction. For Example

declare @OrederByColumn varchar(50)
declare @OrederByDirection varchar(50)
set @OrederByColumn = 'RuleDescription DESC'
--set @OrederByDirection = 'ASC'
select * from dma_businessrules
order by
CASE
WHEN @OrederByColumn = 'RuleDescription ASC' THEN RuleDescription
END ASC,
CASE
WHEN @OrederByColumn = 'RuleDescription DESC' THEN RuleDescription
END DESC

# re: Passing the ORDER BY to a stored procedure

Friday, December 08, 2006 10:11 AM by Corey    
i'm trying to do this:
DECLARE @iSort int
DECLARE @iSortDir varchar(5)
BEGIN
IF @iSort < 0
Set @iSortDir = 'DESC'
ELSE
Set @iSortDir = 'ASC'
END
BEGIN
Select
ContactID,
FirstName,
LastName,
Company,
JobTitle,
Phone,
Cell,
EmailID,
EmailOptOut
From
Contacts
Where
SiteID = '1'
and Deleted = '0'
and PrivateContact = '0'
Order by
CASE
WHEN @iSort = '1' or @iSort = '-1' THEN LastName
WHEN @iSort = '2' or @iSort = '-2' THEN Company
WHEN @iSort = '3' or @iSort = '-3' THEN JobTitle
WHEN @iSort = '4' or @iSort = '-4' THEN Phone
WHEN @iSort = '5' or @iSort = '-5' THEN EmailID
END @iSortDir

# Syntax error converting the varchar value 'Sydney Opera House' to a column of data type int.

Friday, March 09, 2007 1:18 AM by Manivannan    
CREATE PROCEDURE Project
@Index varchar(255)
AS
select * from dbproject
order by
case
when @Index='1' then PrjName
when @Index='2' then PrjTypeKey
when @Index='3' then Client
end
GO

i pass 1 it returns subject error
while for other two it works correctly
Prjname is varchar while other two are integers


# re: Passing the ORDER BY to a stored procedure

Friday, March 09, 2007 8:31 AM by Steve    
You need to group the fields by data type as the example above shows.

Post a Comment

 
 
Prove you're not a spammer: 
5 + 5 =