Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A strange operation problem in SQL Server: -100/-100*10 = 0

  • If you execute SELECT -100/-100*10 the result is 0.
  • If you execute SELECT (-100/-100)*10 the result is 10.
  • If you execute SELECT -100/(-100*10) the result is 0.
  • If you execute SELECT 100/100*10 the result is 10.

BOL states:

When two operators in an expression have the same operator precedence level, they are evaluated left to right based on their position in the expression.

And

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

Is BOL wrong, or am I missing something? It seems the - is throwing the (expected) precedence off.

like image 627
cuizizhe Avatar asked Feb 04 '19 09:02

cuizizhe


People also ask

Is SQL_Latin1_General_CP1_CI_AS the same as Latin1_General_CI_AS?

The SQL_Latin1_General_CP1_CI_AS collation is a SQL collation and the rules around sorting data for unicode and non-unicode data are different. The Latin1_General_CI_AS collation is a Windows collation and the rules around sorting unicode and non-unicode data are the same.

How do you handle special characters in SQL?

Use braces to escape a string of characters or symbols. Everything within a set of braces in considered part of the escape sequence. When you use braces to escape a single character, the escaped character becomes a separate token in the query. Use the backslash character to escape a single character or symbol.

What is SQL_Latin1_General_CP1_CI_AS?

Default server-level collation is SQL_Latin1_General_CP1_CI_AS. If you are migrating databases from SQL Server to Managed Instance, check the server collation in the source SQL Server using SERVERPROPERTY(N'Collation') function and create a Managed Instance that matches the collation of your SQL Server.


2 Answers

According to the precedence table, this is the expected behavior. The operator with higher precedence (/ and *) is evaluated before operator with lower precedence (unary -). So this:

-100 / -100 * 10 

is evaluated as:

-(100 / -(100 * 10)) 

Note that this behavior is different from most programming languages where unary negation has higher precedence than multiplication and division e.g. VB, JavaScript.

like image 136
Salman A Avatar answered Nov 07 '22 14:11

Salman A


BOL is correct. - has lower precedence than *, so

-A * B 

is parsed as

-(A * B) 

Multiplication being what it is, you don't typically notice this, except when mixing in the two other binary operators with equal precedence: / and % (and % is rarely used in compound expressions like this). So

C / -A * B 

Is parsed as

C / -(A * B) 

explaining the results. This is counter-intuitive because in most other languages, unary minus has higher precedence than * and /, but not in T-SQL, and this is documented correctly.

A nice (?) way to illustrate it:

SELECT -1073741824 * 2 

produces an arithmetic overflow, because -(1073741824 * 2) produces 2147483648 as an intermediate, which does not fit in an INT, but

SELECT (-1073741824) * 2 

produces the expected result -2147483648, which does.

like image 43
Jeroen Mostert Avatar answered Nov 07 '22 12:11

Jeroen Mostert