SQL 服务器:根据使用的 WHERE 条件将数据类型 nvarchar 转换为数字时出错

SQL Server: Error converting data type nvarchar to numeric depending on WHERE condition used

我正在使用一个 table,它有一个 NVARCHAR ID 列和另外两个只有十进制值的 NVARCHAR 列,但我不能随意更改模式。

使用CAST(FIELD AS DECIMAL(18,6)),我能够对查询单个ID的数据执行所需的计算,但在查询2个ID时出现转换错误。

考虑两个 ID,'TEST1',AND 'TEST2',下面的就可以了

SELECT ID, CAST(FIELD AS DECIMAL(18,6)) AS FOO 
FROM MY_TABLE 
WHERE ID = 'TEST1'

这也可以正常工作

SELECT ID, CAST(FIELD AS DECIMAL(18,6)) AS FOO 
FROM MY_TABLE 
WHERE ID = 'TEST2'

然而这会产生错误

Error converting data type nvarchar to numeric

SELECT ID, CAST(FIELD AS DECIMAL(18,6)) AS FOO 
FROM MY_TABLE 
WHERE ID = 'TEST1' OR ID = 'TEST2'

我该如何处理?

区别在于执行路径。根据您的前两个查询,以下应该 return 一个有效的结果集:

SELECT ID, CAST(FIELD AS DECIMAL(18,6)) AS FOO
FROM MY_TABLE
WHERE ID = 'TEST1' OR ID = 'TEST2';

不幸的是,正在发生的事情是 SQL 服务器决定进行完整的 table 扫描 cast() 推向更接近数据。 FIELD 的某些值而不是 'TEST1''TEST2' 导致了问题。

我认为这是一个错误。不管我的意见如何,SQL Server 2012+ 中有一个简单的修复方法:

SELECT ID, TRY_CAST(FIELD AS DECIMAL(18, 6)) AS FOO
FROM MY_TABLE
WHERE ID = 'TEST1' OR ID = 'TEST2';

在 SQL Server 2008(即将不再支持)中,您可以使用 CASE 表达式:

SELECT ID,
       (CASE WHEN FIELD NOT LIKE '%[^0-9.]%' AND
                  FIELD NOT LIKE '%.%.%'
             THEN CAST(FIELD AS DECIMAL(18, 6))
        END) AS FOO
FROM MY_TABLE
WHERE ID = 'TEST1' OR ID = 'TEST2';

这不会失败,而是 return NULL,它会被忽略。此外,您应该使用 ID IN ('TEST1', 'TEST2') 而不是 OR,但这与您的问题无关。