0

我创建了两个表。首先是杂志

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 表中的总页数。

请帮我想办法解决这个问题。谢谢。

4

2 回答 2

2

您可以创建一个索引视图,该视图将始终为您保持最新的计数:

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

我保留了你对“杂志”的拼写。从许多角度(正确性、性能等)来看,这比触发器要好得多。引擎将在任何操作中保持此计数最新。从 Magzine 表中删除 TotalPages 列。

于 2012-06-28T10:40:48.053 回答
2

如果您确实需要存储计数,无论出于何种原因,您是否考虑过让 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和一大堆其他问题。

于 2012-06-28T10:42:10.787 回答