Reputation: 13547
This is my stored procedure to search a gallery of images uploaded by users:
ALTER PROCEDURE dbo.sp_SearchGallery
(
@strSearchTerm NVARCHAR(50) = NULL,
@strCategory NVARCHAR(50) = NULL,
@nUserId INT = NULL,
@nSortBy INT = 0,
@nSortDesc BIT = 0,
@nPage INT = 1,
@nPageSize INT = 10
) AS
SET NOCOUNT ON
DECLARE @nSortSwitch INT = 1
IF @nSortDesc = 1 BEGIN
SET @nSortSwitch = -1
END
DECLARE @FirstRec INT = (@nPage - 1) * @nPageSize
DECLARE @LastRec INT = (@nPage * @nPageSize + 1)
; WITH rowQueryResults AS
(
SELECT *, ROW_NUMBER() OVER
(
ORDER BY
CASE @nSortBy
WHEN 0 THEN Date
WHEN 1 THEN Title
WHEN 2 THEN Description
WHEN 3 THEN ID
END
) AS RowNum
FROM dbo.GalleryItems
WHERE ((@strSearchTerm IS NULL OR Title LIKE '%' + @strSearchTerm + '%') OR
(@strSearchTerm IS NULL OR Description LIKE '%' + @strSearchTerm + '%')) AND
(@nUserId IS NULL OR UserId = @nUserId) AND
(@strCategory IS NULL OR Category LIKE '%' + @strCategory + '%') AND
(Accepted=1)
)
SELECT *
FROM rowQueryResults
WHERE RowNum > @FirstRec AND RowNum < @LastRec
ORDER BY RowNum*@nSortSwitch
RETURN
I can set @nSortBy
to 0, which works fine. I can set it to 3, which also works fine, but as soon as I set it to 1 or 2, it crashes with the exception Conversion failed when converting date and/or time from character string.
What I am assuming is it's trying to convert the Title
or Description
to a DateTime
for ordering. The reason why ID
works is because it's an Integer, so that can be safely converted to DateTime (which isn't what I want it to do, obviously)
But, why would it do that? How do I make it so it does a strcmp instead of a time compare for ordering?
Upvotes: 0
Views: 129
Reputation:
There is a simple alternative that does not require conversion:
ORDER BY
CASE WHEN @nSortBy = 0 THEN Date END,
CASE WHEN @nSortBy = 1 THEN Title END,
CASE WHEN @nSortBy = 2 THEN Description END,
CASE WHEN @nSortBy = 3 THEN ID END
This works by a bizarre little trick. Theoretically it is doing ORDER BY over four fields in ranked order. In practice though @nSortBy can only have one value, so only one of the four ranked sorts is actually acted on.
Upvotes: 3
Reputation: 8584
This has to do with data precedence, when you have a case when between different data types SQL converts the lower data types to the highest data type. Try this so your highest data type becomes varchar, so it won't try to convert Title and Description to datetime.
ORDER BY
CASE @nSortBy
WHEN 0 THEN convert(varchar, Date)
WHEN 1 THEN Title
WHEN 2 THEN Description
WHEN 3 THEN convert(varchar, ID)
END
https://msdn.microsoft.com/en-us/library/ms190309.aspx
Upvotes: 3