SQL Server中一个奇怪的操作问题:-100 / -100 * 10 = 0

问题描述 投票:101回答:3
  • 如果执行SELECT -100/-100*10,结果为0
  • 如果执行SELECT (-100/-100)*10,结果为10
  • 如果执行SELECT -100/(-100*10),结果为0
  • 如果执行SELECT 100/100*10,结果为10

BOL状态:

[当表达式中的两个运算符具有相同的运算符优先级时,将根据它们在表达式中的位置从左到右进行评估。

Level   Operators
  1     ~ (Bitwise NOT)
  2     * (Multiplication), / (Division), % (Modulus)
  3     + (Positive), - (Negative), + (Addition), + (Concatenation), - (Subtraction), & (Bitwise AND), ^ (Bitwise Exclusive OR), | (Bitwise OR)

BOL是错误的,还是我缺少什么?似乎-正在放弃(预期的)优先顺序。

sql sql-server tsql operator-precedence
3个回答
90
投票

根据优先级表,此预期的行为。优先级较高的运算符(/*)先于优先级较低的运算符(一元-)进行评估。所以这个:

-100 / -100 * 10

评估为:

-(100 / -(100 * 10))

请注意,这种行为与大多数编程语言不同,在大多数编程语言中,一元求反的优先级高于乘法和除法,例如VBJavaScript


33
投票

BOL是正确的。 -的优先级低于*,因此

-A * B

解析为

-(A * B)

乘法就是它,除了在其他两个具有相同优先级的二元运算符混合时,您通常不会注意到这一点:/%%在这样的复合表达式中很少使用) 。所以

C / -A * B

解析为

C / -(A * B)

解释结果。这是违反直觉的,因为在大多数其他语言中,一元减号的优先级高于*/,但在T-SQL中则没有,并且已被正确记录。]

一种说明它的好方法(?):

SELECT -1073741824 * 2

[产生算术溢出,因为-(1073741824 * 2)产生2147483648作为中间体,但不适合INT,但是

SELECT (-1073741824) * 2

产生期望的结果-2147483648,]。>

文档中的通知(可能是违反直觉的)- (Negative)的优先级为第三。

所以您有效地获得了:

-(100/-(100*10)) = 0

如果将它们放入变量中,您将不会看到这种情况,因为乘法之后不会发生一元运算。

因此,A和B相同,而C,D,E显示了您看到的结果(E带有完整的包围)

DECLARE @i1 int, @i2 int, @i3 int;

SELECT @i1 = -100,
       @i2 = -100,
       @i3 = 10;

SELECT @i1/@i2*@i3      [A],
       -100/(-100)*10   [B],
       -100/-100*10     [C],
       -100/-(100*10)   [D],
       -(100/-(100*10)) [E];

A - 10
B - 10
C - 0
D - 0
E - 0

11
投票

文档中的通知(可能是违反直觉的)- (Negative)的优先级为第三。

© www.soinside.com 2019 - 2024. All rights reserved.