我创建了两个表。首先是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表中的总页数。
请帮我找个出路。 谢谢。答案 0 :(得分: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'。从许多观点来看,这比触发器要好得多(正确性,性能等)。引擎将在任何操作中保持此计数的最新状态。从Magzine表中删除TotalPages列。
答案 1 :(得分: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
现在为1
或2
。您将为其中一个运行更新,而错过另一个。
如果你真的想把它保留在原始表中(我强烈建议反对它,如果你坚持的话):
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
以及其他一系列问题。