我有一个简单的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语句,但我不知道我要去哪里。任何帮助将不胜感激。
答案 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