SQL Server有意思的数据类型隐式转换问题

写这篇文章的时候,还真不知道如何取名,也不知道这个该如何将其归类。这个是同事遇到的一个案例,案例比较复杂,这里抽丝剥茧,仅仅构造一个简单的案例来展现一下这个问题。我们先构造测试数据,如下所示:

CREATE TABLE TEST
( 

  ID    INT, 

  GOOD_TYPE  VARCHAR(12),

  GOOD_WEIGHT NUMERIC(18,2)

)

 

INSERT INTO dbo.TEST

VALUES( 1, ‘T1‘,1.27) 

SELECT  GOOD_TYPE,

        CASE WHEN ( GOOD_TYPE = ‘T1‘ ) THEN 99.1 + SUM(GOOD_WEIGHT)

             ELSE CEILING(SUM(GOOD_WEIGHT))

        END AS GrossWeight ,

        SUM(GOOD_WEIGHT) AS NetWeight

FROM    dbo.TEST

GROUP BY GOOD_TYPE;

如上所示,为什么99.1 + SUM(GOOD_WEIGHT)变成100了呢? 原始SQL非常复杂,我们分析、排除掉各个因素后,始终不得要领,各种折腾中发现,如果这样转换一下(请见下面截图),居然就OK了,后面分析了一下,应该是CASE WHEN里面的不同数据类型导致隐式转换,说实话之前还真没有留意CASE WHEN中存在数据类型的隐性转换,但是为什么就一定从NUMERIC转换为INT了呢? 而不是INT隐性转换为NUMERIC呢, 说实话没有看到相关文档的官方,如果按照官方文档:

当两个不同数据类型的表达式用运算符组合后,优先级较低的数据类型首先转换为优先级较高的数据类型。 如果此转换不是所支持的隐式转换,则返回错误。 对于组合具有相同数据类型的操作数表达式的运算符时,运算的结果便为该数据类型

而我们知道,Decimal 和 NUMERIC 是同义词,可互换使用,而官方文档“数据类型优先级 (Transact-SQL)”中,Decimal的优先级明显高于INT,如果真要按照原理来解释,应该是INT转换NUMERIC才对(两种数据类型支持隐式转换),所以越想越糊涂,只知道有这么一回事,但是真正的Root Cause尚不清楚,而且在精确度要求较高的报表中,这种现象就会类似Bug一样的突然出现。需要谨慎留心!

 

参考资料:

https://docs.microsoft.com/zh-cn/sql/t-sql/data-types/data-type-precedence-transact-sql?view=sql-server-2017

https://docs.microsoft.com/zh-cn/sql/t-sql/data-types/data-type-conversion-database-engine?view=sql-server-2017

原文地址:https://www.cnblogs.com/kerrycode/p/11421484.html

时间: 2024-10-07 02:36:51

SQL Server有意思的数据类型隐式转换问题的相关文章

【转】SQL SERVER标量表达式的隐式转换

在SQL Server中的数据类型中,存在着优先级的问题.标量表达示的返回结果类型也会根据操作数的类型而定,如1 +'1'=2.而不是'11',因些Int型的优先级比VARCHAR型的优先级要高.所以在表达示的结果隐式转换成Int型. 同样对于标量函数,如一个表的一列是Int型,表中有两行值为2和3如果对这一列使用AVG函数,则结果是2,而不是2.5.但是如果这一列是Decimal类型的话,那么结果就是2.5.因为结果类型依据操作数据类型. 如下的一个Case语名 CASE WHEN <logi

SQL Server中提前找到隐式转换提升性能的办法

    http://www.cnblogs.com/shanksgao/p/4254942.html 高兄这篇文章很好的谈论了由于数据隐式转换造成执行计划不准确,从而造成了死锁.那如果在事情出现之前发现了这类潜在的风险岂不是更好?     那么我们来看一个简单的例子,如代码清单1所示.   1: SELECT * 2: FROM HumanResources.Employee 3: WHERE NationalIDNumber = 243322160 4:  5: SELECT * 6: FR

SQL Server优化器特性-隐式谓词

原文:SQL Server优化器特性-隐式谓词 我们都知道,一条SQL语句提交给优化器会产生相应的执行计划然后执行输出结果,但他的执行计划是如何产生的呢?这可能是关系型数据库最复杂的部分了.这里我为大家介绍一个有关SQL Server优化器的特性-隐式谓词,并简单介绍在此特性下如何根据场景控制优化器的行为. 在这里我通过一个简单的实例来给大家说明下. code CREATE TABLE T1 (A INT, B INT) CREATE TABLE T2 (A INT, B INT) set sh

JavaScript复习之--javascript数据类型隐式转换

JavaScript数据类型隐式转换.一,函数类    isNaN()    该函数会对参数进行隐式的Number()转换,如果转换不成功则返回true.    alert()    输出的内容隐式的转换为字符串. 二,运算符类.    1,算术运算符.       - * / %    如果操作数不是数值,将会隐式的调用Number()函数.按照这个函数的转换规则进行转换.    如果转换不成功,整个表达式返回NaN.       +     如果操作数都是数值,然后进行相加.    任何数据

javascript数据类型隐式转换

一.函数类 isNaN() 该函数会对参数进行隐式的Number()转换,如果转换不成功则返回true; alert() 输出的内容隐式的转换为字符串 二.运算符类 1.算数运算符 -  *   /  % 如果操作数不是数值,将会隐式的调用Number()函数,按照这个函数的转换规则进行转换,如果转换不成功,整个表达式返回NaN + 如果操作数都是数值,然后进行相加 任何数据类型和字符串相加,都会隐私的调用他们的toString()方法,然后返回他们拼接的结果. 如果操作数都是布尔值,那么进行N

MySQL SQL优化之字符串索引隐式转换

之前有用户很不解:SQL语句非常简单,就是select * from test_1 where user_id=1 这种类型,而且user_id上已经建立索引了,怎么还是查询很慢? test_1的表结构: CREATE TABLE `test_1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` varchar(30) NOT NULL, `name` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`),

js数据类型隐式转换笔记以及js包装对象

“37”+7              //377 “37”-7              //30 巧用+/-规则  变字符串  x+''   变数字x-0 js里面的==是不严格等于 “123” == 123 0 == false nul l== undefined new  Object() == new Object() [1,2]==[1,2] 但是[1,2]===[1,2]是错的 因为比较的是对象的引用 ps: NaN值和任何东西比较都不相等 即便是不严格等于 ———————————

SQL执行异常系列之——隐式转换

SQL> select object_id,CREATED from dba_objects where rownum < 10; OBJECT_ID CREATED ---------- ------------------ 20 25-JUL-18 46 25-JUL-18 28 25-JUL-18 15 25-JUL-18 29 25-JUL-18 3 25-JUL-18 25 25-JUL-18 41 25-JUL-18 54 25-JUL-18 9 rows selected. se

JavaScript —— 常用数据类型隐式转换

公用方法: let checkType = (data) => { if(data){ console.log(true); }else{ console.log(false); } } 一.字符串 checkType('hello~'); // true checkType(''); // false 总结: 空字符串会被转换为 false,非空字符串会被转换为 true. 二.数值 checkType(10); // true checkType(10.5); // true checkTy