У меня возникли проблемы с безопасным приведением varchar
к int
в SQL2000.
Часть 1 моей проблемы заключалась в том, что IsNumeric возвращает ложные срабатывания , если вы ищете целые числатолько.Однако я знаю, почему IsNumeric делает это (числа с плавающей запятой, деньги и т. Д. Тоже числовые), поэтому я искал в Google функцию IsInteger
.
Я обнаружил следующую пользовательскую функцию (UDF):
CREATE FUNCTION dbo.IsInteger
(
@num VARCHAR(64)
)
RETURNS BIT
BEGIN
IF LEFT(@num, 1) = '-'
SET @num = SUBSTRING(@num, 2, LEN(@num))
RETURN CASE
WHEN PATINDEX('%[^0-9-]%', @num) = 0
AND CHARINDEX('-', @num) <= 1
AND @num NOT IN ('.', '-', '+', '^')
AND LEN(@num)>0
AND @num NOT LIKE '%-%'
THEN
1
ELSE
0
END
END
это, кажется, хорошо проверяет целые числа:
declare @num varchar(256);
declare @num2 varchar(256);
set @num = '22312311';
set @num2 = '22312311.0';
SELECT @num AS [character],
dbo.IsInteger(@num) AS [isInteger],
CASE dbo.IsInteger(@num)WHEN 1 THEN convert(int, @num) ELSE NULL END AS [integer]
UNION
SELECT @num2 AS [character],
dbo.IsInteger(@num2) AS [isInteger],
CASE dbo.IsInteger(@num2)WHEN 1 THEN convert(int, @num2) ELSE NULL END AS [integer];
Как бы то ни было,t проверить, если целое число находится в пределах диапазона (-2^31 <=> 2^31 - 1
)
declare @num varchar(256);
set @num = '2147483648';
SELECT @num AS [character],
dbo.IsInteger(@num) AS [isInteger],
CASE dbo.IsInteger(@num)WHEN 1 THEN convert(int, @num) ELSE NULL END AS [integer];
, который выбрасывает
Server: Msg 248, Level 16, State 1, Line 3<br>
The conversion of the nvarchar value '2147483648' overflowed an int column. Maximum integer value exceeded.
SQL2000 не имеет TRY / CATCH (ответ предполагает, что ISNUMERIC () не возвращает ложных срабатываний), а ошибки приведения приводят к сбою всей партии даже в пределах UDF согласно этому веб-сайту :
При возникновении ошибкив UDF выполнение функции немедленно прерывается, как и запрос, и, если только ошибка не приводит к прерыванию пакета, выполнение продолжается для следующего оператора - но @@ error = 0!
и даже если бы они этого не делали, все равно оставалось неясным @@error
.Я также не могу привести к bigint
, поскольку он все еще может аварийно завершить работу (хотя и не так часто), и этот запрос является частью UNION, который выводится в XML, который дополнительно проверяется и преобразуется с помощью XSLT с помощью COM-библиотеки VB6 и отображается насайт закодирован еще в 2001 году, поэтому я действительно (не действительно ) не хочу менять вывод запроса!.
Так что я застрял в этой, казалось бы, простой задаче:
если varchar преобразуется в int для int, в противном случае вы получите NULL
Любые указатели / решения будут высоко цениться, но учтите, что я ни при каких обстоятельствах не могу изменитьТип данных исходного столбца также не изменяет проверку при вводе данных.