簡體   English   中英

從子表中刪除一條記錄時,如何在SQL中創建刪除觸發器以更新父表中的記錄數?

[英]How to create delete trigger in SQL on deletion of one record from child table updates the records count in parent table?

我創建了兩個表。第一個是magzine

CREATE TABLE [dbo].[Magzine](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](350) NULL,
[MagzineType] [int] NOT NULL,
[TotalPages] [int] NOT NULL,
[DateCreated] [datetime] NOT NULL,
[Active] [bit] NOT NULL, CONSTRAINT [PK_tblMagzine] PRIMARY KEY CLUSTERED (
[ID] ASC)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]) ON [PRIMARY] GO

該列的名稱為TotalPages,用於保存雜志中的總頁數

這是MagzinePage表。

CREATE TABLE [dbo].[MagzinePage](
[ID] [int] IDENTITY(1,1) NOT NULL,
[MagzineID] [int] NOT NULL,
[Title] [nvarchar](255) NULL,
[SubTitle] [nvarchar](255) NULL,
[Photo] [nvarchar](255) NULL,
[Description] [nvarchar](2000) NULL,
[DateCreated] [datetime] NOT NULL,
[CreatedBy] [nvarchar](25) NOT NULL,
[Active] [bit] NOT NULL,
[IsMapped] [bit] NULL, CONSTRAINT [PK_tblPage] PRIMARY KEY CLUSTERED (
[ID] ASC)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]) ON [PRIMARY] GO

我已經在magzinePage表中插入數據時創建了一個觸發器,該觸發器可以根據ID對表中插入的記錄總數進行處理,這是觸發器

Alter TRIGGER trgAfterInsert ON [dbo].[MagzinePage] 
    FOR INSERT

    AS
    Declare @MagzineID int;
    Declare @TotalPages int;
    Set @MagzineID= (Select Top 1 MagzineID From MagzinePage Order By ID Desc)
    Set @TotalPages =  (Select Count(MagzineID) from MagzinePage Where MagzineID=@MagzineID Group By MagzinePage.MagzineID) 

        Update Magzine Set TotalPages=@TotalPages Where ID= @MagzineID

        PRINT 'AFTER INSERT trigger fired.'
    GO  

現在,我想要創建一個觸發器,該觸發器可以在刪除magzinePage表中的記錄時幫助減少Magzine表中的頁面總數。

請幫我找出一個出路。 謝謝。

您可以創建一個索引視圖,該視圖將始終為您保持最新狀態:

create view dbo.vwMagzinePageCount 
with schemabinding
as
select [MagzineID], count_big(*) as TotalPages
from dbo.[MagzinePage]
group by [MagzineID];
go

create unique clustered index cdxMagzinePageCount 
    on dbo.vwMagzinePageCount (MagzineID);
go

我保留了“雜志”的拼寫。 從許多角度(正確性,性能等)來看,這比觸發器要好得多。 引擎將在任何操作中保持此計數為最新。 從雜志表中刪除TotalPages列。

如果確實由於某種原因需要存儲計數,是否考慮過讓SQL Server為您完成工作? 如果從第一個表中刪除TotalPages ,然后定義此視圖:

CREATE VIEW dbo.MagzineWithPages
WITH SCHEMABINDING
AS
    select m.ID,Name,MagzineType,COUNT_BIG(*) as TotalPages,m.DateCreated,m.Active
    from
        dbo.Magzine m
            inner join
        dbo.MagzinePage mp
            on
                m.ID = mp.MagzineID
    group by
        m.ID,Name,MagzineType,m.DateCreated,m.Active
GO
CREATE UNIQUE CLUSTERED INDEX IX_MagzineWithPages on MagzineWithPages (ID)

然后,在添加和刪除頁面行時, COUNT()將自動更新。 這還具有您可能希望更新此定義的好處,例如忽略Active為0的頁面。


為什么你的觸發了-像這樣運行的INSERT:

INSERT INTO [dbo].[MagzinePage]([MagzineID],[DateCreated],[CreatedBy],[Active]) VALUES
(1,CURRENT_TIMESTAMP,'Me',1),
(2,CURRENT_TIMESTAMP,'Me also',1)

現在,該表中的TOP 1 MagzineID將為12 您將為其中一個運行更新,而錯過另一個。


如果您確實想將其保留在原始表中(強烈建議,如果您堅持的話,建議您這樣做):

CREATE TRIGGER T_MagzinePage on dbo.MagzinePage
AFTER INSERT,UPDATE,DELETE
AS

SET NOCOUNT ON

;with Deltas as (
    select MagzineID,COUNT(*) as Cnt,0 as Del from inserted group by MagzineID
    union all
    select MagzineID,COUNT(*),1 from deleted group by MagzineID
), Merged as (
    select MagzineID,SUM(CASE WHEN Del=0 then Cnt ELSE -Cnt END) as Net
)
update m set TotalPages = TotalPages + Net
from Magzine m
inner join
Merged mm
on
    m.MagzineID = mm.MagzineID

應該將其作為單個觸發器(廢除現有觸發器)來完成,並正確處理插入中的多行以及更新更改了MagzineID以及其他許多問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM