如何在SQL中创建删除触发器从子表中删除一条记录时更新父表中的记录计数?

如何在SQL中创建删除触发器从子表中删除一条记录时更新父表中的记录计数?,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我创建了两个表格。第一个是杂志 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_tblMag

我创建了两个表格。第一个是杂志

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

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

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

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列

如果您确实需要存储计数,无论出于何种原因,您是否考虑过让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()
将自动更新。这还有一个好处,即您可能希望更新此定义,例如忽略
活动
为0的页面


为什么你的触发器坏了-按如下方式插入:

INSERT INTO [dbo].[MagzinePage]([MagzineID],[DateCreated],[CreatedBy],[Active]) VALUES
(1,CURRENT_TIMESTAMP,'Me',1),
(2,CURRENT_TIMESTAMP,'Me also',1)
该表中的
前1个MagzineID
现在将是
1
2
。您将为其中一个运行更新,而错过另一个


如果您真的想将其保留在原始表格中(如果您坚持,我强烈建议您不要这样做):


应该将其作为单个触发器来执行(废弃现有触发器),并正确处理插入中的多行,以及更改的更新
MagzineID
和大量其他问题。

如果您确实需要存储计数,无论出于何种原因,您是否考虑过让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()
将自动更新。这还有一个好处,即您可能希望更新此定义,例如忽略
活动
为0的页面


为什么你的触发器坏了-按如下方式插入:

INSERT INTO [dbo].[MagzinePage]([MagzineID],[DateCreated],[CreatedBy],[Active]) VALUES
(1,CURRENT_TIMESTAMP,'Me',1),
(2,CURRENT_TIMESTAMP,'Me also',1)
该表中的
前1个MagzineID
现在将是
1
2
。您将为其中一个运行更新,而错过另一个


如果您真的想将其保留在原始表格中(如果您坚持,我强烈建议您不要这样做):


应该将其作为一个触发器来执行(废弃现有的触发器),并正确处理插入中的多行,以及更新更改的
MagzineID
和一系列其他问题。

您当前的插入触发器已损坏-单个
insert
可以为多个杂志创建行,但您的触发器将只更新一个。另外,您认为为什么需要存储计数?如果在数据检索期间执行计数(例如,
选择
),它永远是正确的。@Damien_The_不相信我相信这个触发器工作正常,我需要计数,因为我需要显示一个包含杂志所有细节的网格。如果我每次都检索数据,可能会花费很长时间。你有什么建议吗?我在回答的末尾添加了一个部分,说明为什么你的触发器会被触发已损坏。您当前的插入触发器已损坏-单个
insert
可以为多个杂志创建行,但您的触发器将只更新一个。另外,您认为为什么需要存储计数?如果在数据检索期间执行计数(例如,
选择
),它总是正确的。@Damien_The_不相信我相信这个触发器工作得很好,我需要计数,因为我需要显示一个包含杂志所有细节的网格。如果我每次都检索数据,可能会花费很长时间。你有什么建议吗?我在回答的末尾添加了一个部分,显示触发器损坏的原因。我无法从中删除totalpages计数,因为我正在使用此表页绑定gridview上的总计数。我只需要一个触发器,可以在这里为我作弊,因为现在我处于项目中间,不能改变结构,否则它会很混乱。我希望你能理解。我不能从中删除总页数,因为我用这个表页绑定GRIDVIEW上的总计数。我只需要一个触发器,可以为我在这里作弊,因为现在我在项目中间,不能改变结构,否则它会是混乱的。我希望你能理解。最后我得到的解决方案与LINQ查询…我喜欢…感谢所有给我反馈的人。这是我的查询
public int-getTotalPages(int-magId){using(SeekDataContextDataContext dc=new-SeekDataContextDataContext()){return dc.MagzinePages.Where(p=>p.MagzineID==magId)。选择(p=>p.ID.Count();}
最后我用Linq查询得到了解决方案。我喜欢它。。感谢所有给我反馈的人。下面是我的查询
public int getTotalPages(int magId){使用(SeekDataContextDataContext dc=new SeekDataContextDataContext()){返回dc.MagzinePages.Where(p=>p.MagzineID