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

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

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

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

        http://www.cnblogs.com/shanksgao/p/4254942.html 高兄这篇文章很好的谈论了由于数据隐式转换造成执行计划不准确,从而造成了死锁.那如果在事情出现之前 ...

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

    在SQL Server中的数据类型中,存在着优先级的问题.标量表达示的返回结果类型也会根据操作数的类型而定,如1 +'1'=2.而不是'11',因些Int型的优先级比VARCHAR型的优先级要高.所以 ...

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

    JavaScript数据类型隐式转换.一,函数类    isNaN()    该函数会对参数进行隐式的Number()转换,如果转换不成功则返回true.    alert()    输出的内容隐式的 ...

  4. js数据类型隐式转换问题

    js数据类型隐式转换 ![] == false //true 空数组和基本类型转换,会先[].toString() 再继续比较 ![] == [] //true ![] //false [] == [ ...

  5. js中的数据类型隐式转换的三种情况

    js的数据类型隐式转换主要分为三种情况: 1. 转换为boolean类型 2. 转换为number类型 3. 转换为string类型 转换为boolean类型 数据在 逻辑判断 和 逻辑运算 之中会隐 ...

  6. Oracle数据类型隐式转换小析

    测试使用环境:oracle 11g r1 平常写sql语句时,大大咧咧,不太注意和数字有关的数据类型,有时例如 where c1=111 和 where c1='111'这样混用,却不曾想这里面另有蹊 ...

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

    之前有用户很不解:SQL语句非常简单,就是select * from test_1 where user_id=1 这种类型,而且user_id上已经建立索引了,怎么还是查询很慢? test_1的表结 ...

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

    我们都知道,一条SQL语句提交给优化器会产生相应的执行计划然后执行输出结果,但他的执行计划是如何产生的呢?这可能是关系型数据库最复杂的部分了.这里我为大家介绍一个有关SQL Server优化器的特性- ...

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

    公用方法: let checkType = (data) => { if(data){ console.log(true); }else{ console.log(false); } } 一.字 ...

随机推荐

  1. Electron中使用sql.js操作SQLite数据库

    推荐sql.js——一款纯js的sqlite工具. 一.关于sql.js sql.js(https://github.com/kripken/sql.js)通过使用Emscripten编译SQLite ...

  2. python-基础-isinstance(p_object, class_or_type_or_tuple)

    1.isinstance(p_object, class_or_type_or_tuple) p_object:实例 class_or_type_or_tuple:类型,可以是一个类型或者是组成的元组 ...

  3. 研究STM32F4的IEEE1558 PTP网络时间同步协议实现,软件是RL-TCPnet V7.X的底层

    这个东西发现挺有意思,刚开始研究没整明白怎么用,实测设置一次时间戳就可以使用了,后面在深入研究下 extern ARM_DRIVER_ETH_MAC Driver_ETH_MAC0; ARM_ETH_ ...

  4. 05-深入python的set和dict

    一.深入python的set和dict 1.1.dict的abc继承关系 from collections.abc import Mapping,MutableMapping #dict属于mappi ...

  5. C# -- Quartz.Net入门案例

    1. 入门案例 using Quartz;using Quartz.Impl; public class PrintTime : IJob { public Task Execute(IJobExec ...

  6. Nginx的安装及配置

    1.概述         Nginx是开源免费的一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.其特点是占有内存少,并发能力强,使用nginx网站用户有很多,如百 ...

  7. Test111

    这是一个测试 以下是截图 以下是代码标记       @@@code [XmlRpcMethod("blogger.deletePost")] haaa ggg @@# publi ...

  8. Hive 时间函数总结【转】

    1.日期函数UNIX时间戳转日期函数: from_unixtime语法:from_unixtime(bigint unixtime[, stringformat]) 返回值: string说明: 转化 ...

  9. C#&.Net干货分享- 构建Spire-Office相关Helper操作Word、Excel、PDF等

    先下载好如下的组件: 直接使用完整源码分享: namespace Frame.Office{    /// <summary>    /// Spire_WordHelper    /// ...

  10. VS 2017 中取消自动补全花括号

    输入 "{", VS 会很智能的给你补全,得到 “{}”, 如果不想享受这个服务,可以按以下设置取消: Tools -> Options -> Text Editor ...