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
,但这与您的问题无关。
我正在使用一个 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
,但这与您的问题无关。