SQL 服务器 Convert() 更改数据?
SQL Server Convert() changing data?
为什么会这样?
在下面的示例中,当我使用 ISNULL 比较空白 int 和空白 varchar 时,它们彼此相等。
当相同的逻辑被 convert 包装时,它们彼此不相等。
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 时,生成的哈希键不同,因为 Convert 函数以某种方式将数据视为不同。
如果您还打印出较小表达式的结果,这将很有启发:
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
总是 returns 与其第一个参数相同类型的数据,对于 @myInt
是 int
。并且 int
不能存储空字符串。当空字符串转换为 int
时,它被解释为 0
.
这也是您第二次比较中发生的情况 - 我们将 int
与 varchar
进行比较,并且由于 int
具有更高的优先级,这就是转换发生的方向in 等他们比较相等。
但在第一种情况下,您实际上是在强制数据转换发生在另一个方向。而0
转成varchar
不会变成空串。
原因都与 Data type precedence (Transact-SQL) 有关,这是 SQL 服务器的文档部分。
对于ISNULL
,使用的数据类型是第一个值的数据类型。所以对于ISNULL(@int,'')
,如果@int
的值为NULL
,那么就会使用''
的值。然而,''
是 varchar
,并且具有 比 int
更低的 数据类型优先级;因此它被转换为 int
。 ''
作为一个整数是 0
。因此,(再次假设 @int
的值为 NULL
)ISNULL(@int,'') = 0
的计算结果为真。
但是,如果 @int
是一个(奇怪的)varchar
,那么 ISNULL(@int,'')
将 return ''
,而不是 0
.因此,您可以立即看到因数据类型而导致的行为差异。 但是请注意,即使 @int
是 varchar
,ISNULL(@int,'') = 0
的计算结果仍为真,因为在解析表达式时数据类型优先级将再次应用。
不同的函数处理数据类型优先级的方式不同。因此,例如 COALESCE
在函数中使用最高数据类型优先级。因此 COALESCE('a',1)
会尝试 return 和 int
(并失败)。另一方面,ISNULL('a',1)
将 return 变成 varchar(1)
,因为这是第一个参数的数据类型。
这是因为隐式转换。当您在 ISNULL 中包装一个 int 并告诉它 return 一个空字符串时,会将该空字符串隐式转换为 int。当空字符串转换为 int 时,它变为 0。
这就是我的意思。
DECLARE @myint int
SET @myint = null
select iSNULL(@myint,'')
为什么会这样?
在下面的示例中,当我使用 ISNULL 比较空白 int 和空白 varchar 时,它们彼此相等。 当相同的逻辑被 convert 包装时,它们彼此不相等。
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 时,生成的哈希键不同,因为 Convert 函数以某种方式将数据视为不同。
如果您还打印出较小表达式的结果,这将很有启发:
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
总是 returns 与其第一个参数相同类型的数据,对于 @myInt
是 int
。并且 int
不能存储空字符串。当空字符串转换为 int
时,它被解释为 0
.
这也是您第二次比较中发生的情况 - 我们将 int
与 varchar
进行比较,并且由于 int
具有更高的优先级,这就是转换发生的方向in 等他们比较相等。
但在第一种情况下,您实际上是在强制数据转换发生在另一个方向。而0
转成varchar
不会变成空串。
原因都与 Data type precedence (Transact-SQL) 有关,这是 SQL 服务器的文档部分。
对于ISNULL
,使用的数据类型是第一个值的数据类型。所以对于ISNULL(@int,'')
,如果@int
的值为NULL
,那么就会使用''
的值。然而,''
是 varchar
,并且具有 比 int
更低的 数据类型优先级;因此它被转换为 int
。 ''
作为一个整数是 0
。因此,(再次假设 @int
的值为 NULL
)ISNULL(@int,'') = 0
的计算结果为真。
但是,如果 @int
是一个(奇怪的)varchar
,那么 ISNULL(@int,'')
将 return ''
,而不是 0
.因此,您可以立即看到因数据类型而导致的行为差异。 但是请注意,即使 @int
是 varchar
,ISNULL(@int,'') = 0
的计算结果仍为真,因为在解析表达式时数据类型优先级将再次应用。
不同的函数处理数据类型优先级的方式不同。因此,例如 COALESCE
在函数中使用最高数据类型优先级。因此 COALESCE('a',1)
会尝试 return 和 int
(并失败)。另一方面,ISNULL('a',1)
将 return 变成 varchar(1)
,因为这是第一个参数的数据类型。
这是因为隐式转换。当您在 ISNULL 中包装一个 int 并告诉它 return 一个空字符串时,会将该空字符串隐式转换为 int。当空字符串转换为 int 时,它变为 0。
这就是我的意思。
DECLARE @myint int
SET @myint = null
select iSNULL(@myint,'')