I am trying to create a stored procedure with multiple order by fields. The order by field and direction is passed through the stored procedure as arguments.
CREATE PROCEDURE GetFilteredLogs
@FromDate datetime2,
@ToDate datetime2,
@SearchText nvarchar(100) = NULL,
@LogTypeIds Ids READONLY,
@AreaIds Ids READONLY,
@SubTypeIds Ids READONLY,
@UnitIds Ids READONLY,
@SortField nvarchar(25) = NULL,
@SortDirection nvarchar(5) = NULL
AS
SELECT *
FROM LogsView
WHERE
(CreatedDate >= @FromDate AND CreatedDate <= @ToDate)
AND ((([Text] LIKE '%' + @SearchText + '%' OR @SearchText IS NULL)
AND (LogTypeId IN (SELECT Id FROM @LogTypeIds) OR NOT EXISTS (SELECT 1 FROM @LogTypeIds))
AND (OperationAreaId IN (SELECT Id FROM @AreaIds) OR NOT EXISTS (SELECT 1 FROM @AreaIds))
AND (Subtype IN (SELECT Id FROM @SubTypeIds) OR NOT EXISTS (SELECT 1 FROM @SubTypeIds))
AND (Unit IN (SELECT Id FROM @UnitIds) OR NOT EXISTS (SELECT 1 FROM @UnitIds))) OR IsCritical = 1)
ORDER BY
CASE @SortField
WHEN 'LogTypeId' THEN CreatedDate DESC(should be passed as argument), LogTypeId DESC
ELSE CreatedDate DESC
END
GO
The order by section in the above stored procedure is not in correct syntax. How can I do it and is it possible the way I have tried above?
This is a classic Kitchen Sink Query.
Use dynamic SQL to build up a series of conditions and ordering clauses. Then use sp_executesql
to execute it, passing in all necessary parameters.
CREATE OR ALTER PROCEDURE GetFilteredLogs
@FromDate datetime2,
@ToDate datetime2,
@SearchText nvarchar(100) = NULL,
@LogTypeIds Ids READONLY,
@AreaIds Ids READONLY,
@SubTypeIds Ids READONLY,
@UnitIds Ids READONLY,
@SortField nvarchar(25) = NULL,
@SortDirection nvarchar(5) = NULL
AS
DECLARE @sql nvarchar(max) = '
SELECT *
FROM LogsView
WHERE (CreatedDate >= @FromDate AND CreatedDate <= @ToDate)
AND (
IsCritical = 1
OR (1=1';
IF @SearchText IS NOT NULL
SET @sql += '
AND [Text] LIKE ''%'' + @SearchText + ''%''';
IF EXISTS (SELECT 1 FROM @LogTypeIds)
SET @sql += '
AND LogTypeId IN (SELECT Id FROM @LogTypeIds)';
IF EXISTS (SELECT 1 FROM @AreaIds)
SET @sql += '
AND OperationAreaId IN (SELECT Id FROM @AreaIds)';
IF EXISTS (SELECT 1 FROM @SubTypeIds)
SET @sql += '
AND Subtype IN (SELECT Id FROM @SubTypeIds)';
IF EXISTS (SELECT 1 FROM @UnitIds)
SET @sql += '
AND Unit IN (SELECT Id FROM @UnitIds)';
SET @sql += '
)
)
ORDER BY
CreatedDate' + IIF(@SortDirection = 'DESC', ' DESC', '');
IF @SortField = 'LogTypeId'
SET @sql += ',
LogTypeId' + IIF(@SortDirection = 'DESC', ' DESC', '');
PRINT @sql; -- your friend
EXEC sp_executesql @sql,
N'@FromDate datetime2,
@ToDate datetime2,
@SearchText nvarchar(100),
@LogTypeIds Ids READONLY,
@AreaIds Ids READONLY,
@SubTypeIds Ids READONLY,
@UnitIds Ids READONLY',
@FromDate = @FromDate,
@ToDate = @ToDate,
@SearchText = @SearchText,
@LogTypeIds = @LogTypeIds,
@AreaIds = @AreaIds,
@SubTypeIds = @SubTypeIds,
@UnitIds = @UnitIds
;
It's not clear from your description, but it seems you always want to sort by CreatedDate
, and possibly also by LogTypeId
depending on the parameter.