2

我在 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

它产生一个错误:

消息 245,级别 16,状态 1,第 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而不是 a stringorint值。

但我仍然得到同样的错误。

我错过了什么?

注意

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

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

OR

(isCalcByA <> 1 AND b IS NOT NULL)

(效果很好)

但我问为什么它在第一种CASE情况下不起作用

4

4 回答 4

3

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

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

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

于 2013-10-23T08:12:54.733 回答
1

不管你CASE是在 theSELECT还是WHERE从句中使用。CASE表达式应始终返回相同的数据类型。因此,将两列都转换为可以同时保存的数据类型:

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

CASE表达式文档:

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

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

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

于 2013-10-23T08:11:30.373 回答
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并且 case 可以返回two different types。在第二个查询中,返回类型始终是same type.

于 2013-10-23T08:02:45.713 回答
0

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

您也可以将其视为 SELECT 的结果应该可以由CREATE TABLE.

于 2013-10-23T08:16:52.000 回答