【发布时间】:2020-09-03 21:41:43
【问题描述】:
我尝试创建一个表“MyTable”并添加一个小 int 类型的字段“field1”。
然后我将负数 -12289 添加到 field1。
然后我执行下面的 SQL 查询:
select field1 ^ 0xcfff from MyTable
结果为零。
但是如果我将十六进制整数常量替换为十进制整数常量,如下:
select field1 ^ 53247 from MyTable
结果是-65536。
为什么?
大于 2,147,483,647 的整数常量被转换为十进制数据类型,而不是 bigint 数据类型。
但是 0xcfff 和 53247 都比 2,147,483,647 小得多。为什么它们会产生不同的结果?
更新:
据我了解,这个问题的关键是我们可以将 0xcfff 转换为 small int,如下所示:
select cast(0xcfff as smallint)
但我们不能将 53247 转换为 small int,以下行会导致溢出:
select cast(53247 as smallint)
这与 C/C++ 不同。在 C/C++ 中,两种转换都可以。
【问题讨论】:
-
您正在处理不同的数据类型并看到由于类型转换而导致的问题。
0xcfff不是十六进制常量 - 它是binary(2)值。smallint数据类型的范围是 -32768 到 32767,因此当0xcfff转换为smallint时,其十进制等效值为-12289... 和-12289 ^ -12289 = 0。值53247超出smallint范围,因此至少转换为int,这导致field1也转换为int以进行异或运算。将field1和53247都转换为int 后,异或结果为-65536。 -
@AlwaysLearning,为什么 0xcfff 作为 binary(2) 将被转换为 smallint(-12289),而不是 int,而 53247 将被转换为 int,而不是 smallint(-12289) 当另一个运算符是smallint?
-
因为
smallint是有符号的16 位值,而0xcfff是两个字节(16 位)。53247不能表示为带符号的 16 位值,因此被强制转换为带符号的 32 位 int。 -
SQL Server 没有无符号数据类型 - 也许这就是您遗漏的线索?
-
@AlwaysLearning,我知道 SQL Server 没有无符号数据类型,但最初认为它支持将 53247 转换为 smallint,就像 C++ 一样。但事实并非如此。请参阅我对帖子的“更新”。
标签: sql-server int hex decimal xor