9

我需要一种方法来检测 MSSQL 中表中带有无法转换为 int 的 varchar 条目的行。

我正在处理的系统在一个地方使用了一个可编辑的 varchar 字段,并将其连接到另一个地方的一个整数列。如果 varchar 字段中的数字无效(空白,带有字母或符号,或者将是超过 21 亿的数字(最大 int 大小)),则另一个查询失败,表示值 xyz 溢出了一个 int 列,或者可能不被转换。

我想出了以下部分解决方案来查找违规记录:

select g.id, g.membernumber from groups g
left join secondary_groups sg on sg.id=g.id 
where convert(bigint, g.membernumber) > 2147483647 
or isnumeric(g.membernumber) = 0

这对大多数事情都很好,但后来我意识到,如果你的 varchar 值超过'bigint',它可能会被打败。是否有更通用的方法来定位这些类型的记录,而不是使用强制转换/转换?如果有一个“IsInt()”的内置方法,那就太棒了,但是唉......

4

2 回答 2

14

从 SQL Server 2012 开始,您可以使用无法执行强制转换时返回的TRY_CAST表达式:NULL

select * from table
where TRY_CAST(Value as int) is null

请注意,它TRY_CAST使用与 相同的转换规则CAST,例如它将空白字符串转换为 0。这在您的情况下不是问题,但在 SQL 之外使用转换结果时应该考虑。

还有类似的TRY_CONVERT表达式,其语法与 相同CONVERT,但需要将 DB 兼容级别更改为 120 或更高,同时也TRY_CAST适用于 100。

于 2018-01-17T16:56:41.707 回答
7

如果您只对 INT 感兴趣,那么您可以使用 PATINDEX('[^0-9]', g.membernumber) 来测试字符串是否包含任何非数字字符。然后,您将使用 LEN 确保字符串不超过 10 个字符,然后尝试将其转换为 bigint。因此,WHERE 条件将如下所示:

where 1 = CASE WHEN patindex('%[^0-9]%', g.membernumber) > 0 THEN 1
               WHEN LEN(g.membernumber) > 10 THEN 1
               WHEN convert(bigint, g.membernumber) > 2147483647 THEN 1
               WHEN LEN(g.membernumber) = 0 THEN 1 --Empty string causes error on convert
               ELSE 0 END

SQL Server CASE用作短路评估。这就是我在 where 子句中使用 CASE 的原因

SQLFiddle

于 2013-06-17T23:21:23.197 回答