Sql server:更新后创建一个触发器

时间:2017-11-23 08:07:13

标签: sql-server triggers

我有3张桌子:

  • 艺术家= {artistname,members}
  • Musician = {msin,firstname,lastname}
  • 播放= {artistname,msin}

键:

  • 艺术家:artistname
  • 音乐家:msin
  • 播放:artistname(外键参考艺术家),msin(外键参考音乐家)

其他信息:

  • 艺术家是乐队名称,会员记录乐队中的音乐家人数。
  • msin是音乐家的身份证号码。
  • 播放音乐家演奏乐队/艺术家
  • 的唱片

我需要在Plays表上创建一个触发器:Artist表的members属性应该始终等于Artist的成员音乐家的数量。 “播放”中的任何插入,删除和更新都会触发音乐家中成员属性的更改。

我做了这些删除和插入:

create trigger memberAddDel
on Plays
after insert, delete
as
if exists ( select 1 from inserted ) and not exists ( select 1 from deleted )
begin
    update Artist
    set members = (select count(msin) 
                    from Plays p 
                    group by p.artistname 
                    having p.artistname = (select artistname from inserted))
    where artistname = (select artistname from inserted)
end 
else if exists ( select 1 from deleted ) and not exists ( select 1 from inserted ) 
begin
    update Artist
    set members = (select count(msin) 
                    from Plays p 
                    group by p.artistname 
                    having p.artistname = (select artistname from deleted))
    where artistname = (select artistname from deleted)
end

但我坚持使用更新部分。我的理解是,在更新表时,查询会创建一个已插入和已删除的表。 inserted是新记录,删除是旧记录。我考虑过以下情况:

  • 仅限播放中的msin更新:再次计算该艺术家名称的msin
  • 仅限播放中的artistname更新:再次计算msn(同时插入和删除)
  • 在artistname和msin中更新:再次计算两个artistname(插入和删除)的msin

这是我的尝试:我只是非常野蛮地更新这两个艺术家名字。

create trigger memberUpdate
on Plays
after update
as
if exists ( select 1 from inserted ) and exists ( select 1 from deleted )
begin
    update Artist 
    set members = (select count(msin) 
                    from Plays p 
                    group by artistname 
                    having artistname = (select artistname from inserted)
    where artistname = (select artistname from inserted)

    update Artist 
    set members = (select count(msin) 
                    from Plays p 
                    group by artistname 
                    having artistname = (select artistname from deleted)
    where artistname = (select artistname from deleted)

end 

我有零经验创建触发器。这是我的问题:这是处理更新触发器的正确​​方法吗?这个查询是否正确?或任何更简洁的方式来写这个触发器?

2 个答案:

答案 0 :(得分:1)

首先,havingwhere条件不正确:select artistname from inserted可能包含多行。

此外,我们可能会争辩说,由于可以随时计算此信息,因此不需要使用特定列来计算成员。但是这个选择可能与提高你的表现有关,这取决于你。

以下是我建议根据INSERTEDDELETED更新成员的信息:

CREATE TRIGGER memberUpdate
ON Plays
AFTER UPDATE
AS
BEGIN
    UPDATE A SET members = A2.members
    FROM Artist A
    INNER JOIN (
        SELECT A.artistname, A.members + COUNT(I.msin) - COUNT(D.msin) AS members
        FROM Artist A
            LEFT OUTER JOIN inserted I ON A.artistname = I.artistname
            LEFT OUTER JOIN deleted D ON A.artistname = D.artistname
        WHERE 
            --exclude artists that have not been updated
            I.artistname IS NOT NULL OR D.artistname IS NOT NULL
        GROUP BY A.artistname, A.members) AS A2
    ON A.artistname = A2.artistname
END

答案 1 :(得分:0)

我可以看到的主要问题是,您希望乐队成员的数量存储在乐队表中,您已经知道它必然会发生变化。

如果我是你,我只需使用Play表来了解乐队有多少成员。请记住,您可能需要跟踪"流体"乐队,成员来和离开。因此,您可能希望为此目的添加DateFromDateTo列。

然后,您可以通过使用所需日期查询Play表,在任何时间点找到乐队中准确的成员数。