为什么一个特定的 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 一个可以转换为数字的值,或者根本没有结果。所以我注意到的是:

  1. 一个数据库运行 Microsoft SQL Server 2012 - 11.0.2100.60执行查询没有错误,只要内部语句不会return一个非数字值
  2. 另一个数据库 运行 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_MAPPINGSCONFIGURATIONS 之前加入 DEPARTMENTSCONFIG_MAPPINGS,并且在应用 c.name = .. 过滤器之前,那么我们将在 dpt.department_id (numeric) = cm.mapped_value 加入,而 mapped_value 也将在该点包含非数字值。

第二个数据库就是这种情况,这解释了转换错误