我有这样的查询:
SELECT SerialNumber
FROM [ETEL-PRDSQL].[ERP10DBLIVE].[ERP].[SerialNo]
WHERE CustNum IN (2);
导致以下错误:
Msg 245, Level 16, State 1, Line 4
将nvarchar值'239.6'转换为int数据类型时失败。
如果我将CustNum
与不同的值进行比较,则查询工作,但当我尝试CustNum IN (2)
时失败。
我该如何解决这个问题?
您有一个名为CustNum
的varchar
列。本列中的varchar
值可能只包含数字,但这并不使它们成为数字!然后将此文本列与整数值2
进行比较。同样,整数值2
与文本值'2'
不同。它也不同于浮点值2.0
。这些都是不同的,它们有不同的类型,SQL Server必须在比较值之前解决任何这样的差异。
根据类型优先规则,SQL Server决定它需要将列中的文本转换为整数,而不是相反。在为查询做出此决定之后,如果文本列中有任何数据不是,则整数-compatible,查询将失败。
重要的是要理解这种转换与WHERE子句中的条件检查分开发生,并且是该检查的先决条件。对于不进行转换的行,期望WHERE条件求值为FALSE是不够的。这是真的,即使你不需要行,因为SQL Server不能知道你不需要行,直到它尝试转换!
在本例中,我们的值是293.6
。该值可以是数字,但不是整数。它也不能转换为整数。因此查询失败。
除了(最终!)查询失败之外,这对性能来说绝对是糟糕的。SQL Server必须为表中的每一行做此转换…即使是你不需要的行。这是因为SQL Server在检查条件表达式之前不知道哪些行将匹配WHERE子句,并且需要进行此转换以进行检查。更糟糕的是,新的转换值不再匹配您的索引,因此您的任何索引对于该查询都可能变得毫无价值。这直接关系到数据库性能的核心。
如果你不喜欢它,更好地定义你的数据类型,或者尝试将字符串与另一个字符串进行比较:
SELECT SerialNumber
FROM [ETEL-PRDSQL].[ERP10DBLIVE].[ERP].[SerialNo]
WHERE CustNum IN ('2');
如果您这样做,查询也可能运行:
SELECT SerialNumber
FROM [ETEL-PRDSQL].[ERP10DBLIVE].[ERP].[SerialNo]
WHERE CustNum IN (2.0);
现在,类型优先规则将把文本转换为浮点类型,如果表中的其他值兼容,则有可能成功。也有可能这更接近你的意图……但是,这里的性能会差得多。