3 sql-server type-conversion sql-server-2014
按照我之前的问题:隐式转换不会影响性能
我使用了下面的简单查询
select count(*)
from fpc
where SKey in ('201701', '201702A')
Run Code Online (Sandbox Code Playgroud)
SKey 是 int 类型,我在它上面有非聚集列存储索引。
显然我无法运行它,因为第二个值不是数字。所以我按 Ctrl+L 来查看估计的执行计划,我在Predicate
属性中看到了一个有趣的事情:
[mydb].[dbo].[fpc].[SKey]=CONVERT_IMPLICIT(int,'201702A',0) OR
[mydb].[dbo].[fpc].[SKey]=(201701)
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么 SQL 使用“201701”作为数字,但对第二个值使用隐式转换:“201702A”
我感兴趣的是 SQL 服务器如何查看这两个值的内部机制。它知道第一个是数字而第二个不是吗?
Pau*_*ite 10
我的问题是为什么 SQL 使用“201701”作为数字,但对第二个值使用隐式转换:“201702A”
我感兴趣的是 SQL 服务器如何查看这两个值的内部机制。它知道第一个是数字而第二个不是吗?
SQL Server 尝试将两个字符串转换为正确的类型(根据数据类型优先规则),以便Skey
在查询编译的常量折叠阶段与整数列进行比较。此活动发生在流程的早期,甚至在考虑最简单的查询计划之前就发生了。
当常量折叠成功时,输入树包含派生的文字值(作为正确的类型)并继续优化,就像查询编写者使用了常量而不是表达式一样。
当常量折叠不成功时(例如因为转换会抛出错误),树包含一个转换函数。在编译时抛出错误是不正确的;只有在执行查询时才会发生错误,并且实际评估有问题的表达式(如果有的话)。
因此,在您的情况下,'201701' 被常量折叠为整数 201701,但 '201702A' 变为CONVERT_IMPLICIT(int,'201702A',0)
.
常量折叠比上面的简单示例所暗示的更强大和更完整。例如:
LastName LIKE SUBSTRING(LEFT(NCHAR(UNICODE(NCHAR(68))), 1) + N'%', 1, 2)
Run Code Online (Sandbox Code Playgroud)
被常数折叠为:
LastName LIKE N'D%'
Run Code Online (Sandbox Code Playgroud)
在 SQL Server 2012 及更高版本中,即使是确定性 SQLCLR 标量函数也可以进行常量折叠。