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

时间:2012-05-09 14:06:17

标签: sql-server tsql casting integer isnumeric

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

以下是一些清晰明了的代码。如果MY_FIELD不是int,则此代码将失败:

SELECT @MY_VAR = CAST(MY_FIELD AS INT)
FROM MY_TABLE
WHERE MY_OTHER_FIELD = 'MY_FILTER'

谢谢

22 个答案:

答案 0 :(得分:32)

这是一个blog post,描述了IsInteger UDF的创建。

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

答案 1 :(得分:23)

在他的文章Can I convert this string to an integer?中,Itzik Ben-Gan提供了纯T-SQL的解决方案和另一个使用CLR的解决方案。

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

  

T-SQL或CLR解决方案更好吗?使用T-SQL的优势   解决方案是您不需要超出T-SQL的域   节目。但是,CLR解决方案有两个重要优势:   它更简单,更快捷。当我针对桌子测试两种解决方案时   有100万行,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;

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

SELECT keycol, string, ISNUMERIC(string) AS is_numeric,
  dbo.fn_IsInt(string) AS is_int
FROM dbo.T1;

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);
        }
    }
};

请阅读Itzik的文章,了解这些代码示例的完整说明。

答案 2 :(得分:13)

使用sqlserver 2005及更高版本,您可以将类似于regex的字符类与LIKE运算符一起使用。请参阅here

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

SELECT numstr
  FROM table
 WHERE numstr NOT LIKE '%[^0-9]%'

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

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

请参阅fiddle

答案 3 :(得分:6)

WHERE IsNumeric(MY_FIELD) = 1 AND CAST(MY_FIELD as VARCHAR(5)) NOT LIKE '%.%'

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

答案 4 :(得分:3)

以下对CASE WHEN子句是正确的;使函数将其包装在 ISNUMERIC(table.field) > 0 AND PATINDEX('%[^0123456789]%', table.field) = 0

<div class="col-lg-4 col-md-6 col-sm-12">
    <!-- your stuff here -->
</div>
<div class="col-lg-4 col-md-6 col-sm-12">
    <!-- your stuff here -->
</div>
<div class="col-lg-4 col-md-6 col-sm-12">
    <!-- your stuff here -->
</div><br>
<div class="col-lg-6 col-md-6 col-sm-12">
    <!-- your stuff here -->
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
    <!-- your stuff here -->
</div>

答案 5 :(得分:3)

  

查看以下查询是否有帮助

SELECT *
FROM MY_TABLE
WHERE CHARINDEX('.',MY_FIELD) = 0 AND CHARINDEX(',',MY_FIELD) = 0       
AND ISNUMERIC(MY_FIELD) = 1 AND CONVERT(FLOAT,MY_FIELD) / 2147483647 <= 1

答案 6 :(得分:2)

创新。
从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 

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

是否需要对SQL Server 2008的支持,然后再回过Sam DeHaan的回答:

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

SQL-Server <2012(aka 2008R2)将于2019-07-09终止支持(扩展)。
此时(即将到来),可以放弃对<2012的支持。
我现在不会再使用其他任何骇客了。
只需告诉您的节俭客户进行更新-自2008年以来已经有10年了。

答案 7 :(得分:2)

使用IsNumeric函数可以解决这个问题:

从A中选择*,其中ISNUMERIC(x)= 1而X不喜欢'%。%'

或使用

从A中选择*,其中x 不喜欢'%[^ 0-9]%'

答案 8 :(得分:1)

我尝试了这个脚本并得到了答案

ISNUMERIC(Replace(Replace([enter_your_number],'+','A'),'-','A') + '.0e0')

例如对于向上问题,这是答案:

SELECT @MY_VAR = CAST(MY_FIELD AS INT)
FROM MY_TABLE
WHERE MY_OTHER_FIELD = 'MY_FILTER' and ISNUMERIC(Replace(Replace(MY_FIELD,'+','A'),'-','A') + '.0e0') = 1

答案 9 :(得分:1)

我有一种感觉这样做是撒旦的工作,但作为另类:

TRY - CATCH怎么样?

DECLARE @Converted as INT
DECLARE @IsNumeric BIT

BEGIN TRY
    SET @Converted = cast(@ValueToCheck as int)
    SET @IsNumeric=1
END TRY
BEGIN CATCH
    SET @IsNumeric=0
END CATCH

select IIF(@IsNumeric=1,'Integer','Not integer') as IsInteger

这虽然只在SQL Server 2008及更高版本中有效。

答案 10 :(得分:1)

declare @i numeric(28,5) = 12.0001


if (@i/cast(@i as int) > 1)
begin
    select 'this is not int'
end
else
begin
    select 'this is int'
end

答案 11 :(得分:1)

我认为您的数据库设计存在问题。我认为在一列中混合varchar和数字是一个非常糟糕的主意吗?这是什么原因?

当然你可以检查是否有除[0-9]以外的任何字符,但想象你在表格中有1米的行并且你正在检查每一行。我认为它不会奏效。

无论如何,如果你真的想这样做,我建议你在客户端进行。

答案 12 :(得分:0)

有时您无法设计数据库,您只需要处理您的工作。就我而言,它是一台位于计算机上的数据库,自2008年以来我一直只有读取权限。

我需要从设计不佳的数据库中的列中进行选择,该数据库是varchar,数字为1-100但有时是随机字符串。我使用以下方法绕过它(虽然我希望我可以重新设计整个数据库)。

SELECT A from TABLE where isnumeric(A)=1

答案 13 :(得分:0)

我不是SQL方面的专家,但是检查它是否可以被1表示呢? 对我来说,它能胜任。

<session-config>
<cookie-config>
<http-only>true</http-only>
<secure>false</secure>
</cookie-config>
</session-config>

答案 14 :(得分:0)

使用PATINDEX

DECLARE @input VARCHAR(10)='102030.40'
SELECT PATINDEX('%[^0-9]%',RTRIM(LTRIM(@input))) AS IsNumber

参考 http://www.intellectsql.com/post-how-to-check-if-the-input-is-numeric/

答案 15 :(得分:0)

从SQL Server 2012开始,已实现TRY_CONVERTTRY_CAST函数。这是对ISNUMERIC解决方案的巨大改进,该解决方案可以(并且确实)提供假阳性(或阴性)。例如,如果您运行以下命令:

SELECT CONVERT(int,V.S)
FROM (VALUES('1'),
            ('900'),
            ('hello'),
            ('12b'),
            ('1.1'),
            ('')) V(S)
WHERE ISNUMERIC(V.S) = 1;

使用TRY_CONVERT(或TRY_CAST)可以避免这种情况:

SELECT TRY_CONVERT(int,V.S),
       V.S,
       ISNUMERIC(V.S)
FROM (VALUES('1'),
            ('900'),
            ('hello'),
            ('12b'),
            ('1.1'),
            ('')) V(S)
--WHERE TRY_CONVERT(int,V.S) IS NOT NULL; --To filter to only convertable values

请注意,'1.1'返回了NULL,这导致了之前的错误(因为十进制的字符串重新表示不能转换为int),而且还返回了'' 0,即使ISNUMERIC指出值“无法转换”。

答案 16 :(得分:0)

使用TRY_CONVERT,它是.NET中TryParse的SQL替代方法。 IsNumeric()不知道空字符串算作(整数)零,并且某些完全有效的货币符号本身不会转换为(货币)零。 reference

var declaration = document.styleSheets[0].cssRules[0].style;
var priority = declaration.getPropertyPriority("background-color");

答案 17 :(得分:0)

WHERE IsNumeric(value + 'e0') = 1 AND CONVERT(FLOAT, value) BETWEEN -2147483648 AND 2147483647

答案 18 :(得分:-1)

为什么不做以下事情:

CASE
WHEN ROUND(MY_FIELD,0)=MY_FIELD THEN CAST(MY_FIELD AS INT)
ELSE MY_FIELD
END
as MY_FIELD2

答案 19 :(得分:-1)

这在SQL Server中正常工作

SELECT(选择ISNUMERIC(2),其中ISNUMERIC(2)= 1和2不像'%。%')

答案 20 :(得分:-1)

Case
When (LNSEQNBR / 16384)%1 = 0 then 1 else 0 end

答案 21 :(得分:-1)

有同样的问题。我终于用

where ATTRIBUTE != round(ATTRIBUTE)

对我有用