Reputation: 661
I am trying to create a stored procedure that will allow for the caller to specify if they would like to order by a column. The parameter is supposed to be optional. I am using SQL Server Express
@sortBy VARHCAR(255) = ''
BEGIN
SELECT * FROM Document
ORDER BY
CASE @sortBy
WHEN 'documentId' THEN documentId
WHEN 'documentName' THEN documentName
WHEN 'dateCreated' THEN dateCreated
WHEN 'dateLastAccessed' THEN dateLastAccessed
ELSE documentName
END;
END
I can create the procedure, but when I execute it I get the following message
Conversion failed when converting date and/or time from character string.
dateCreated and dateLastAccessed are of type DATE, but I can't tell if they are culprit. Am I accidentally telling the DB to convert a date/time with this procedure? This is the first time that I have worked with optional parameters for stored procedures, so I may not be doing that right. Any help is appreciated
Thanks
Upvotes: 1
Views: 2162
Reputation: 82524
As Tim and Sean wrote in their comment, a case expression can only return a single data type.
When each of the options contains a different data type, SQL Server tries to implicitly convert all the data types to the higher precedence data type (see the list here).
You can overcome this by using a slightly more cumbersome query:
SELECT *
FROM Document
ORDER BY
CASE WHEN @sortBy = 'documentId' THEN documentId END,
CASE WHEN @sortBy = 'documentName' THEN documentName END,
CASE WHEN @sortBy = 'dateCreated' THEN dateCreated END,
CASE WHEN @sortBy = 'dateLastAccessed' THEN dateLastAccessed END;
Note that without specifying the else
part, the case
expression will return null
- so that shouldn't effect the overall order of the records.
Upvotes: 6
Reputation: 2245
First, dynamic ordering doesn't work for mixed data types. That is, if you have fields of different data types that you want to order by - such as varchars and date. You need to use CONVERT to convert the mismatched data type to the same data type as the others. Or you can use dynamic sql. Maybe it's easier :))
SELECT * FROM Document
ORDER BY
CASE @sortBy
WHEN 'documentId' THEN documentId
WHEN 'documentName' THEN documentName
WHEN 'dateCreated' THEN CONVERT(DATE, dateCreated)
WHEN 'dateLastAccessed' THEN CONVERT(DATE, dateLastAccessed)
ELSE documentName
END;
Upvotes: 2