据我了解,当您更新 SQL Server 中的一行或多行时,该记录将被删除并重新插入新值。因此,这是否意味着触发了 INSERT 事件,或者只是在更新行时触发了 UPDATE?
编辑:为任何懒惰的读者突出主要信息(尽管我建议您阅读下面 davek 答案中的完整链接详细信息):
SQL 是否将所有更新都作为拆分更新?
简短的回答是:
不
稍微长一点的答案:
对于更改键值的更新,SQL 不会将其作为就地更新进行。
据我了解,当您更新 SQL Server 中的一行或多行时,该记录将被删除并重新插入新值。因此,这是否意味着触发了 INSERT 事件,或者只是在更新行时触发了 UPDATE?
编辑:为任何懒惰的读者突出主要信息(尽管我建议您阅读下面 davek 答案中的完整链接详细信息):
SQL 是否将所有更新都作为拆分更新?
简短的回答是:
不
稍微长一点的答案:
对于更改键值的更新,SQL 不会将其作为就地更新进行。
更新永远不会触发插入事件,即使它在物理上实现为插入/删除,因为逻辑上操作仍然是UPDATE
.
如果被认为是谈论键列的逻辑更新,则接受的答案中有一个短语并不完全正确。
对于更改键值的更新,SQL 不会将其作为就地更新执行
这不是针对唯一索引的多行更新的情况。对于那些 SQL Server 提供了一个带有拆分/排序/折叠运算符的计划。因此,在以下示例中,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 |
+-----------------+--------------------+---------------------------+
我认为(拆分为删除+插入)仅在更新需要更新索引时才成立。请参阅此链接:
尤其是最后一段:
现在我们确实有一个拆分更新。我们在日志中有一个 delete_rows 和一个 insert_rows 操作。这不是作为就地更新完成的 那么我们可以在这里得出什么结论呢?SQL 是否将所有更新都作为拆分更新?应该清楚的是,对于索引键未更改的情况,SQL 可以将更新作为就地更新进行。我不会试图声称它总是会,那会很愚蠢,有很多我没有看过的场景(页面拆分和转发的行是最明显的),但它可以而且会做就地更新。对于更改键值的更新,SQL 不会将其作为就地更新进行。保罗在不久前的一篇揭穿文章中解释说——http: //sqlskills.com/BLOGS/PAUL/post/Do-changes-to-index-keys-really-do-in-place-updates.aspx