T-sql - 确定值是否为整数

zaf*_*s.m 40 t-sql sql-server integer casting isnumeric

我想确定一个值是否为整数(如TryParse在.NET中).不幸的是ISNUMERIC,我不适合我,因为我只想解析整数而不是每种数字.有ISINT什么东西吗?

这里有一些代码可以清楚地表达出来.如果MY_FIELD不是int,则此代码将失败:

SELECT @MY_VAR = CAST(MY_FIELD AS INT)
FROM MY_TABLE
WHERE MY_OTHER_FIELD = 'MY_FILTER'
Run Code Online (Sandbox Code Playgroud)

谢谢

Sam*_*aan 35

这是一篇描述IsIntegerUDF 创建的博客文章.

基本上,它建议添加'.e0'值并使用IsNumeric.这样,任何已经有小数点的东西现在都有两个小数点,导致IsNumeric为假,并且任何已经用科学记数法表示的东西都被无效e0.

  • 博客文章中显示的功能在几个方面存在缺陷.不要使用它!这些输入返回一个肯定不正确的肯定结果:SELECT/*超过18个字符 - 函数应接受MAX数据类型并测试更多无效长度*/dbo.IsInt32('99999999999999999999999999999999999999999999930'),/*18个字符,但显然不是有效的int*/dbo.IsInt32('999999999999999999'); (6认同)

Iai*_*der 23

在他的文章中我可以将此字符串转换为整数吗?,Itzik Ben-Gan提供了纯T-SQL的解决方案和另一个使用CLR的解决方案.

您应该选择哪种解决方案?

T-SQL或CLR解决方案更好吗? 使用T-SQL解决方案的优点是您不需要超出T-SQL编程领域.但是,CLR解决方案有两个重要优点:它更简单,更快捷.当我针对具有1,000,000行的表测试两种解决方案时,CLR解决方案需要两秒钟,而不是七秒钟(对于T-SQL解决方案),可以在我的笔记本电脑上运行.因此,下次需要检查给定字符串是否可以转换为整数时,可以包含我在本文中提供的T-SQL或CLR解决方案.

如果您只想维护T-SQL,那么请使用纯T-SQL解决方案.如果性能比方便更重要,那么使用CLR解决方案.

纯T-SQL解决方案很棘手.它将内置的ISNUMERIC函数与模式匹配和转换相结合,以检查字符串是否表示int.

SELECT keycol, string, ISNUMERIC(string) AS is_numeric,
  CASE
    WHEN ISNUMERIC(string) = 0     THEN 0
    WHEN string LIKE '%[^-+ 0-9]%' THEN 0
    WHEN CAST(string AS NUMERIC(38, 0))
      NOT BETWEEN -2147483648. AND 2147483647. THEN 0
    ELSE 1
  END AS is_int
FROM dbo.T1;
Run Code Online (Sandbox Code Playgroud)

CLR解决方案的T-SQL部分更简单.您调用fn_IsInt函数就像调用ISNUMERIC一样.

SELECT keycol, string, ISNUMERIC(string) AS is_numeric,
  dbo.fn_IsInt(string) AS is_int
FROM dbo.T1;
Run Code Online (Sandbox Code Playgroud)

C#部分只是.NET解析函数Int32.TryParse的包装器.这是有效的,因为SQL Server int和.NET Int32都是32位有符号整数.

using System;
using System.Data.SqlTypes;

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlBoolean fn_IsInt(SqlString s)
    {
        if (s.IsNull)
            return SqlBoolean.False;
        else
        {
            Int32 i = 0;
            return Int32.TryParse(s.Value, out i);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

有关这些代码示例的完整说明,请阅读Itzik的文章.


101*_*010 14

使用sqlserver 2005及更高版本,您可以使用LIKE运算符使用类似regex的字符类.看到这里.

要检查字符串是否为非负整数(它是一个十进制数字序列),您可以测试它是否包含其他字符.

SELECT numstr
  FROM table
 WHERE numstr NOT LIKE '%[^0-9]%'
Run Code Online (Sandbox Code Playgroud)

注1:这也将返回空字符串.

注意2:使用LIKE '%[0-9]%'将返回包含至少一个数字的任何字符串.

小提琴


小智 6

WHERE IsNumeric(MY_FIELD) = 1 AND CAST(MY_FIELD as VARCHAR(5)) NOT LIKE '%.%'
Run Code Online (Sandbox Code Playgroud)

这可能是最简单的解决方案.除非你MY_FIELD包含.00或类似的东西.在这种情况下,将其强制转换为浮动以删除任何尾随的.00s


Ste*_*ger 6

死灵术。
从 SQL-Server 2012+ 开始,您可以使用 TRY_CAST,如果转换不成功,它会返回 NULL。

例子:

DECLARE @foo varchar(200)
SET @foo = '0123' 
-- SET @foo = '-0123' 
-- SET @foo = '+0123' 
-- SET @foo = '+-0123' 
-- SET @foo = '+-0123' 
-- SET @foo = '.123' 
-- SET @foo = '1.23' 
-- SET @foo = '.' 
-- SET @foo = '..' 
-- SET @foo = '0123e10' 

SELECT CASE WHEN TRY_CAST(@foo AS integer) IS NULL AND @foo IS NOT NULL THEN 0 ELSE 1 END AS isInteger 
Run Code Online (Sandbox Code Playgroud)

这是唯一真正可靠的方法。

如果您需要 SQL-Server 2008 支持,请参考 Sam DeHaan 的回答:

SELECT CASE WHEN ISNUMERIC(@foo + '.e0') = 1 THEN 1 ELSE 0 END AS isInteger 
Run Code Online (Sandbox Code Playgroud)

SQL-Server < 2012(又名 2008R2)将于 2019 年 7 月 9 日结束(扩展)支持。
此时,很快,对 < 2012 的支持就会被放弃。
此时我不会再使用任何其他黑客了。
只需告诉您节俭的客户进行更新即可 - 自 2008 年以来已经过去 10 多年了。