关于隐式转换

      昨天,一个读者向我提交了一个问题,请我就SQL server 隐式转换发表一些看法。当SQL server遇到一个不匹配类型的表达式的时候,它有两种选择。它使用隐式转换并能够执行或者转换错误而导致执行失败。在深入隐式转换之前,让我们假定错误的情形。

      如果一个隐式转换不可能实现,SQL server可能产生两种可能的错误。如果两种数据类型不能完全兼容(简言之,在两种数据类型之间不能实现隐式或显式转换),SQL server产生下列错误:

DECLARE   @a INT
DECLARE   @b DATE
SET           @a = @b

--Msg 206, Level 16, State 2, Line 3
--Operand type clash: date is incompatible with int
   对于这种情形尝试做一个修正,发生了下列错误:
DECLARE @a INT
DECLARE @b DATE
SET @a = CONVERT(INT,@b)

--Msg 529, Level 16, State 2, Line 3
--Explicit conversion from data type date to int is not allowed.

      另一方面,如果两种数据类型是兼容的,仅仅需要一个显示转换,SQL server产生下列错误:

 

DECLARE @a
INT
DECLARE @b
DATETIME
SET @a = @b

--Msg 257, Level 16, State 3, Line 3
--Implicit conversion from data type datetime to int is not allowed. Use the CONVERT function to run this query.

      通过使用显示convert来解决这个问题:

DECLARE @a
INT
DECLARE @b
DATETIME
SET @a =
CONVERT (INT ,@b)

      联接丛书页面中涵盖了一个兼容性矩阵,描述了SQL server如何处理数据类型转换的所有可能性。如果SQL server使用一个隐式转换到一个表达式,它必须选择其中的一个表达式以及一种目标数据类型来实现转换。基本上, 有三种比较表达式选项:

1->转换右边表达式到左边表达式的数据类型

2->转换左边表达式到右边表达式的数据类型

3->将两者转换到第三方数据类型

      对于指定的转换,它明确的将右边表达式转换到左边表达式的数据类型。假定不允许这种类型的转换,则指定的转换将失败。下述转换将没有意义:

DECLARE @a INT
DECLARE @b DATETIME
SET CONVERT(DATETIME,@a) = @b

--Msg 156, Level 15, State 1, Line 3
--Incorrect syntax near the keyword 'convert'.

      实际隐式转换中,SQL server选择一到两种选项中的一个。对于特定的,SQL server将对所有的数据类型分类排列并且从优先级低的向优先级高的数据类型转换。例如,由于整型的优先级低于日期类型,下列查询语句将转换整型变量到日期型:

DECLARE @a INT
DECLARE @b DATETIME
SELECT 0 WHERE @a = @b

|--Compute Scalar(DEFINE:([Expr1000]=(0)))
   |--Filter(WHERE:(STARTUP EXPR(CONVERT_IMPLICIT(datetime,[@a],0)=[@b])))
            |—Constant Scan

      这种方法有一些缺陷。需要特别指出的是,一些转换是无损转换,一些是有损转换,而一些则出现转换失败。举例来说,转换一个SMALLINT到INT类型则是一个无损转换。对于这个SAMLLINT值的集合能够被一个作为父集的INT值集来表达。然而转换一个INT到REAL型是有损转换。大多数的INT值不能被一个REAL所表达。

   DECLARE @a INT
    DECLARE @b REAL
    DECLARE @c INT
    SET @a = 1000000001
    SET @b = CONVERT(REAL,@a)
    SET @c = CONVERT(INT,@b)
    SELECT @a, @b, @c

a                    b             c
-------------------- ------------- --------------------
1000000001           1E+09         1000000000

      转换一个REAL型到INT整型是一个有损转换(一个整型不能够表示小数部分)而且转换彻底失败:

   DECLARE @a REAL
    DECLARE @b INT
    SET @a = 1e13
    SET @b = CONVERT(INT,@a)

Msg 232, Level
 16, State 3, Line 4

Arithmetic overflow error for type int, value = 9999999827968.000000.

      SQL server使用类型的优先级别试图最小化有损转换的风险或转换失败,但有时候数据丢失或失败是不可避免的,就像上面的实型REAL转为INT整型的例子。

      在STRING字符串和NUMERIC数据类型之间的转换(如CHAR或VARCHAR)也是有些疑问。SQL server STRING字符型级别低于NUMERIC数据类型,而且转换的时候STRING字符型总是转换为NUMERIC型。这个转换很容易失败。显然地,有一些包含非NUMERIC的数据不能够被转换为字符型。然而,对这两种类型,反向转换则是更糟糕。有一些方法可以表示一个NUMERIC型作为一个STRING型。下述所有的STRING字符型代表了相同的数字:'1', '˽1', '1˽ ',
'+1', '1.0', 和'01'.(其中˽代表空格) 。SQL server 转换STRING到NUMERIC是能够确定地选择一种公认的格式,而不去转换那些特殊的STRING到NUMERIC。没有更容易的方式去比较那些并没有公认格式的STRING到NUMERIC类型的转换。举个例子,考虑下面的对比结果:

DECLARE @a INT
DECLARE @b CHAR(4)
SET @a = 1SET @b = @a
SELECT @a AS a, @b AS b,
    CASE WHEN   @a = '1 '  THEN 'True' ELSE 'False' END AS [a = '1'],
    CASE WHEN   @a = '+1' THEN 'True' ELSE 'False' END AS [a = '+1'],
    CASE WHEN   @b = '1'   THEN 'True' ELSE 'False' END AS [b = '1'],
    CASE WHEN   @b = '+1' THEN 'True' ELSE 'False' END AS [b = '+1']

a           b    a = '1 '   a = '+1 '   b = '1'    b = '+1'

----------- ---- ------- -------- ------- --------
1           1    True    True     True    False

    注意:上例中当作为一个整型的时候,1=+1,但是做为字符串的时候,'1' <> '+1'。

    从上述的三种隐式转换的例子可知,SQL server隐式转换并不会转换两者的数据类型到第三方数据类型。在一些场景中,对于有损转换,转换两者的数据类型到一个超级类型是有可能的。但是目前没有这样的超级类型存在。(至少在目前的SQL版本中)。

    有时,这些转换规则并不是非常方便或比较离奇。现实中,它们演变了多年(甚至数十年)并且基于这些推断,一些应用程序已经被开发。现在如果做一个调整将一定会导致一些已经存在的应用程序的失败。

    总的来说,无论什么场景的可能性,新的代码中应避免使用不匹配的数据类型,或避免上述那些离奇的错误来最大化提高性能。

Published Wednesday, January 20, 2010 11:56 AM by craigfr

Filed under: Conversions

原文博客地址:http://blogs.msdn.com/craigfr/archive/2010/01/20/more-on-implicit-conversions.aspx

 

 

 

时间: 2024-09-19 07:33:39

关于隐式转换的相关文章

第3课 隐式转换

1)val array=Array(1,2,3,4,5); array.map(item => 2*item);map的作用是循环遍历array中的每一个元素,并把每个元素做为具体的值传给map中的做为参数的函数.map执行结果为Array[Int] =Array(2,4,6,8,10);函数的参数也是函数,item时匿名函数,这个也是高阶函数 2)高阶函数的返回值也可能是函数.高阶函数的参数是函数,这是高阶函数的2个层面.高阶函数可以自动推断出函数参数的类型.而且对只有一个参数的函数,可以省略

JavaScript的隐式转换

JavaScript的数据类型分为六种,分别为null,undefined,boolean,string,number,object.object是引用类型,其它的五种是基本类型或者是原始类型.我们可以用typeof方法打印来某个是属于哪个类型的.不同类型的变量比较要先转类型,叫做类型转换,类型转换也叫隐式转换.隐式转换通常发生在运算符加减乘除,等于,还有小于,大于等.. typeof '11'  //string       typeof(11) //number '11' < 4     /

Oracle隐式转换会影响物化视图查询重写

今天有人问我一个物化视图查询重写的问题,最后发现问题其实和物化视图的功能没有多大的关系,而是隐式转换导致的问题. 还是通过例子来说明这个问题: SQL> create table t ( 2  id number, 3  time date, 4  other varchar2(4000)) 5  partition by range (time) 6  (partition p1 values less than (to_date('2008-1-1', 'yyyy-mm-dd')), 7  

struct-c# 在一个实现了隐式转换的结构体进行强制类型转换时报错

问题描述 c# 在一个实现了隐式转换的结构体进行强制类型转换时报错 50C 如题,我有一个结构体,类似这样: public struct AInt{ private int _a; public int ToInt() { reurn _a; } public static implicit operator int(AInt value) { return value.ToInt(); } public static implicit operator AInt(int value) { _a

RDS SQL Server - 专题分享 - 巧用执行计划缓存之数据类型隐式转换

摘要 SQL Server数据库基表数据类型隐式转换,会导致Index Scan或者Clustered Index Scan的问题,这篇文章分享如何巧用执行计划缓存来发现数据类型隐式转换的查询语句,从而可以有针对性的优化查询,解决高CPU使用率的问题. 问题引入 测试环境 为了更好的展示从执行计划缓存缓存中找出导致数据类型转化的查询语句,我们先建立测试环境. -- Create testing database IF DB_ID('TestDb') IS NULL CREATE DATABASE

Scalaz(1)- 基础篇:隐式转换解析策略-Implicit resolution

  在正式进入scalaz讨论前我们需要理顺一些基础的scalaz结构组成概念和技巧.scalaz是由即兴多态(ad-hoc polymorphism)类型(typeclass)组成.scalaz typeclass在scala中的应用有赖于scala compiler的一项特别功能:隐式转换(implicit conversion),使程序表述更精简.由于隐式转换是一项compiler功能,在程序编译(compile)的时候是由compiler来进行类型转换代码的产生和替代的.   让我们先了

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

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

ORACLE绑定变量隐式转换导致性能问题

   年后一次系统升级后,监控数据库的工具DPA发现数据库的Total Wait时间突然飙增,如下截图所示,数据库的总体等待时间对比升级前飙增了非常多 另 外就是发现出现了较多的等待事件,主要有latch: cache buffers chains. latch: shared pool .db file scattered read.根据这边的监控发现TOP SQL里面从升级前的0次变为了一天的一万多次(有些甚至更多),分析过后我们就找开发人员了解一下系统升级变跟的内容和改动 开 发人员坚定的

Scala入门到精通——第十九节 隐式转换与隐式参数(二)

作者:摇摆少年梦 配套视频地址:http://www.xuetuwuyou.com/course/12 本节主要内容 隐式参数中的隐式转换 函数中隐式参数使用概要 隐式转换问题梳理 1. 隐式参数中的隐式转换 前一讲中,我们提到函数中如果存在隐式参数,在使用该函数的时候如果不给定对应的参数,则编译器会自动帮我们搜索相应的隐式值,并将该隐式值作为函数的参数,这里面其实没有涉及到隐式转换,本节将演示如何利用隐式参数进行隐式转换,下面的代码给定的是一个普通的比较函数: object ImplicitP

Scala入门到精通——第十八节 隐式转换与隐式参数(一)

本节主要内容 隐式转换简介 隐式转换函数 隐式转换规则 隐式参数 1. 隐式转换简介 在scala语言当中,隐式转换是一项强大的程序语言功能,它不仅能够简化程序设计,也能够使程序具有很强的灵活性.要想更进一步地掌握scala语言,了解其隐式转换的作用与原理是很有必要的,否则很难得以应手地处理日常开发中的问题. 在scala语言中,隐式转换是无处不在的,只不过scala语言为我们隐藏了相应的细节,例如scala中的类继承层次结构中: 它们存在固有的隐式转换,不需要人工进行干预,例如Float在必要