您的触发器当前假定总是会有单行插入。你试过这样的触发器吗?
INSERT dbo.[poll-options](option_order --, ...)
VALUES(1 --, ...),
(2 --, ...);
此外,您说 SQL Server“无法访问插入的表” - 但您的声明是这样说的。你在哪里引用inserted
(即使这是一个有效的子查询结构)?
SET @count = (SELECT COUNT (*) FROM [poll-count]
WHERE option_order = i.option_order)
-----------------------^ "i" <> "inserted"
这是一个正确引用inserted
并正确处理多行插入的触发器:
CREATE TRIGGER dbo.pollupdate
ON dbo.[poll-options]
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
;WITH x AS
(
SELECT option_order, c = COUNT(*)
FROM dbo.[poll-options] AS p
WHERE EXISTS
(
SELECT 1 FROM inserted
WHERE option_order = p.option_order
)
GROUP BY option_order
)
UPDATE p SET total = x.c
FROM dbo.[poll-options] AS p
INNER JOIN x
ON p.option_order = x.option_order;
END
GO
但是,为什么要在每一行上存储这些数据?您始终可以在运行时导出计数,知道它是最新的,并且完全不需要触发器。如果它是关于在运行时推导计数的性能方面,那么在 DML 期间以大约相同的维护成本实现这种预写优化的一种更简单的方法是创建一个索引视图:
CREATE VIEW dbo.[poll-options-count]
WITH SCHEMABINDING
AS
SELECT option_order, c = COUNT_BIG(*)
FROM dbo.[poll-options]
GROUP BY option_order;
GO
CREATE UNIQUE CLUSTERED INDEX oo ON dbo.[poll-options-count](option_order);
GO
现在为您维护了索引,您可以非常快速地得出任何给定(或所有)option_order
值的计数。当然,您将测试查询时间的改进是否值得增加维护(尽管您已经为触发器付出了这个代价,除了它可以影响任何给定插入中的更多行,所以......) .
最后的建议是,不要-
在对象名称中使用特殊字符。它只是迫使你总是把它包裹起来,[square brackets]
这对任何人来说都没有乐趣。