为什么一个特定的 SQL 服务器数据库无法将 VARCHAR 转换为 NUMERIC?
Why would one specific SQL Server Database fail to convert VARCHAR to NUMERIC?
是否有可能 2 个不同的 SQL 服务器数据库,具有相同的模式和数据,可以以不同的方式处理查询,并且其中一个抛出“Error converting data type varchar to numeric.
”错误,而另一个没有?
例如,查看此查询:
SELECT count(*) FROM DEPARTMENTS dpt
inner join
EMPLOYEES emp
on dpt.subgroup_id = emp.subgroup_id
WHERE
emp.employee_id = 12856
and
dpt.department_id in
(
select cm.mapped_value from CONFIGURATIONS c
inner join
CONFIG_MAPPINGS cm on cm.configuration_id = c.id
where
c.name = 'Department that can override self-destruction protocol'
)
内部 select 子查询是 returning 一个可以转换为数字的值,或者根本没有结果。所以我注意到的是:
- 一个数据库运行
Microsoft SQL Server 2012 - 11.0.2100.60
执行查询没有错误,只要内部语句不会return一个非数字值
- 另一个数据库 运行
Microsoft SQL Server 2012 (SP4-GDR) (KB4057116) - 11.0.7462.6
总是抛出“Error converting data type varchar to numeric.
”错误,无论内部 select 查询 return 是什么。
我还注意到,如果我用另一个 return 完全相同但没有内连接的子查询更改子查询,第二个数据库不会抛出错误
SELECT count(*) FROM DEPARTMENTS dpt
inner join
EMPLOYEES emp
on dpt.subgroup_id = emp.subgroup_id
WHERE
emp.employee_id = 12856
and
dpt.department_id in
(
select cm.mapped_value FROM CONFIG_MAPPINGS
WHERE cm.configuration_id = 'DPT_OVERRIDE_SDP'
)
我知道无论如何我都应该改进查询,添加一个 ISNUMERIC
检查,但出于好奇,我的问题是:
会不会是这些数据库中的一个正在以不同的方式(可能是不同的执行计划)处理查询并且总是暴露错误,而另一个数据库设法执行查询?
执行此查询:
select cm.mapped_value FROM CONFIG_MAPPINGS
WHERE cm.configuration_id = 'DPT_OVERRIDE_SDP' AND ISNUMERIC(cm.mapped_value)<>1
和
select cm.mapped_value from CONFIGURATIONS c
inner join
CONFIG_MAPPINGS cm on cm.configuration_id = c.id
where
c.name = 'Department that can override self-destruction protocol'
AND ISNUMERIC(cm.mapped_value)<>1
查看哪些值是错误的原因。然后您可以在内部查询中使用 "ISNUMERIC(cm.mapped_value)=1" 来忽略它们。
比较两个数据库的执行计划后,我发现它们有很大的不同。
如果计划在加入 CONFIG_MAPPINGS
和 CONFIGURATIONS
之前加入 DEPARTMENTS
和 CONFIG_MAPPINGS
,并且在应用 c.name = ..
过滤器之前,那么我们将在 dpt.department_id (numeric) = cm.mapped_value
加入,而 mapped_value
也将在该点包含非数字值。
第二个数据库就是这种情况,这解释了转换错误
是否有可能 2 个不同的 SQL 服务器数据库,具有相同的模式和数据,可以以不同的方式处理查询,并且其中一个抛出“Error converting data type varchar to numeric.
”错误,而另一个没有?
例如,查看此查询:
SELECT count(*) FROM DEPARTMENTS dpt
inner join
EMPLOYEES emp
on dpt.subgroup_id = emp.subgroup_id
WHERE
emp.employee_id = 12856
and
dpt.department_id in
(
select cm.mapped_value from CONFIGURATIONS c
inner join
CONFIG_MAPPINGS cm on cm.configuration_id = c.id
where
c.name = 'Department that can override self-destruction protocol'
)
内部 select 子查询是 returning 一个可以转换为数字的值,或者根本没有结果。所以我注意到的是:
- 一个数据库运行
Microsoft SQL Server 2012 - 11.0.2100.60
执行查询没有错误,只要内部语句不会return一个非数字值 - 另一个数据库 运行
Microsoft SQL Server 2012 (SP4-GDR) (KB4057116) - 11.0.7462.6
总是抛出“Error converting data type varchar to numeric.
”错误,无论内部 select 查询 return 是什么。
我还注意到,如果我用另一个 return 完全相同但没有内连接的子查询更改子查询,第二个数据库不会抛出错误
SELECT count(*) FROM DEPARTMENTS dpt
inner join
EMPLOYEES emp
on dpt.subgroup_id = emp.subgroup_id
WHERE
emp.employee_id = 12856
and
dpt.department_id in
(
select cm.mapped_value FROM CONFIG_MAPPINGS
WHERE cm.configuration_id = 'DPT_OVERRIDE_SDP'
)
我知道无论如何我都应该改进查询,添加一个 ISNUMERIC
检查,但出于好奇,我的问题是:
会不会是这些数据库中的一个正在以不同的方式(可能是不同的执行计划)处理查询并且总是暴露错误,而另一个数据库设法执行查询?
执行此查询:
select cm.mapped_value FROM CONFIG_MAPPINGS
WHERE cm.configuration_id = 'DPT_OVERRIDE_SDP' AND ISNUMERIC(cm.mapped_value)<>1
和
select cm.mapped_value from CONFIGURATIONS c
inner join
CONFIG_MAPPINGS cm on cm.configuration_id = c.id
where
c.name = 'Department that can override self-destruction protocol'
AND ISNUMERIC(cm.mapped_value)<>1
查看哪些值是错误的原因。然后您可以在内部查询中使用 "ISNUMERIC(cm.mapped_value)=1" 来忽略它们。
比较两个数据库的执行计划后,我发现它们有很大的不同。
如果计划在加入 CONFIG_MAPPINGS
和 CONFIGURATIONS
之前加入 DEPARTMENTS
和 CONFIG_MAPPINGS
,并且在应用 c.name = ..
过滤器之前,那么我们将在 dpt.department_id (numeric) = cm.mapped_value
加入,而 mapped_value
也将在该点包含非数字值。
第二个数据库就是这种情况,这解释了转换错误