SQL Server, где поле int?

как я могу выполнить:

select * from table where column_value is int 

Я знаю, что, возможно, я могу присоединиться к системным таблицам и типам таблиц, но мне интересно, есть ли более элегантный способ.

Обратите внимание, что column_value является varchar, который «мог» иметь int, но не обязательно.

Может быть, я могу просто бросить его и поймать ошибку? Но опять же, это похоже на хак.

 select * from table where column_value not like '[^0-9]' 

Если отрицательные ints разрешены, вам нужно что-то вроде

 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 гарантирует, что выражение может быть преобразовано в один из этих числовых типов.

Я бы сделал 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 », вы можете отправить его в другой скалярный UDF, называемый IsInt (), чтобы вызвать эту функцию и просто вернуть « 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».
Если вы хотите разрешить округление, то настройте логику в предложении «THEN», чтобы добавить Round () следующим образом:
ROUND (CAST (REPLACE (REPLACE (@IntString, '$', ''), ',', '') как десятичный (10)), 0)
Вы также должны удалить «И», который проверяет «десятичные точки», чтобы разрешить округление или усечение.

Почему бы не использовать следующее и проверить на 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-способные к 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, вам придется иметь дело с пустой строкой и начальным отрицательным знаком. И вручную убедитесь, что он не слишком длинный для вашего разнообразия INTEGER.