如何在子表insert / update / delete上更新父表列值?

时间:2011-08-08 15:27:26

标签: sql-server-2008

我必须使用以下示例脚本中的相关表格:

-- Creating table 'Product'
CREATE TABLE [dbo].[Product] (
    [Id] int IDENTITY(1,1) NOT NULL,
    [Text] nvarchar(max)  NOT NULL,
    [AvgRating] decimal(18,2)  NOT NULL
);
GO

-- Creating table 'Review'
CREATE TABLE [dbo].[Review] (
    [Id] int IDENTITY(1,1) NOT NULL,
    [Text] nvarchar(max)  NOT NULL,
    [Rating] decimal(18,2)  NOT NULL,
    [Product_Id] int  NOT NULL
);
GO

-- Creating primary key on [Id] in table 'Product'
ALTER TABLE [dbo].[Product]
ADD CONSTRAINT [PK_Product]
    PRIMARY KEY CLUSTERED ([Id] ASC);
GO

-- Creating primary key on [Id] in table 'Review'
ALTER TABLE [dbo].[Review]
ADD CONSTRAINT [PK_Review]
    PRIMARY KEY CLUSTERED ([Id] ASC);
GO

-- Creating foreign key on [Product_Id] in table 'Review'
ALTER TABLE [dbo].[Review]
ADD CONSTRAINT [FK_ProductReview]
    FOREIGN KEY ([Product_Id])
    REFERENCES [dbo].[Product]
        ([Id])
    ON DELETE NO ACTION ON UPDATE NO ACTION;

-- Creating non-clustered index for FOREIGN KEY 'FK_ProductReview'
CREATE INDEX [IX_FK_ProductReview]
ON [dbo].[Review]
    ([Product_Id]);
GO

我想在用户插入/更新/删除评论时计算产品行的AvgRating。我想到的最明显和最暴力的方法是从数据库中提取数据并计算客户端的平均值,然后手动更新产品行。是否可以在数据库服务器上自动执行而无需提取数据?如果是这样,怎么样?数据库托管在MS SQL Server 2008上。

1 个答案:

答案 0 :(得分:3)

您可以在Review表上创建触发器。在审核更新后,它可以重新计算平均审核。

CREATE TRIGGER TRG_REVIEW 
ON Review
AFTER INSERT, UPDATE, DELETE
AS 

;WITH ratings 
AS 
(
    SELECT product_id, AVG(Rating) AS rating
    FROM Review R
    WHERE EXISTS (SELECT * FROM INSERTED WHERE product_id = R.product_id AND UPDATE(rating))
         OR EXISTS (SELECT * FROM DELETED WHERE product_id = R.product_id)
    GROUP BY product_id
)
UPDATE P set AvgRating = COALESCE(R.rating,0)
FROM Product P 
INNER JOIN ratings R 
ON P.id = R.Product_id