开发者

Is there a reason for the inconsistent datatype overflow handling of SQL Server

开发者 https://www.devze.com 2023-03-27 01:46 出处:网络
I would like to know what the reasoning could be for inconsistent way sql server handles type overflowing. And what would be the proper way to prevent the silent data corruption SQL Server inflicts on

I would like to know what the reasoning could be for inconsistent way sql server handles type overflowing. And what would be the proper way to prevent the silent data corruption SQL Server inflicts on us.

The well behaved int

An int f开发者_运维知识库or example gives a proper overflow exception

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

The Silent bit

A bit value will be zero for zero and one for everything else you try to put in (with a little extra fun on an empty string).

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

output:

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

output:

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

output:

a
-
1
0

This behavior is often the cause of very hard to debug ETL problems (invalid value in an input file is silently converted to a 1 or a zero)

The schizophrenic varchar

Varchar (and char/nchar/nvarchar) is another highly annoying datatype

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

The result is silently truncated.

12345

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

Here we get a proper overflow error.

Msg 8152, Level 16, State 14, Line 1 String or binary data would be truncated. The statement has been terminated.

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

Here we get a proper overflow error as well.

Msg 8152, Level 16, State 14, Line 2 String or binary data would be truncated. The statement has been terminated.


BIT

SQL is assuming that ANY numeric value is 'TRUE', while an empty string or 0 is 'FALSE'.

The best way to handle this is through filtering in your code, i.e.:

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

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

SELECT @b

Varchar

SQL doesn't consider @variables as mission-critical as tables. The overflow error on tables can be disabled as well by using the SET ANSI WARNINGS OFF command.

I think the designers also assumed that if you are declaring a variable with a length, you will handle checking the length of that variable yourself. Other reasons could include:

  • You are setting the length of the variable (it's not automatic for the most part)
  • You are specifying the input
  • Ergo, you should know if your input will possibly overflow, and you will check for it if necessary

This is different for a string than an int since a string can still be useful when truncated, while truncation fundamentally changes the nature and value of a number.

The recommended procedure is similar to that for bit:

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
0

精彩评论

暂无评论...
验证码 换一张
取 消