【问题标题】:Does an update trigger an INSERT event as all updates are DELETE + (re)INSERT in SQL Server更新是否会触发 INSERT 事件,因为 SQL Server 中的所有更新都是 DELETE + (re)INSERT
【发布时间】:2012-09-14 09:29:56
【问题描述】:

据我了解,当您在 SQL Server 中更新一行或多行时,记录将被删除并重新插入新值。因此,这是否意味着触发了 INSERT 事件,或者只是在更新行时触发了 UPDATE?

编辑:为任何懒惰的读者突出主要信息(尽管我建议您阅读下面 davek 答案中的完整链接详细信息):

SQL 是否将所有更新都作为拆分更新进行?

简短的回答是:

没有

略长一点的答案:

对于更改键值的更新,SQL 不会将其作为 就地更新。

【问题讨论】:

    标签: sql-server sql-server-2008 triggers


    【解决方案1】:

    更新永远不会触发插入事件,即使它在物理上被实现为插入/删除,因为逻辑上操作仍然是UPDATE

    如果被认为是在谈论键列的逻辑更新,则接受的答案中有一个短语并不完全正确。

    对于更改键值的更新,SQL 不会将其作为 就地更新

    这不是针对唯一索引的多行更新的情况。对于那些 SQL Server 提供了一个带有split/sort/collapse 运算符的计划。所以在下面的例子中,9 个更新操作被转换为 1 个删除、8 个更新和一个插入。

    CREATE TABLE TestingUpdate7 (
    ID INT,
    SomeString CHAR(50)
    )
    
    CREATE UNIQUE CLUSTERED INDEX idx_ID ON TestingUpdate7 (ID)
    
    INSERT INTO TestingUpdate7 (ID, SomeString)
    VALUES
    (1,'One'),(2,'Two'),(3,'Three'),(4,'Four'),
    (5,'Five'),(6,'Six'),(7,'Seven'),(8,'Eight'),(9,'Nine')
    
    CHECKPOINT -- truncate the log, DB is in simple recovery.
    
    UPDATE TestingUpdate7
    SET  ID +=1
    
    SELECT Operation, Context, AllocUnitName 
    FROM fn_dblog(NULL, NULL) 
    

    返回

    +-----------------+--------------------+---------------------------+
    |    Operation    |      Context       |       AllocUnitName       |
    +-----------------+--------------------+---------------------------+
    | LOP_BEGIN_CKPT  | LCX_NULL           | NULL                      |
    | LOP_XACT_CKPT   | LCX_BOOT_PAGE_CKPT | NULL                      |
    | LOP_END_CKPT    | LCX_NULL           | NULL                      |
    | LOP_BEGIN_XACT  | LCX_NULL           | NULL                      |
    | LOP_DELETE_ROWS | LCX_MARK_AS_GHOST  | dbo.TestingUpdate7.idx_ID |
    | LOP_SET_BITS    | LCX_PFS            | dbo.TestingUpdate7.idx_ID |
    | LOP_MODIFY_ROW  | LCX_CLUSTERED      | dbo.TestingUpdate7.idx_ID |
    | LOP_MODIFY_ROW  | LCX_CLUSTERED      | dbo.TestingUpdate7.idx_ID |
    | LOP_MODIFY_ROW  | LCX_CLUSTERED      | dbo.TestingUpdate7.idx_ID |
    | LOP_MODIFY_ROW  | LCX_CLUSTERED      | dbo.TestingUpdate7.idx_ID |
    | LOP_MODIFY_ROW  | LCX_CLUSTERED      | dbo.TestingUpdate7.idx_ID |
    | LOP_MODIFY_ROW  | LCX_CLUSTERED      | dbo.TestingUpdate7.idx_ID |
    | LOP_MODIFY_ROW  | LCX_CLUSTERED      | dbo.TestingUpdate7.idx_ID |
    | LOP_MODIFY_ROW  | LCX_CLUSTERED      | dbo.TestingUpdate7.idx_ID |
    | LOP_INSERT_ROWS | LCX_CLUSTERED      | dbo.TestingUpdate7.idx_ID |
    | LOP_COMMIT_XACT | LCX_NULL           | NULL                      |
    +-----------------+--------------------+---------------------------+
    

    【讨论】:

      【解决方案2】:

      我认为(拆分为删除+插入)仅在更新需要更新索引时才成立。请参阅此链接:

      http://www.sqlservercentral.com/blogs/sqlinthewild/2011/06/21/are-all-updates-split-into-delete_2D00_insert_3F00_/

      尤其是最后一段:

      现在我们确实进行了拆分更新。我们有一个 delete_rows 和一个 日志中的 insert_rows 操作。这不是就地完成的 更新那么我们可以在这里得出什么结论? SQL 是否将所有更新作为拆分进行 更新?应该清楚的是,对于索引键不是 更改后,SQL 可以将更新作为就地更新进行。我不会尝试 并声称它总是会的,那太愚蠢了,有很多 我没有看过的场景(页面拆分和转发行 是最明显的),但它可以并且将就地进行 更新。对于更改键值的更新,SQL 不会执行这些操作 作为就地更新。保罗在他的一篇揭穿帖子中解释说 一会儿回来 - http://sqlskills.com/BLOGS/PAUL/post/Do-changes-to-index-keys-really-do-in-place-updates.aspx

      【讨论】:

      • SQL Server 有时会设法仍然进行就地更新,即使在逻辑上通过转换操作来更改键列,使得键列不变而非键列得到更新。跨度>
      猜你喜欢
      • 1970-01-01
      • 2011-07-07
      • 2018-10-07
      • 1970-01-01
      • 1970-01-01
      • 2016-02-16
      • 1970-01-01
      • 1970-01-01
      • 2016-03-21
      相关资源
      最近更新 更多