插入和删除的伪表存储在哪里? [关闭]

Posted

技术标签:

【中文标题】插入和删除的伪表存储在哪里? [关闭]【英文标题】:where are the inserted and deleted pseudo tables stored? [closed] 【发布时间】:2017-12-05 17:55:53 【问题描述】:

SQL Server 触发器允许访问two special tables。 INSERTED - 使用“after”值,DELETED 使用“before”值。

这些存储在哪里?它们是存在于tempdb 中还是存在于与被操作的表相同的数据库中?

【问题讨论】:

关于 SQL Server 中魔术表的技术细节的信息并不多。 This page 谈论的是内部表,所有的魔法表文档都建议它们被存储。 @Barmar,我相信OP在sql server 2000+中谈论this feature 为什么你认为你需要知道这些实现细节?它们在该声明中可用,但不在该声明之外 【参考方案1】:

在 SQL Server 2005 之前的版本中,这些表 were read from the transaction log when needed。

自 SQL Server 2005 起,构成 after 触发器的插入和删除伪表的行都存储在 the version store 中(总是tempdb 的页面中 - 这些页面可能存在也可能不存在在内存中)。

您可以从下面非常清楚地看到这一点(在快照隔离和 RCSI 关闭的数据库中运行)

CREATE TABLE T1 (X BINARY(10));

GO

--B = Before
INSERT INTO T1
VALUES     (0xBBBBBBBBBBBBBBBBBBBB); 

GO

CREATE TRIGGER TR ON T1 AFTER UPDATE
AS
    PRINT 'Trigger called'

GO

DECLARE @mtsn INT = ISNULL(MAX(transaction_sequence_num), 0)
FROM   sys.dm_tran_version_store
WHERE  database_id = DB_ID();    

UPDATE T1
SET    X = 0xAAAAAAAAAAAAAAAAAAAA;    --A = After

SELECT transaction_sequence_num,
       version_sequence_num,
       record_image_first_part,
       CASE
         WHEN CHARINDEX(0xBBBBBBBBBBBBBBBBBBBB, record_image_first_part) > 0
           THEN 'Before'
         WHEN CHARINDEX(0xAAAAAAAAAAAAAAAAAAAA, record_image_first_part) > 0
           THEN 'After'
       END
FROM   sys.dm_tran_version_store
WHERE  database_id = DB_ID()
       AND transaction_sequence_num > @mtsn;


DROP TABLE T1 

返回类似的东西

【讨论】:

【参考方案2】:

这是疯狂的谈话。这些表在事务范围内存在于内存中*

使用触发器已经够糟糕了,不要试图弄乱 INSERTED 和 DELETED 表。如果您非常想这样做,您可以在触发器内用它的数据填充另一个(临时?)表。

触发器几乎在任何情况下都被认为是反模式,它只是不是普通的日志。一般来说,您可以首先使用触发触发器的数据,并保持简洁且易于维护的业务逻辑。

*在内存中: 大多数情况下,SQL 引擎会尝试让所有内容都在 RAM 内存中,如果出于任何原因它需要更多内存有可用的页面,它会开始使用磁盘tempBD,但它是完全透明的,不受您的控制。

编辑

Martin Smith 的回答非常好。我知道可以对临时表执行类似的操作,但从未尝试对触发器表执行此操作。我只想指出,实现任何需要直接操作对象的东西都会引起人们对错误方向的怀疑。

这里有一些关于我对(错误使用)触发器的“咆哮”的来源

Are database triggers evil?

When are database triggers bad?

【讨论】:

如果您没有在触发器中添加太多逻辑,那么触发器没有任何问题。我通常坚持使用它来记录或快速取消基于业务逻辑的事务。我避免让一个触发器启动另一个触发器,它非常有用。 SQL Server 触发器不是反模式。就像调用安全带反模式一样。否则答案是正确的。 @benjaminmoskovits 将业务逻辑放在数据库中是非常反模式的,使用触发器是(可能)反模式的信号。像日志这样的触发器有很多用途,您确实需要将 BL 放在 DB 端以提高性能,但必须谨慎处理,不能成为项目模式,永远不要。 @benjaminmoskovits 注意 SQL 世界充满了不推荐使用的、反模式的、不好的用途,例如触发器、游标、使用命令式/过程范式而不是函数/数据集和隐式连接 我真的不想参与辩论,但请不要将触发器与光标放在同一类别中。虽然 SQL Server 审计已经大部分取代了触发器作为审计功能的使用,但我发现有时没有比使用触发器更好的方法来防止“坏”事情的发生。当然,如果开发人员编写了完美的代码并且使用没有出错(例如将价格降低 99% 而不是 9%),则触发器将是不必要的。

以上是关于插入和删除的伪表存储在哪里? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

ros的关闭清除距离 在哪里?

我们可以删除 hive 表中的特定存储桶吗? [关闭]

固定大小键的最快持久键/值数据库并且仅插入/获取(无删除/更新)? [关闭]

生成一首包含 160 位可恢复信息的伪诗 [关闭]

伪表和伪列

使用 mocha 进行所有测试后在哪里删除数据库并关闭连接