【问题标题】:Getting error while writing else case statement in sql在sql中编写else case语句时出错
【发布时间】:2016-10-05 07:39:02
【问题描述】:

我有一个查询,我必须使用 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)

得到错误:

消息 245,第 16 级,状态 1,第 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,'')='')
        )

这里的confidencelevel、serverity和visibility不是varchar

【问题讨论】:

  • CASE 语句中的逻辑没有意义。
  • [WeekOfYear] 实际上是一个整数吗?您似乎正在将字符串与 int 进行比较 - 可能与 CASE 本身无关
  • 哦,对了,无论如何你都知道——如果你知道它是什么,为什么还要发布错误?为什么不修复你的错误,看看它是怎么回事?
  • 安德鲁 我试过了,但找不到解决办法

标签: sql-server tsql case


【解决方案1】:

问题可能是where 中的case 表达式。老实说,这在没有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

【讨论】:

  • 在顶部添加查询
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-15
  • 2017-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多