插入和删除的伪表存储在哪里? [关闭]
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%),则触发器将是不必要的。以上是关于插入和删除的伪表存储在哪里? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章