我怎样才能完成:
select * from table where column_value is int
我知道我可能可以内部加入系统表和类型表,但我想知道是否有更优雅的方式。
请注意, column_value 是一个“可能”具有 int 的 varchar,但不一定。
也许我可以将其转换并捕获错误?但同样,这似乎是一个黑客行为。
我怎样才能完成:
select * from table where column_value is int
我知道我可能可以内部加入系统表和类型表,但我想知道是否有更优雅的方式。
请注意, column_value 是一个“可能”具有 int 的 varchar,但不一定。
也许我可以将其转换并捕获错误?但同样,这似乎是一个黑客行为。
select * from table
where column_value not like '[^0-9]'
如果允许负整数,则需要类似
where column_value like '[+-]%'
and substring(column_value,patindex('[+-]',substring(column_value,1))+1,len(column_value))
not like '[^0-9]'
如果 column_value 可以是超出“int”类型限制的整数,并且您希望排除此类情况,则需要更多代码。
在这里如果你想实现你的自定义功能
CREATE Function dbo.IsInteger(@Value VARCHAR(18))
RETURNS BIT
AS
BEGIN
RETURN ISNULL(
(SELECT CASE WHEN CHARINDEX('.', @Value) > 0 THEN
CASE WHEN CONVERT(int, PARSENAME(@Value, 1)) <> 0 THEN 0 ELSE 1 END
ELSE 1
END
WHERE ISNUMERIC(@Value + 'e0') = 1), 0)
END
当输入表达式计算为有效整数、浮点数、货币或小数类型时,ISNUMERIC 返回 1 ;否则返回 0。返回值 1 保证表达式可以转换为这些数字类型之一。
我会按照 Svetlozar Angelov 的建议做一个 UDF,但我会先检查 ISNUMERIC(如果不是则返回 0),然后检查column_value % 1 = 0
它是否是整数。
这是身体的样子。您必须将模逻辑放在单独的分支中,因为如果值不是数字,它将引发异常。
DECLARE @RV BIT
IF ISNUMERIC(@value) BEGIN
IF CAST(@value AS NUMERIC) % 1 = 0 SET @RV = 1
ELSE SET @RV = 0
END
ELSE SET @RV = 0
RETURN @RV
这应该处理所有情况而不会引发任何异常:
--This handles dollar-signs, commas, decimal-points, and values too big or small,
-- all while safely returning an int.
DECLARE @IntString as VarChar(50) = '$1,000.'
SELECT CAST((CASE WHEN --This IsNumeric check here does most of the heavy lifting. The rest is Integer-Specific
ISNUMERIC(@IntString) = 1
--Only allow Int-related characters. This will exclude things like 'e' and other foreign currency characters.
AND @IntString NOT LIKE '%[^ $,.\-+0-9]%' ESCAPE '\'--'
--Checks that the value is not out of bounds for an Integer.
AND CAST(REPLACE(REPLACE(@IntString,'$',''),',','') as Decimal(38)) BETWEEN -2147483648 AND 2147483647
--This allows values with decimal-points for count as an Int, so long as there it is not a fractional value.
AND CAST(REPLACE(REPLACE(@IntString,'$',''),',','') as Decimal(38)) = CAST(REPLACE(REPLACE(@IntString,'$',''),',','') as Decimal(38,2))
--This will safely convert values with decimal points to casting later as an Int.
THEN CAST(REPLACE(REPLACE(@IntString,'$',''),',','') as Decimal(10))
END) as Int)[Integer]
将其放入标量 UDF 中并将其称为ReturnInt()。
如果该值返回为 NULL,则它不是 int (所以有您的 IsInteger() 要求)
如果您不喜欢键入“ WHERE ReturnInt(SomeValue) IS NOT NULL ”,则可以将其放入另一个名为IsInt()的标量UDF中以调用此函数并简单地返回“ ReturnInt(SomeValue) IS NOT NULL ”。
很酷的是,UDF 可以通过返回“安全”转换的 int 值来提供双重任务。
仅仅因为某些东西可以是 int 并不意味着将其转换为 int 不会引发巨大的异常。这会为您解决这个问题。
另外,我会避免使用其他解决方案,因为这种通用方法将处理逗号、小数、美元符号,并检查可接受的 Int 值的范围,而其他解决方案则不会 - 或者它们需要多个 SET 操作来阻止您使用逻辑一个标量函数以获得最佳性能。
请参阅下面的示例并针对我的代码和其他代码进行测试:
--Proves that appending "e0" or ".0e0" is NOT a good idea.
select ISNUMERIC('$1' + 'e0')--Returns: 0.
select ISNUMERIC('1,000' + 'e0')--Returns: 0.
select ISNUMERIC('1.0' + '.0e0')--Returns: 0.
--While these are numeric, they WILL break your code
-- if you try to cast them directly as int.
select ISNUMERIC('1,000')--Returns: 1.
select CAST('1,000' as Int)--Will throw exception.
select ISNUMERIC('$1')--Returns: 1.
select CAST('$1' as Int)--Will throw exception.
select ISNUMERIC('10.0')--Returns: 1.
select CAST('10.0' as Int)--Will throw exception.
select ISNUMERIC('9999999999223372036854775807')--Returns: 1. This is why I use Decimal(38) as Decimal defaults to Decimal(18).
select CAST('9999999999223372036854775807' as Int)--Will throw exception.
更新:
我在这里阅读了一条评论,您希望能够解析像“123”这样的值。成一个整数。我也更新了我的代码来处理这个问题。
注意:这会转换“1.0”,但会在“1.9”上返回 null。
如果要允许舍入,请调整“THEN”子句中的逻辑以添加 Round(),如下所示:
ROUND(CAST(REPLACE(REPLACE(@IntString,'$',''),',',' ') as Decimal(10)), 0)
您还必须删除检查“小数点”以允许舍入或截断的“AND”。
为什么不使用以下内容并测试 1?
DECLARE @TestValue nvarchar(MAX)
SET @TestValue = '1.04343234e5'
SELECT CASE WHEN ISNUMERIC(@TestValue) = 1
THEN CASE WHEN ROUND(@TestValue,0,1) = @TestValue
THEN 1
ELSE 0
END
ELSE null
END AS Analysis
如果您纯粹是想验证一个字符串是所有数字,而不仅仅是 CAST-able to INT,那么您可以做这个可怕的、可怕的事情:
select LEN(
REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE(
'-1.223344556677889900e-1'
,'0','') ,'1','') ,'2','') ,'3','') ,'4','') ,'5','') ,'6','') ,'7','') ,'8','') ,'9','')
)
当字符串为空或纯数字时返回 0。
为了使它成为“穷人”整数的有用检查,您必须处理空字符串和初始负号。并手动确保它对于您的各种 INTEGER 来说不会太长。