使用带有 ISNUMERIC 的派生表进行查询会导致转换失败(varchar 到 int)

Posted

技术标签:

【中文标题】使用带有 ISNUMERIC 的派生表进行查询会导致转换失败(varchar 到 int)【英文标题】:Query using a derived table with ISNUMERIC results in conversion failure (varchar to int) 【发布时间】:2012-02-28 10:17:33 【问题描述】:

这是一个示例查询:

DECLARE @table table (loc varchar(10))

INSERT INTO @table VALUES
('134a'), ('123'), ('abc'), ('124')

SELECT * 
FROM (
    SELECT * FROM @table WHERE ISNUMERIC(loc) = 1
) as a
WHERE CAST(loc as INT) BETWEEN 100 AND 200

如果我有一些 varchar 值并且我在查询的派生表中使用 ISNUMERIC 将它们限制为数值,为什么会导致转换错误?:

将 varchar 值“134a”转换为数据类型 int 时转换失败。

有没有办法解决这个问题?

【问题讨论】:

SQL Server 2008: Error converting data type nvarchar to float的可能重复 澄清一下:你有那个约束作为子查询并不重要。 SQL Server 解开它,因为它很容易。 @GSerg 你能详细说明“因为它很容易做到”吗? SQL Server 在执行前分析查询以构建执行计划。这个过程相当深刻和美好。可以展开和展平的东西通常是。这包括子查询和引用视图,以及内联表值函数。因此,请参阅链接的问题以了解解决方法。 @GSerg 谢谢,CASE 表达式可能是最简单的解决方法。 【参考方案1】:

WHERE 子句首先执行。试试:

DECLARE @table table (loc varchar(10)) 

INSERT INTO @table VALUES 
('134a'), ('123'), ('abc'), ('124') 

SELECT *  
FROM ( 
    SELECT * FROM @table
) as a 
WHERE ISNUMERIC(loc) = 1 and CAST(loc as INT) BETWEEN 100 AND 200 

【讨论】:

有什么方法可以确保ISNUMERIC(loc) 会在CAST(loc as INT) BETWEEN 100 AND 200 之前执行? SQL Server 保证相同优先级的运算符将从左到右计算,但不保证布尔表达式的短路计算。此外,似乎行为在不同的上下文中可能会有所不同,例如IFCASEWHERE。我希望我能引用一个权威的参考资料来解决这个问题。或者他们会像其他一些语言一样支持显式的AND_THENOR_ELSE 运算符。

以上是关于使用带有 ISNUMERIC 的派生表进行查询会导致转换失败(varchar 到 int)的主要内容,如果未能解决你的问题,请参考以下文章

Mysql如何ISNUMERIC()可用?

oracle数据库表频繁插入和删除,会导致用不到索引吗?

带有“order by”的派生表使用临时表和文件排序,即使我只选择主键

MySQL派生表

MySQL派生表

使用子查询派生表错误更新