经过测试发现,如果update语句中新的值和原值相同,则不会做更新操作,问题是,SQL Serve判断新值和原值相同的机制是什么?

解决方案 »

  1.   

    update tb set col=@var where col!=@var
      

  2.   

    这个不难理解,scan时比较值就行了。
      

  3.   


    可是用update()测试还是true
      

  4.   

    1. UPDATE() 返回一个布尔值,指示是否对表或视图的指定列进行了 INSERT 或 UPDATE 尝试。UPDATE() 返回 TRUE,不考虑 INSERT 或 UPDATE 尝试是否成功。2. 如果一条被更新的记录的原值与要更新的值相同,即更新操作的前值与后值相同,则该更新操作不会记入日志,当事务提交时也不会写到磁盘中数据页中。换言之,只有数据发生变化,操作才会写入记录到日志文件并修改到数据页。(归纳出的结论,未找到明确的文档依据)3. 如果被修改的字段不是聚集索引键,或者是聚集索引键但修改后的记录不改变在聚集索引中的位置,则更新数据页的操作是覆盖更新,且只修改相关字段的对应字节;如果该字段是聚焦索引键,并且修改后的记录需要改变记录在聚集索引中的位置,则会删除原记录再添加新记录到新的位置。4. 只有数据发生变化,执行该操作的事务才会申请排他锁,并且默认是行级锁,当更新的记录数比较多的时候也可能是页级锁或表级锁。
      

  5.   

    又做了一次测试,发现如果表中有TimeStamp字段,则该字段依然会被自动更新,数据库日志中会记录改更新操作。
    如有一条记录
    ID Name TS
    1  ‘A'   0000ABCDUpdate T
    set Name=’A'
    where ID=1执行后TS可能会变为0000CDEF同时数据库日志会记录该更新操作
      

  6.   

    我个人感觉,不论值等或不等,Updated里的set赋值是无论如何都要执行的,有新的log生成就是最好证明。
    至于内部机制而言,
    1,对update语句做先初步编译,判断语句有没有语法错误,做语法分解
    2,深入编译检查索引或约束,设定涉及的字段,以作备用(Update简单分解相当于先查询再赋值)
    3,然后是update动作分解先对目标表根据索引做整体扫描,当然输出只要深入编译时设定的字段
    4,再做默认排序(即使随便一个查询也是有默认排序的)
    5,根据条件匹配索引,检索出所要的记录数备用
    6,执行语句对表内数据更新,即使数据一样也是把一样的数据覆盖(至于物理上具体有没有先开辟一个空间存放一样的新值,把字段有效地指出指向新的数据位置还是直接覆盖就不得而知了)
    7,程序返回结束提示(可省略)
    这些应该都是在内存中进行的就是逻辑上的,只有执行更新过后才实际操作物理磁盘