我想确定一个值是否为整数(如TryParse
在.NET 中)。不幸ISNUMERIC
的是不适合我,因为我只想解析整数而不是每种数字。有没有这样的ISINT
东西?
这是一些使事情变得清晰的代码。如果MY_FIELD
不是 int,则此代码将失败:
SELECT @MY_VAR = CAST(MY_FIELD AS INT)
FROM MY_TABLE
WHERE MY_OTHER_FIELD = 'MY_FILTER'
谢谢
我想确定一个值是否为整数(如TryParse
在.NET 中)。不幸ISNUMERIC
的是不适合我,因为我只想解析整数而不是每种数字。有没有这样的ISINT
东西?
这是一些使事情变得清晰的代码。如果MY_FIELD
不是 int,则此代码将失败:
SELECT @MY_VAR = CAST(MY_FIELD AS INT)
FROM MY_TABLE
WHERE MY_OTHER_FIELD = 'MY_FILTER'
谢谢
这是一篇描述UDF创建的博客文章。IsInteger
基本上,它建议增加'.e0'
值并使用IsNumeric
. 这样,任何已经有小数点的东西现在都有两个小数点,导致IsNumeric
为假,任何已经用科学计数法表示的东西都被e0
.
在他的文章中我可以将此字符串转换为整数吗?, 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 的文章以获得对这些代码示例的完整解释。
WHERE IsNumeric(MY_FIELD) = 1 AND CAST(MY_FIELD as VARCHAR(5)) NOT LIKE '%.%'
这可能是最简单的解决方案。除非您MY_FIELD
包含 .00 或类似的东西。在这种情况下,将其转换为浮点数以删除任何尾随 .00
死灵术。
从 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 多年了。
使用 IsNumeric 函数的这种解决方法将起作用:
select * from A where ISNUMERIC(x) =1 and X not like '%.%'
或使用
select * from A where x **not like** '%[^0-9]%'
以下对于一个WHERE
子句是正确的;使函数将其包装在CASE WHEN
.
ISNUMERIC(table.field) > 0 AND PATINDEX('%[^0123456789]%', table.field) = 0
看看下面的查询是否有帮助
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
声明@i 数字(28,5)= 12.0001 if (@i/cast(@i as int) > 1) 开始 选择“这不是 int” 结尾 别的 开始 选择“这是 int” 结尾
从 SQL Server 2012 开始,实现了TRY_CONVERT
和TRY_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
声明值“无法转换”。
我认为您的数据库设计有问题。我认为在一个列中混合 varchar 和数字是一个非常糟糕的主意?这是什么原因?
当然,您可以检查是否有除 [0-9] 以外的任何字符,但假设您在表中有 1m 行并且您正在检查每一行。我认为它不会很好地工作。
无论如何,如果您真的想这样做,我建议您在客户端进行。
我觉得这样做是撒旦的工作,但作为替代方案:
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 及更高版本中有效。
我尝试了这个脚本并得到了答案
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
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
为什么不这样做:
CASE
WHEN ROUND(MY_FIELD,0)=MY_FIELD THEN CAST(MY_FIELD AS INT)
ELSE MY_FIELD
END
as MY_FIELD2
我不是 SQL 的专业人士,但是如何检查它是否可以被 1 分开?对我来说,它完成了这项工作。
SELECT *
FROM table
WHERE fieldname % 1 = 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'
使用 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/
看到这已经很老了,但我的解决方案不在这里,我想添加另一种可能的方法来做到这一点:
--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
这里最简单的部分是检查选择的值在转换为整数时是否相同。
有同样的问题。我终于用了
where ATTRIBUTE != round(ATTRIBUTE)
它对我有用
WHERE IsNumeric(value + 'e0') = 1 AND CONVERT(FLOAT, value) BETWEEN -2147483648 AND 2147483647
Case
When (LNSEQNBR / 16384)%1 = 0 then 1
else 0
end
这在 SQL Server 中工作正常
SELECT (SELECT ISNUMERIC(2) WHERE ISNUMERIC(2)=1 AND 2 NOT LIKE '%.%')