TSQL CASE意外处理多个THEN语句

时间:2018-09-19 19:37:02

标签: sql sql-server tsql case

我有一个简单的SQL CASE语句,该语句试图解释变量的数据类型,然后将其转换为所述格式。我有以下示例:

  DECLARE @P1 varchar(10) = '2';

  SELECT CASE 1 
    WHEN ISNUMERIC(@P1) THEN (CAST(@P1 AS INT)) 
    WHEN ISDATE(@P1) THEN (CAST(@P1 AS DateTime)) 
    ELSE 'N' END AS Test2P1

我希望它返回2的整数。但是,这就是我得到的。

Test2P1

1900-01-03 00:00:00.000

但是,如果我修改代码以仅显示字符而不是CASTING变量,则会得到不同的结果:

  DECLARE @P1 varchar(10) = '2';


  SELECT CASE 1 
    WHEN ISNUMERIC(@P1) THEN 'I' 
    WHEN ISDATE(@P1) THEN 'D'
    ELSE 'N' END AS Test2P1

然后我得到以下结果:I

再进行一次此实验,如果我让第一个测试返回“ I”但强制转换了日期,那么我会得到一个错误:

  DECLARE @P1 varchar(10) = '2';

  SELECT CASE 1 
    WHEN ISNUMERIC(@P1) THEN 'I'
    WHEN ISDATE(@P1) THEN (CAST(@P1 AS DateTime)) 
    ELSE 'N' END AS Test2P1

Msg 241, Level 16, State 1, Line 3
Conversion failed when converting date and/or time from character string.

似乎SQL正在评估THEN语句的多个实例。但是,ISDATE表达式不会返回true。我很沮丧。

在研究中,我碰到了这篇文章[SQL Performance](https://sqlperformance.com/2014/06/t-sql-queries/dirty-secrets-of-the-case-expression),他在本文中所说的完全有道理。但是我看不到它在这种情况下的适用范围,因为我从未更改过变量的值。

我也将CASE语句包装在COALESCE()中,但似乎无济于事。我本来没想到,但是我发现有多篇文章将其作为解决类似问题的解决方案。这似乎是一个非常简单的CASE语句,但我不知道我要去哪里。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:6)

DateTime在SQL Server中具有比INT高的数据类型优先级,因此您的整个CASE都将转换为DATETIME。您只能在一列中返回单个数据类型的数据,因此需要数据类型优先。

Here是显示优先级的MSDN文章。

答案 1 :(得分:0)

尽管我想不出这样做的充分理由,但是您可以强制case表达式返回sql_variant,该表达式可以存储多种不同的类型,例如:

 DECLARE @P1 varchar(10) = '2';

  SELECT CASE 1 
    when 0 then cast(null as sql_variant)
    WHEN ISNUMERIC(@P1) THEN (CAST(@P1 AS INT)) 
    WHEN ISDATE(@P1) THEN (CAST(@P1 AS DateTime)) 
    ELSE 'N' END AS Test2P1