我有一个查询,我必须使用case语句进行过滤。似乎每个案件的条件都在执行:
declare @filterValue varchar(50)='test'
declare @filterCol varchar(50)='DayOfWeekAbr'
select * from datetable where 1=1 and (
case when @filterCol='' then DayOfWeekAbr
when @filterCol='' then [WeekOfYear]
end = @filterValue
OR case when ISNULL(@filterCol,'')='' then 1
end =1)
获取错误:
Msg 245,Level 16,State 1,Line 5 转换varchar值时转换失败' test'数据类型int。
现在错误是因为列WeekOfYear是int。但我怀疑的是案件情况是否与执行案件的情况不符?并解决方法如何做到。
当在下面的查询中实现时,得到相同的错误告诉我我错在哪里:
SELECT
[threat_feed].[Id]
, [threat_feed].[Name]
, [threat_feed].[Url]
, [threat_feed].[RefreshRate]
, [threat_feed].[ConfidenceLevel]
, [threat_feed].[Severity]
, [threat_feed].[Type]
, [threat_feed].[Source]
, [threat_feed].[Description]
, [threat_feed].[Visibility]
, [threat_feed].[Integration]
, [threat_feed].[IntegrationOptions]
, [threat_feed].[CreatedBy]
, [threat_feed].[CreatedOn]
, [threat_feed].[ModifiedBy]
, [threat_feed].[ModifiedOn]
, [threat_feed].[IsDeleted]
, COUNT(*) OVER () AS [TOTALROWS]
FROM [dbo].[ThreatFeed] [threat_feed]
WHERE [threat_feed].[IsDeleted] IN (0, @IncludeDeleted) AND (
(@filterCol = 'Name' and [threat_feed].[Name] = @filterValue) or
(@filterCol = 'Source' and [threat_feed].[Source] = @filterValue) or
(@filterCol = 'URL' and [threat_feed].[Url] = @filterValue) or
(@filterCol = 'RefreshRate' and [threat_feed].[RefreshRate] = @filterValue) or
(@filterCol = 'ConfidenceLevel' and [threat_feed].[ConfidenceLevel] = @filterValue) or
(@filterCol = 'Severity' and [threat_feed].[Severity] = @filterValue) or
(@filterCol = 'Visibility' and [threat_feed].[Visibility] = @filterValue) or
(isnull(@filterCol,'')='')
)
此处置信度,服务器和可见性不是varchar
答案 0 :(得分:2)
问题可能是case
中的where
表达式。说实话,没有case
就可以更简单地完成。我想这就是你想要的:
where ( (@filterCol = 'DayOfWeekAbr' and DayOfWeekAbr = @filterValue) or
(@filterCol = 'WeekOfYear' and WeekOfYear = @filterValue) or
(@filterCol is null)
)
编辑:
哦,这很有意思。 SQL(通常)不保证对布尔表达式进行惰性求值。因此,可能会评估or
的两侧。 。 。当过滤器值是一个字符串时,这可能会导致问题,但该列需要一个数字。
这是一个解决方案:
where (case when @filterCol = 'Name' and [threat_feed].[Name] = @filterValue) then 1
when @filterCol = 'Source' and [threat_feed].[Source] = @filterValue)
then 1
. . .
end) = 1
然后,确保所有字符串列都在日期列之前。 case
中的条款保证按顺序搜索。
在SQL Server 2012+中,另一种可能性是将try_convert()
用于非字符串列。是的,如果RefreshRate
是一个整数:
where . . .
(@filterCol = 'URL' and [threat_feed].[Url] = @filterValue) or
(@filterCol = 'RefreshRate' and [threat_feed].[RefreshRate] = try_convert(int, @filterValue) ) or