数据类型为tinyint的算术溢出错误,值= -1

时间:2014-06-11 13:48:41

标签: sql sql-server tsql

在运行此查询时,我收到错误,任何想法为什么?

select ISNULL(NULLIF(0,0), -1)

错误:

Msg 220,Level 16,State 2,Line 1

数据类型tinyint的算术溢出错误,值= -1。

编辑 - 另一个例子:

select ISNULL(NULLIF(0.0,0.0), 1.0)

Msg 8115,Level 16,State 8,Line 1 算术溢出错误将数字转换为数据类型数字。

2 个答案:

答案 0 :(得分:5)

这项工作:

select ISNULL(NULLIF(cast(0 as int),0), -1)

SQL优化器做"隐藏"转换为最小的数据类型。

来自NULLIF(http://technet.microsoft.com/pl-pl/library/ms177562%28v=sql.110%29.aspx)的文档:

  

返回与第一个表达式相同的类型。

所以NULLIF返回tinyint,ISNULL尝试将tinyint替换为-1然后你有溢出

当你将第一个参数(0)转换为int(或smallint)时,NULLIF会返回你的" new"数据类型,适用于-1

要查找正在使用的实际类型:

SELECT NULLIF(0,0) test_col INTO #test_table

SELECT data_type, numeric_precision, numeric_scale
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE '#test_table%' AND COLUMN_NAME = 'test_col'

答案 1 :(得分:1)

无论如何,这都是奇怪的行为。为什么像“0”这样的常量以不同的方式计算 - 有时是 int 有时是 tinyint。如果我做 SELECT 选择一个常量“0”,那么它被评估为“int”。但是将“0”传递给 NULLIF() 常量被评估为 tinyint。并且在 NULLIF 文档中根本没有提到这种行为。

-- 1) SELECT evaluates numeric constant "0" as "int":
DROP TABLE IF EXISTS #t
GO
SELECT c = 0
   INTO #t
GO

EXEC tempdb..sp_help #t
GO

-- 2) NULLIF() evaluates numeric constant "0" as "tynyint":
DROP TABLE IF EXISTS #t
GO
SELECT c = NULLIF(0, 0)
   INTO #t
GO

EXEC tempdb..sp_help #t
GO