有人最近问了我这个问题,我想我会把它发布在Stack Overflow上以获取一些意见。
现在显然以下两种情况都应该失败。
#1:
DECLARE @x BIGINT
SET @x = 100
SELECT CAST(@x AS VARCHAR(2))
明显的错误:
Msg 8115,Level 16,State 2,Line 3
将表达式转换为数据类型varchar的算术溢出错误。
#2:
DECLARE @x INT
SET @x = 100
SELECT CAST(@x AS VARCHAR(2))
不明显,它返回一个*(人们会认为这也是一个算术溢出?)
现在我真正的问题是,为什么???这仅仅是设计还是有历史或其他东西 在这背后阴险?
我看了几个网站,得不到满意的答案。
http://msdn.microsoft.com/en-us/library/aa226054(v=sql.80).aspx
请注意我知道/了解当一个整数太大而无法转换为特定大小的字符串,它将被“转换”为星号时,这是明显的答案,我希望我可以向所有人投票继续给出这个答案。 我想知道为什么使用星号而不是抛出异常,例如历史原因等??
答案 0 :(得分:34)
要获得更多乐趣,请尝试以下方法:
DECLARE @i INT
SET @i = 100
SELECT CAST(@i AS VARCHAR(2)) -- result: '*'
go
DECLARE @i INT
SET @i = 100
SELECT CAST(@i AS NVARCHAR(2)) -- result: Arithmetic overflow error
:)
您的查询的答案是:“历史原因”
数据类型INT和VARCHAR早于BIGINT和NVARCHAR。 很多 更旧。实际上它们属于原始 SQL规范。更老的是用星号替换输出的异常抑制方法。
后来,SQL人员认为抛出错误比替换伪造(并且通常令人困惑)输出字符串更好/更一致等。但是为了保持一致性,他们保留了先前存在的数据类型组合的先前行为(以免破坏现有代码)。
稍后当添加BIGINT和NVARCHAR数据类型时,他们得到了新的(呃)行为,因为他们没有被上面提到的祖父所覆盖。
答案 1 :(得分:2)
您可以在“截断和舍入结果”部分的CAST and CONVERT页面上阅读。 当结果长度太短而无法在转换为char或varchar时显示时,Int,smallint和tinyint将返回*。其他数字到字符串转换将返回错误。