56

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

这是一些使事情变得清晰的代码。如果MY_FIELD不是 int,则此代码将失败:

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

谢谢

4

23 回答 23

44

这是一篇描述UDF创建的博客文章。IsInteger

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

于 2012-05-09T14:12:04.100 回答
25

在他的文章中我可以将此字符串转换为整数吗?, 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;

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

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 的文章以获得对这些代码示例的完整解释。

于 2012-05-09T14:46:45.983 回答
19

使用 sqlserver 2005 及更高版本,您可以使用带有 LIKE 运算符的类似正则表达式的字符类。见这里

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

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

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

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

小提琴

于 2015-07-16T20:40:57.570 回答
10
WHERE IsNumeric(MY_FIELD) = 1 AND CAST(MY_FIELD as VARCHAR(5)) NOT LIKE '%.%'

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

于 2014-08-27T14:13:40.153 回答
4

死灵术。
从 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(又名 2008R2)将在 2019 年 7 月 9 日结束(扩展)支持。
此时,很快,可以放弃对 < 2012 的支持。
我现在不会再使用任何其他黑客了。
只需告诉您节俭的客户进行更新 - 自 2008 年以来已经 10 多年了。

于 2019-02-26T12:42:08.117 回答
3

使用 IsNumeric 函数的这种解决方法将起作用:

select * from A where ISNUMERIC(x) =1 and X not like '%.%'

或使用

select * from A where x **not like** '%[^0-9]%'

于 2017-09-12T11:22:39.667 回答
3

以下对于一个WHERE子句是正确的;使函数将其包装在CASE WHEN.

 ISNUMERIC(table.field) > 0 AND PATINDEX('%[^0123456789]%', table.field) = 0
于 2017-12-14T22:33:48.993 回答
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
于 2016-07-01T06:34:17.203 回答
2
声明@i 数字(28,5)= 12.0001


if (@i/cast(@i as int) > 1)
开始
    选择“这不是 int”
结尾
别的
开始
    选择“这是 int”
结尾
于 2016-04-06T10:32:10.773 回答
2

从 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(or 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声明值“无法转换”。

于 2019-03-07T17:09:48.050 回答
1

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

当然,您可以检查是否有除 [0-9] 以外的任何字符,但假设您在表中有 1m 行并且您正在检查每一行。我认为它不会很好地工作。

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

于 2012-05-09T14:21:55.440 回答
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 及更高版本中有效。

于 2017-05-17T12:08:23.993 回答
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
于 2021-01-09T12:20:49.070 回答
0

Sometimes you don't get to design the database, you just have to work with what you are given. In my case it's a database located on a computer that I only have read access to which has been around since 2008.

I need to select from a column in a poorly designed database which is a varchar with numbers 1-100 but sometimes a random string. I used the following to get around it (although I wish I could have re designed the entire database).

SELECT A from TABLE where isnumeric(A)=1
于 2015-02-04T23:25:56.697 回答
0

为什么不这样做:

CASE
WHEN ROUND(MY_FIELD,0)=MY_FIELD THEN CAST(MY_FIELD AS INT)
ELSE MY_FIELD
END
as MY_FIELD2
于 2014-07-08T21:21:34.323 回答
0

我不是 SQL 的专业人士,但是如何检查它是否可以被 1 分开?对我来说,它完成了这项工作。

SELECT *
FROM table    
WHERE fieldname % 1 = 0
于 2018-11-29T10:25:40.743 回答
0

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

SELECT @MY_VAR = CASE WHEN TRY_CONVERT(INT,MY_FIELD) IS NOT NULL THEN MY_FIELD
                 ELSE 0
                 END
FROM MY_TABLE
WHERE MY_OTHER_FIELD = 'MY_FILTER'
于 2020-05-21T18:42:48.097 回答
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/

于 2018-12-19T04:44:08.173 回答
0

看到这已经很老了,但我的解决方案不在这里,我想添加另一种可能的方法来做到这一点:

  --This query only returns values with decimals
  SELECT ActualCost
  FROM TransactionHistory
  where  cast(ActualCost as int) != ActualCost

  --This query only returns values without decimals
  SELECT ActualCost
  FROM TransactionHistory
  where  cast(ActualCost as int) = ActualCost

这里最简单的部分是检查选择的值在转换为整数时是否相同。

于 2022-03-04T13:36:32.557 回答
0

有同样的问题。我终于用了

where ATTRIBUTE != round(ATTRIBUTE)

它对我有用

于 2020-08-06T00:28:10.547 回答
0
WHERE IsNumeric(value + 'e0') = 1 AND CONVERT(FLOAT, value) BETWEEN -2147483648 AND 2147483647
于 2020-12-02T22:30:22.120 回答
-1

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

于 2020-02-21T20:08:10.120 回答
-1

这在 SQL Server 中工作正常

SELECT (SELECT ISNUMERIC(2) WHERE ISNUMERIC(2)=1 AND 2 NOT LIKE '%.%')

于 2019-03-01T05:51:01.433 回答