sql server无法在触发器中访问inserted表

时间:2013-01-19 18:21:14

标签: sql sql-server triggers

我正在尝试创建一个简单的插入触发器,从表中获取计数并将其添加到另一个像这样的

CREATE TABLE [poll-count](
id VARCHAR(100),
altid BIGINT,
option_order BIGINT,
uip VARCHAR(50),
[uid] VARCHAR(100),
[order] BIGINT
PRIMARY KEY NONCLUSTERED([order]),
FOREIGN KEY ([order]) references ord ([order]  
)
GO

CREATE TRIGGER [get-poll-count]
ON [poll-count]
FOR INSERT 
AS 
    BEGIN
        DECLARE @count INT
        SET @count = (SELECT COUNT (*) FROM [poll-count] WHERE option_order = i.option_order)
        UPDATE [poll-options] SET [total] = @count WHERE [order] = i.option_order
    END
GO

当我尝试运行此操作时,我收到此错误:

  

多部分标识符“i.o​​ption_order”无法绑定

问题是什么?

感谢

1 个答案:

答案 0 :(得分:3)

您的触发器当前假定始终存在单行插入。你有没有试过这样的触发器?

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]中,这对任何人来说都没有用。