我有以下存储过程,可以在TemplateName,CreatedOn和UploadedBy上升序和降序排序。运行时的以下SP不会对记录进行排序。如果我用列名替换2,3,4,我收到错误消息“将nvarchar值'测试模板'转换为数据类型int时转换失败。”。请建议如何实现排序
CREATE PROCEDURE [dbo].[usp_SEL_GetRenderingTemplate]
(
@facilityID INT,
@sortOrder VARCHAR(5),
@sortExpression VARCHAR(100),
@errorCode INT OUTPUT
)
AS
BEGIN
SET NOCOUNT ON ;
BEGIN TRY
SET @sortOrder = CASE @sortOrder
WHEN 'Ascending' THEN 'ASC'
WHEN 'Descending' THEN 'DESC'
ELSE 'ASC'
END
SELECT TemplateID,
TemplateName,
CreatedOn,
( [user].LastName + ' ' + [user].FirstName ) AS UploadedBy
FROM Templates
INNER JOIN [user] ON [user].UserID = Templates.CreatedBy
WHERE facilityid = @facilityID
ORDER BY CASE WHEN @sortExpression = 'TemplateName'
AND @sortOrder = 'ASC' THEN 2
WHEN @sortExpression = 'CreatedOn'
AND @sortOrder = 'ASC' THEN 3
WHEN @sortExpression = 'UploadedBy'
AND @sortOrder = 'ASC' THEN 4
END ASC,
CASE WHEN @sortExpression = 'TemplateName'
AND @sortOrder = 'DESC' THEN 2
WHEN @sortExpression = 'CreatedOn'
AND @sortOrder = 'DESC' THEN 3
WHEN @sortExpression = 'UploadedBy'
AND @sortOrder = 'DESC' THEN 4
END DESC
SET @errorCode = 0
END TRY
BEGIN CATCH
SET @errorCode = -1
DECLARE @errorMsg AS VARCHAR(MAX)
DECLARE @utcDate AS DATETIME
SET @errorMsg = CAST(ERROR_MESSAGE() AS VARCHAR(MAX))
SET @utcDate = CAST(GETUTCDATE() AS DATETIME)
EXEC usp_INS_LogException 'usp_SEL_GetFacilityWorkTypeList',
@errorMsg, @utcDate
END CATCH
END
答案 0 :(得分:1)
动态排序必须具有相同的数据类型。下面是一个我用来命令三种不同数据类型的例子 - 整数,日期(升序和降序)和字符串。这可能不适合您的情况,但至少您可以看到一些用于转换为通用数据类型的技术。
...
ORDER BY
Case Parent.RankTypeID
When 0 Then dbo.Documents.Rank
When 1 Then Convert(int, dbo.Documents.DateStart, 112)
When 2 Then (1 - Convert(int, dbo.Documents.DateStart, 112))
When 3 Then Cast(dbo.Documents.Title as sql_variant)
End
注意:强>
112是YYYYMMDD的日期格式 - 对订购有用。
答案 1 :(得分:0)
我们在其中一个产品中执行类似的动态订购。 与您的代码唯一真正不同的是,首先,我们不使用实时联接。 我们创建一个临时表,因此我们可以执行分页,然后应用订单。 我们还使用int来进行排序,减少了字符串比较的开销。
它确实使您的SQL更长一些,但这种方法对于查询优化器来说肯定更快。此外,更重要的是,我不认为你可以在Switch块中混合使用类型进行排序,因此要遵循原始代码,你必须同时转换所有数据,这会使对象失败:(< / p>
所以你有
DECLARE @temp TABLE(ID int identity(1,1), TemplateID int, TemplateName nvarchar(100), CreatedOn datetime, UploadedBy nvarchar(100))
INSERT INTO @temp(TemplateID, TemplateName, CreatedOn, UploadedBy)
SELECT TemplateID,
TemplateName,
CreatedOn,
( [user].LastName + ' ' + [user].FirstName ) AS UploadedBy
FROM Templates
INNER JOIN [user] ON [user].UserID = Templates.CreatedBy
WHERE facilityid = @facilityID
然后:
IF @SortOrder = 1 --'ASC'
BEGIN
IF @sort = 2
Select *
From @Temp
Order by TemplateName ASC
ELSE IF @sort = 3
Select *
From @Temp
Order By CreatedBy ASC
-- and so on...
END
ELSE -- descending
BEGIN
-- Ad. Inf.
END
Delete
From @Temp
WHERE ID < @pageStart or ID > @pageStart + @pageSize
答案 2 :(得分:0)
运行时的以下SP不会 排序记录。如果我用2,3,4替换 列名,
您不应该使用列名替换ORDER BY子句中的2,3,4。当您调用该过程时,只需将要排序的列作为第3个参数进行排序。
EXEC [dbo].[usp_SEL_GetRenderingTemplate] 1,'Ascending','CreatedOn',@vErrorCode
然后,CASE会将查询评估为
...ORDER BY 3 DESC
通过SELECT子句中的第3列(即CreatedOn)对查询进行排序
答案 3 :(得分:0)
问题是在CASE子句中,返回值必须具有相同的数据类型。
您可以使用多个CASE语句http://www.extremeexperts.com/sql/articles/CASEinORDER.aspx
解决此问题或者将所有内容都转换为相同的数据类型。