Как обновить значение столбца родительской таблицы при вставке / обновлении / удалении дочерней таблицы? - PullRequest
2 голосов
/ 08 августа 2011

У меня есть связанные таблицы, как в примере сценария ниже:

-- 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 в строке Product, когда пользователь вставляет / обновляет / удаляет обзор. Наиболее очевидный и грубый подход, который приходит мне в голову, - это извлечь данные из базы данных и вычислить среднее значение на стороне клиента, а затем вручную обновить строку продукта. Можно ли сделать это автоматически на сервере базы данных без необходимости извлечения данных? Если так, то как? База данных размещена на MS SQL Server 2008.

1 Ответ

3 голосов
/ 08 августа 2011

Вы можете создать триггер в таблице просмотра.После обновления на 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 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...