我来自 Oracle/PostgreSQL 背景,很难应对 SQL Server 触发器实现的限制。
datetime
如果不同列的值发生变化,我想更新两个不同的列。这是为了记录行的两个具体状态变化。
现在 SQL Server 既没有行级触发器,也没有before update
触发器。所以我的理解是我需要加入插入和删除以找出是否发生了状态变化以及发生了哪些状态变化,然后对正在更新的表运行“定期”更新。
我的触发器目前看起来像这样:
create trigger ord_status_history_trigger
on jobs
AFTER UPDATE
AS
IF ( UPDATE(order_status) )
BEGIN
update jobs
set transfercomplete = case
when o.order_status = 'initial' and n.order_status = 'sent' then current_timestamp
else n.transfercomplete
end,
installcomplete = case
when o.order_status = 'delivered' n.order_status = 'installed' then current_timestamp
else n.installcomplete
end
from inserted n
join deleted o on o.jobid = n.jobid
join jobs aj on aj.jobid = n.jobid;
END
我的问题是:这个触发器是否有效地导致表上的两个更新?
第一个是触发更新,第二个是触发器执行的更新?
或者 SQL Server 是否足够聪明,可以将其合并到对基表的单个更新中(基本上就像BEFORE UPDATE
PostgreSQL 中的触发器一样)
我会在这里造成潜在的性能瓶颈吗?
我们也可以在应用程序中设置这些时间戳,但是如果我们可以将其委托给数据库会更好,这样我们就可以确保永远不会忘记这一点。
您的触发器在表上发生更新后运行。如果您在触发器中再次更新表,则会执行新的更新。另请参阅有关RECURSIVE_TRIGGERS的讨论。
如果您想在更新之前运行代码,您必须创建一个INSTEAD OF 触发器。
是否必须进行两次更新而不是一次会成为瓶颈,完全取决于触发器中更新的效率,当然还有这个 UPDATE 是否已经在关键路径上。您可能在作业 id 上有一个主键,页面在缓冲池中很热,并且您不能有锁冲突。所以基本上只受a)您的日志接受写入的速度和b)版本存储(为已删除和插入的伪表提供服务)是否可以跟上。
如果你问我:这样的业务逻辑状态管家属于应用程序,而不是触发器......