我正在尝试按照 Richard Snodgrass 的书(在 SQL 中开发面向时间的数据库应用程序)在 MSSQL Server 2016 上实现事务时间表。
通过触发器具有顺序主键的表可以这样实现:
CREATE TABLE test_table (
a [tinyint] NOT NULL,
b [date] NOT NULL,
c [float] NOT NULL,
[tt_start] [datetime2](7) NOT NULL,
[tt_end] [datetime2](7) NOT NULL)
GO
CREATE TRIGGER Seq_Primary_Key_tt ON test_table FOR INSERT, UPDATE, DELETE AS
BEGIN
IF (( EXISTS ( SELECT * FROM test_table AS b1
WHERE 1 < (SELECT COUNT(b2.a) FROM
test_table AS b2
WHERE b1.a = b2.a AND
b1.b = b2.b AND
b1.tt_start < b2.tt_end AND b2.tt_start < b1.tt_end) )))
BEGIN
RAISERROR('Transaction violates sequenced constraint', 1, 2)
ROLLBACK TRANSACTION
END
END
GO
触发器在较大的表上非常慢。因此,使用多个 INSERT 会导致等待时间过长。此外,像更新这样的许多操作需要不止一个操作(例如 INSERT,然后是 UPDATE)。这不适用于此触发器,因为触发器将在 INSERT 之后启动并失败,尽管如果触发器在 UPDATE 之后启动,该操作将完美运行。
这就是为什么 Snodgrass 写道约束/断言(或这里的触发器)必须是 DEFERRABLE INITIALLY DEFERRED。这样,将在所有操作完成后检查约束。这同时也会提高多个 INSERT 的性能。
但是,据我所知,MSSQL Server 没有实现 DEFERRABLE INITIALLY DEFERRED。然后如何实施类似的约束或触发器?或者“临时表”功能可以替代我正在尝试做的事情吗?