sql sql-server tsql operator-precedence

Un problema de operación extraño en SQL Server(-100/-100*10=0



sql-server tsql (3)

  • Si ejecuta SELECT -100/-100*10 el resultado es 0 .
  • Si ejecuta SELECT (-100/-100)*10 el resultado es 10 .
  • Si ejecuta SELECT -100/(-100*10) el resultado es 0 .
  • Si ejecuta SELECT 100/100*10 el resultado es 10 .

BOL estados:

Cuando dos operadores en una expresión tienen el mismo nivel de precedencia de operadores, se evalúan de izquierda a derecha según su posición en la expresión.

Y

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

¿Está BOL equivocado, o me estoy perdiendo algo? Parece que el - está desechando la precedencia (esperada).


BOL es correcto. - tiene menor precedencia que * , entonces

-A * B

se analiza como

-(A * B)

Dado que la multiplicación es lo que es, normalmente no se nota esto, excepto cuando se mezclan en los otros dos operadores binarios con igual precedencia: / y % (y % rara vez se usa en expresiones compuestas como esta). Asi que

C / -A * B

Se analiza como

C / -(A * B)

Explicando los resultados. Esto es contraintuitivo porque en la mayoría de los otros idiomas, el menos unario tiene una prioridad más alta que * y / , pero no en T-SQL, y esto está documentado correctamente.

Una buena manera de ilustrarlo:

SELECT -1073741824 * 2

produce un desbordamiento aritmético, porque -(1073741824 * 2) produce 2147483648 como intermedio, que no cabe en un INT , pero

SELECT (-1073741824) * 2

produce el resultado esperado -2147483648 , que lo hace.


De acuerdo con la tabla de precedencia, este es el comportamiento esperado. El operador con mayor prioridad ( / y * ) se evalúa antes que el operador con menor prioridad (unario - ). Así que esto:

-100 / -100 * 10

se evalúa como:

-(100 / -(100 * 10))

Tenga en cuenta que este comportamiento es diferente de la mayoría de los lenguajes de programación donde la negación unaria tiene mayor prioridad que la multiplicación y la división, por ejemplo, VB , JavaScript .


Observe en la documentación que (tal vez en forma contraria a la intuición) el orden de precedencia para - (Negative) es tercero.

Así que efectivamente obtienes:

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

Si los coloca en variables, no verá que esto suceda, ya que no hay una operación única que ocurra después de la multiplicación.

Así que aquí A y B son iguales, mientras que C, D, E muestran el resultado que está viendo (con E el corchete completo)

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