T-sql-определить, является ли значение целочисленным

Я хочу определить, является ли значение целочисленным (например,TryParse в .NET). К сожалению ISNUMERIC не подходит мне, потому что я хочу анализировать только целые числа, а не каждый вид чисел. Есть ли такая вещь, как ISINT или что-то?

вот некоторый код, чтобы сделать вещи ясно. Если MY_FIELD не является int, этот код завершится ошибкой:

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

спасибо

12 ответов


здесь блоге описание создания IsInteger UDF.

в основном, он рекомендует добавить '.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;

часть T-SQL решения CLR проще. Вызове функции 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);
        }
    }
};

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


С sqlserver 2005 и более поздних версий вы можете использовать regex-подобные классы символов с оператором LIKE. См.здесь.

чтобы проверить, является ли строка неотрицательным целым числом (это последовательность десятичных цифр), вы можете проверить, что она не содержит других символов.

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

Note1: это также вернет пустые строки.

Примечание 2: С Помощью LIKE '%[0-9]%' вернет любую строку, содержащую хотя бы цифру.

посмотреть скрипка


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

это, вероятно, самое простое решение. Если MY_FIELD содержит .00 или что-то в этом роде. В этом случае бросьте его на поплавок, чтобы удалить любой трейлинг .00-е


посмотрите, поможет ли приведенный ниже запрос

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

следующее правильно для WHERE предложение; чтобы функция обернула его в CASE WHEN.

 ISNUMERIC(table.field) > 0 AND PATINDEX('%[^0123456789]%', table.field) = 0

эта работа вокруг с IsNumeric функцией будет работать:

выберите * из A, где ISNUMERIC (x) =1 и X не нравится '%.%'

или использовать

выберите * из A, где x Не нравится '%[^0-9]%'


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

конечно, вы можете проверить, есть ли какие-либо символы, кроме [0-9], но представьте, что у вас есть строки 1m в таблице, и вы проверяете каждую строку. Думаю,это не сработает.

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


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

У меня такое чувство, что это работа сатаны, но в качестве альтернативы:

Как насчет попробовать поймать?

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 и выше.


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

мне нужно выбрать из столбца в плохо спроектированной базы данных, которая является varchar с числами 1-100, но иногда случайная строка. Я использовал следующее, чтобы обойти это (хотя я хотел бы, чтобы я мог повторно разработать всю базу данных).

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