在SQL Server中实例CASE实现澄清?

时间:2013-10-23 07:58:34

标签: sql-server sql-server-2008-r2 case

我在sql server中有这个简单的表:

DECLARE @tbl table( a int ,  b NVARCHAR(100), isCalcByA bit)

INSERT INTO @tbl
SELECT 1,'c',1
UNION ALL
SELECT 2,'d',0

确定。

如果我这样做:

SELECT CASE 
            WHEN  isCalcByA = 1 THEN  a
            ELSE  b
       END  FROM @tbl

产生错误:

  

Msg 245,Level 16,State 1,Line 9
   将nvarchar值'd'转换为数据类型int时,转换失败。

可以理解为什么会这样:

因为正在累积(要显示)的数据无法在同一列附加intstring

确定

但是这个怎么样:

SELECT 'dummy'
FROM   @tbl
WHERE  CASE 
            WHEN isCalcByA = 1 THEN a
            ELSE b
       END IS NOT NULL

此处 -

  • 总是显示string
  • 我不会累积不同类型的显示结果。
  • 我正在针对not null而不是stringint值进行检查。

但我仍然遇到相同的错误。

我错过了什么?

NB

我知道我可以/应该这样做:

SELECT 'dummy'
FROM   @tbl
WHERE 
(isCalcByA = 1 AND a IS NOT NULL)

OR

(isCalcByA <> 1 AND b IS NOT NULL)

(工作正常)

但我问为什么它不适用于第一个CASE情况

4 个答案:

答案 0 :(得分:3)

CASE表达式 - 它返回特定类型的。它可能返回的所有可能值都必须可以转换为某种常见类型。系统使用类型优先级规则来考虑所有可能返回值的类型,并确定该常见类型是什么。 int具有更高的优先级并获胜。

CASE 
        WHEN isCalcByA = 1 THEN CONVERT(nvarchar(100),a)
        ELSE b
   END

会起作用,因为现在选择的常用类型是明确的nvarchar(100)

答案 1 :(得分:1)

无论您是在CASE还是SELECT子句中使用WHERECASE表达式应始终返回相同的数据类型。因此,将两列都转换为可以同时包含两者的数据类型:

CASE 
    WHEN isCalcByA = 1 THEN CAST(a AS NVARCHAR(100))
    ELSE b
END

来自CASE expression文档:

  

从result_expressions中的类型集和可选的else_result_expression返回最高优先级类型。

当各种WHENELSE部分具有不同的数据类型作为结果时,从该列表中选择最高优先级:Data Type Precedence并且所有结果都将转换为该数据类型。

您的查询失败,因为int的优先级高于nvarchar

答案 2 :(得分:0)

DECLARE @tbl table( a int ,  b NVARCHAR(100), isCalcByA bit)

INSERT INTO @tbl
SELECT 1,'c',1
UNION ALL
SELECT 2,'d',0
UNION ALL
SELECT null,'d',1


SELECT CASE 
            WHEN  isCalcByA = 1 THEN  CAST(a AS VARCHAR(30))
            ELSE  b
       END  FROM @tbl

上面,您将根据选择选择两种不同的数据类型。

SELECT 'dummy'
FROM   @tbl
WHERE  CASE 
            WHEN isCalcByA = 1 THEN CAST(a AS VARCHAR(30))
            ELSE b
       END IS NOT NULL

以上,无论条件如何,您每次都选择'哑'。

因此,在第一个声明中,您要根据return type设置case,并且案例可以返回two different types。在第二个查询中,返回类型始终为same type

答案 3 :(得分:0)

不要将CASE视为内置IF来自常规语言。它更像是具有强类型的... ? ... : ...运算符 - 它必须导致特定的单数类型。如果要混合列,则需要将其转换为例如nvarchar。

你也可以考虑一下,因为SELECT的结果应该可以由CREATE TABLE来定义。