Msg 245,级别 16,状态 1,第 4 行 将 nvarchar 值'239.6'转换为数据类型 int 时转换失败



我有这样的查询:

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)时失败。

我该如何解决这个问题?

您有一个名为CustNumvarchar列。本列中的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);

现在,类型优先规则将把文本转换为浮点类型,如果表中的其他值兼容,则有可能成功。也有可能这更接近你的意图……但是,这里的性能会差得多。

最新更新