Есть ли причина непоследовательной обработки переполнения типа данных в SQL Server?

Я хотел бы знать, что может быть причиной непоследовательного способа, которым сервер sql обрабатывает переполнение типа. И как правильно предотвратить тихое повреждение данных, которое вызывает у нас SQL Server.

Хорошо себя int

Например, int дает правильное исключение переполнения.

declare @b int = 123456789000
Msg 8115, Level 16, State 2, Line 3
Arithmetic overflow error converting expression to data type int.

Безмолвный bit

Битовое значение будет равно нулю для нуля и единице для всего остального, что вы пытаетесь вставить (с небольшим дополнительным развлечением на пустой строке).

declare @a bit = 123
      , @b bit = ''
select a = @a, b = @b

выход:

a     b
----- -----
1     0
create table #bit_type(a bit) 
insert into #bit_type values (123), ('')
select * from #bit_type

выход:

a
-
1
0
declare @bit_type table (a bit)
insert into @bit_type values (123), ('')
select * from @bit_type

выход:

a
-
1
0

Такое поведение часто является причиной очень проблем с отладкой ETL (недопустимое значение во входном файле автоматически преобразуется в 1 или ноль)

Шизофреник varchar

Varchar (и char/nchar/nvarchar) — еще один раздражающий тип данных.

declare @c varchar(5)
select @c = '123456789'
print @c 

Результат молча усекается.

12345

create table #varchar_type(a varchar(5)) 
insert into #varchar_type values ('123456789')

Здесь мы получаем правильную ошибку переполнения.

Сообщение 8152, уровень 16, состояние 14, строка 1 Строка или двоичные данные будут усечены. Заявление было прекращено.

declare @varchar_type  table(a varchar(5)) 
insert into @varchar_type values ('123456789')

Здесь мы также получаем правильную ошибку переполнения.

Сообщение 8152, уровень 16, состояние 14, строка 2 Строковые или двоичные данные будут усечены. Заявление было прекращено.


person Filip De Vos    schedule 11.08.2011    source источник
comment
Я чувствую твою боль. Округление также непостоянно - некоторые типы округляются в большую сторону, некоторые в меньшую. Будь осторожен.   -  person A-K    schedule 11.08.2011


Ответы (1)


BIT

SQL предполагает, что числовое значение ЛЮБОЕ равно 'TRUE', а пустая строка или 0 равно 'FALSE'.

Лучший способ справиться с этим - фильтровать код, т.е.:

DECLARE @b BIT
DECLARE @v char(4) = '1234'

SET @b = (CASE WHEN @v = '1' THEN 1 ELSE 0 END)

SELECT @b

Varchar

SQL не считает @variables столь же важными, как таблицы. Ошибку переполнения в таблицах можно также отключить с помощью команда SET ANSI WARNINGS OFF.

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

  • Вы устанавливаете длину переменной (по большей части это не автоматически)
  • Вы указываете ввод
  • Следовательно, вы должны знать, может ли ваш ввод переполниться, и вы проверите его при необходимости.

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

Рекомендуемая процедура аналогична процедуре для бита:

DECLARE @v varchar(10)
DECLARE @str varchar(25) = 'This is a longer string'

IF LEN(@str) <= 10
    SET @v = @Str
ELSE RAISERROR('Invalid string length!', 0, 1) WITH NOWAIT
person JNK    schedule 11.08.2011
comment
бит истинен для любого числового значения. Я все еще считаю, что это плохое дизайнерское решение, которое весьма подвержено ошибкам. BCP, например, также спокойно перекачивает данные в битовый столбец. Хорошая мысль о SET ANSI WARNINGS OFF. Я просто хочу, чтобы переменные также следовали этому параметру. - person Filip De Vos; 11.08.2011
comment
Переменные varchar особенно сложны, например, при объединении строк в динамическом sql. (Я знаю, меньше проблем с varchar(max)) - person Filip De Vos; 11.08.2011
comment
@Filip - bit также отвечает на строки TRUE и FALSE - person JNK; 11.08.2011
comment
@filip - еще больше причин для проверки ваших входных данных - person JNK; 11.08.2011
comment
На данный момент я установил контрольные ограничения для всех битовых столбцов. - person Filip De Vos; 11.08.2011