【问题标题】:SQL Server Convert() changing data?SQL Server Convert() 更改数据?
【发布时间】:2018-03-16 15:26:41
【问题描述】:

为什么会这样?

在以下示例中,当 i ISNULL 比较空白 int 和空白 varchar 时,它们彼此相等。 当相同的逻辑用转换包装时,它们彼此不相等。

DECLARE @myint int
DECLARE @mychar VARCHAR(200)

SET @myint = null
SET @mychar = NULL

SELECT CASE when CONVERT(VARCHAR(40),iSNULL(@myint,'')) = CONVERT(VARCHAR(40),ISNULL(@mychar,'')) THEN 1 ELSE 0 END AS 'poop'

SELECT CASE when iSNULL(@myint,'') =ISNULL(@mychar,'') THEN 1 ELSE 0 END AS 'poop'`

这是一个问题的原因是因为我正在创建带有几个附加字段的哈希键。我最近将一个字段的数据类型从 varchar 更改为 int(该字段只存储一个 int),现在当该字段为 null 时,生成的 hashkey 不同,因为 Convert 函数以某种方式将数据视为不同。

【问题讨论】:

    标签: sql sql-server type-conversion isnull


    【解决方案1】:

    如果你也打印出更小的表达式的结果是很有启发性的:

    DECLARE @myint int
    DECLARE @mychar VARCHAR(200)
    
    SET @myint = null
    SET @mychar = NULL
    
    SELECT CASE when CONVERT(VARCHAR(40),iSNULL(@myint,'')) = CONVERT(VARCHAR(40),ISNULL(@mychar,'')) THEN 1 ELSE 0 END AS 'poop',
    CONVERT(VARCHAR(40),iSNULL(@myint,'')),
    CONVERT(VARCHAR(40),ISNULL(@mychar,''))
    
    SELECT CASE when iSNULL(@myint,'') =ISNULL(@mychar,'') THEN 1 ELSE 0 END AS 'poop',
    iSNULL(@myint,''),
    ISNULL(@mychar,'')
    

    您应该能够看到,即使在检查了ISNULL 之后,您最终也会将@myint 替换为0@mychar 一个空字符串。为什么?因为ISNULL 将始终返回与其第一个参数相同类型的数据,对于@myInt,它是intint 不能存储空字符串。当空字符串转换为int 时,它会被解释为0

    这也是您的第二次比较中发生的情况 - 我们将 intvarchar 进行比较,并且由于 int 具有更高的优先级,这就是转换发生的方向,因此它们比较相等。

    但在第一种情况下,您实际上是在强制数据转换发生在另一个方向。并且0 转换为varchar 不会变成空字符串。

    【讨论】:

      【解决方案2】:

      这是因为隐式转换。当您在 ISNULL 中包装一个 int 并告诉它返回一个空字符串时,就会将该空字符串隐式转换为一个 int。当空字符串转换为 int 时,它变为 0。

      这就是我的意思。

      DECLARE @myint int
      SET @myint = null
      select iSNULL(@myint,'')
      

      【讨论】:

        【解决方案3】:

        原因与Data type precedence (Transact-SQL) 有关,这是 SQL Server 的文档化部分。

        对于ISNULL,使用的数据类型是第一个值的数据类型。所以对于ISNULL(@int,''),如果@int 的值为NULL,那么将使用值''。但是,''varchar,其数据类型优先级低于int;因此它被转换为int'' 作为 int 是 0。因此,(再次假设 @int 的值为 NULLISNULL(@int,'') = 0 的计算结果为 true。

        但是,如果 @int 是(奇怪的)varchar,那么 ISNULL(@int,'') 将返回 '',而不是 0。因此,您可以立即看到由于数据类型而导致的行为差异。 但请注意,即使 @intvarcharISNULL(@int,'') = 0 的计算结果仍为 true,因为解析表达式时将再次应用数据类型优先级。

        不同的函数以不同的方式处理数据类型优先级。因此,例如COALESCE 使用函数中使用的最高数据类型优先级。因此COALESCE('a',1) 会尝试返回int(并失败)。另一方面,ISNULL('a',1) 将返回 varchar(1),因为这是第一个参数的数据类型。

        【讨论】:

          猜你喜欢
          • 2021-05-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多