SQL Server仅触发更改以更新计算列

时间:2017-01-02 08:07:04

标签: sql-server triggers

对于时间安排项目,我有两个表:tbl_timeslots保存可用时间slotid作为主键,totalmembers计算为此插槽作出的约会数,和tbl_appointments主键apptid,其中包含实际约会,slotid作为链接到插槽信息的外键。

我需要在创建/删除/更改约会时自动更新totalmembers列。我写的触发器(如下所示)未更新tbl_timeslotstotalmembers中正确的约会数。

CREATE TABLE tbl_timeslots
(
    slotid int ,
    fromdate datetime ,
    todate datetime ,
    totalmembers int 
)

INSERT tbl_timeslots (slotid, fromdate, todate, totalmembers) 
VALUES (1, '2016-01-01 10:00:00', '2016-01-01 11:00:00', 0)
INSERT tbl_timeslots (slotid, fromdate, todate, totalmembers) 
VALUES (2, '2016-01-01 11:00:00', '2016-01-01 12:00:00', 0)

CREATE TABLE tbl_appointments
(
    apptid int ,
    slotid int ,
    firstname varchar(10) ,
    lastname varchar(10) 
)

INSERT tbl_appointments (apptid, slotid, firstname, lastname) 
VALUES (1, 1, 'Mark', 'Twain')
INSERT tbl_appointments (apptid, slotid, firstname, lastname)  
VALUES (2, 1, 'Thomas', 'Jefferson')
INSERT tbl_appointments (apptid, slotid, firstname, lastname) 
VALUES (3, 2, 'Donald', 'Duck')


CREATE TRIGGER [dbo].[tr_totalmembers] 
ON [dbo].[TBL_appointments]
AFTER UPDATE, INSERT, DELETE 
AS 
BEGIN
    UPDATE tbl_timeslots 
    SET totalmembers = (SELECT COUNT(1) 
                        FROM tbl_appointments a 
                        WHERE tbl_timeslots.slotid = a.slotid) 
    FROM inserted i 
    INNER JOIN deleted d ON i.apptid = d.apptid 
    WHERE
        d.slotid <> i.slotid 
        AND (tbl_timeslots.slotid = i.slotid OR tbl_timeslots.slotid = d.slotid)
END

2 个答案:

答案 0 :(得分:0)

我刚刚修改了一下触发器,它对我有用:

CREATE TRIGGER [dbo].[tr_totalmembers] 
ON [dbo].[TBL_appointments]
AFTER UPDATE, INSERT, DELETE 
AS 
BEGIN
UPDATE tbl_timeslots 
SET totalmembers = a.cnt 
from 
(
SELECT slotid,COUNT(1) as cnt 
 FROM tbl_appointments 
 group by slotid
 ) a
WHERE
   tbl_timeslots.slotid=a.slotid
 END

如果有特定问题,请提及以便我们查看。

答案 1 :(得分:0)

计算totalmembers的更好方法是创建和使用索引视图:

CREATE VIEW dbo.vw_timeslots_with_totalmembers
WITH SCHEMA_BINDING
AS
SELECT  a.slotid, COUNT_BIG(*) AS totalmembers
FROM    dbo.tbl_appointments a
GROUP BY a.slotid
GO

CREATE UNIQUE CLUSTERED INDEX IUC_vw_timeslots_with_totalmembers_slotid
ON dbo.vw_timeslots_with_totalmembers (slotid)
GO

DECLARE @slotid INT = 123
SELECT  totalmembers
FROM    dbo.vw_timeslots_with_totalmembers WITH(NOEXPAND) -- This table hint is needed in order to force usage of indexed view
WHERE   slotid = @slotid
GO

注意:请阅读以下关于SET tings正确配置的说明(请参阅Required SET Options for Indexed Views部分):https://msdn.microsoft.com/en-us/library/ms191432.aspx

注意#2:如果最后SELECT语句返回0行,则表示当前插槽没有约会(我假设当前插槽有效)。