简体   繁体   中英

SQL Server compatibility creates issue

We have changed the SQL Server compatibility from 100 to 130 the below code in our stored procedure behaves differently:

DECLARE @i decimal(4, 0) = 1,
        @j decimal(4, 1) = 0.5

SELECT SUM(@i) - SUM(@j)

Result of the select:

  • Compatibility Level 100: 0
  • Compatibility Level 130: 1

We are not sure how many calculation we have in our code like this.

Is there any setting in the SQL Server database we can make to work same as compatibility level 100?

Let's try to use suitable data types: https://stackoverflow.com/a/7158770/5309660

DECLARE @i decimal(4, 0) = 1,
        @j decimal(4, 1) = 0.5

SELECT CAST(SUM(@i) AS REAL) - CAST(SUM(@j) AS REAL)

In previous versions of SQL Server, the "scale" of the result was not following the rules. This was corrected in a later version (I don't remember which version changed).

No, there is no way to change it back.

https://learn.microsoft.com/en-us/sql/t-sql/data-types/precision-scale-and-length-transact-sql?view=sql-server-ver16

To simplify things a bit the gist of the issue is that Compatibility Level 120

DECLARE @A decimal(38,0) = 1, 
        @B decimal(38,1) = 0.5

SELECT @A - @B /*Returns 0*/

Compatibility Level 130

DECLARE @A decimal(38,0) = 1, 
        @B decimal(38,1) = 0.5

SELECT @A - @B /*Returns 1*/

The datatype of the result is decimal(38,0) in both cases.

Your question is not asking how to get the mathematically correct result of 0.5 . You are just asking how to get the compat 120 behaviour.

You can't without setting that compatibility level I'm afraid.

Note in both compat levels

SELECT CONVERT(decimal(38,0), 0.5) 

Returns 1 so this should really be the "expected" result in both cases.

In the 100 case I assume what it actually does is convert the operand first . ie as below

SELECT @A - CONVERT(decimal(38,0), @B)

I think the only time it will make a difference in this case is when one of the operands has decimal .5 and you are subtracting it. If @B is 0.6 for example it makes no odds if this gets rounded up to the closest integer before the subtraction or the result of the subtraction is rounded down to the closest integer after it.

The SQL Server 2016 breaking changes does call out

Under database compatibility level 130, operations that perform implicit conversions between certain numeric and datetime data types show improved accuracy and can result in different converted values.

Although it doesn't explicitly mention this case when clicking through .

Is there any setting in the SQL Server database we can make to work same as compatibility level 100?

Only by setting the compatibility level. It is exactly this sort of thing that the compatibility level mechanism is for (to give you time to identify and adjust any affected code)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM