【问题标题】:Get deleted values from 3 tables and put in 1 table从 3 个表中获取已删除的值并放入 1 个表中
【发布时间】:2015-06-10 10:27:45
【问题描述】:

我有三张桌子

最终用户可以从 ASP 的下拉列表中选择一个 top2000jaar,它将其值发送到存储过程,存储过程必须删除 [LIJST] 中的所有值,其中 top2000jaar 等于已选择的值但是需要一个触发器,当 [LIJST] 中不再存在该 songid 时,从 [SONG] 中删除 song.songid = lijst.songid 的行,因此如果 [artiest] 中的艺术家在 [song] 中没有剩余歌曲,艺术家也应该被删除。

所有删除的数据都应该放在[logtable]中

我尝试了一种我认为可行的方法,但没有。

预期的输出应该是这样的:

这是创建的触发器,我在谷歌上找到了一些答案,但不起作用:

ALTER TRIGGER [dbo].[TRGremoveSong]
ON [dbo].[Lijst]
AFTER DELETE AS

Begin
DELETE FROM song where songid not in (Select songid from lijst)
END
begin
INSERT INTO logtable
   SELECT 
       *
   FROM deleted
 end

【问题讨论】:

  • 请通过编辑问题在问题本身中添加您的结构、示例数据和预期输出。请不要添加链接。如果将来链接断开,问题可能会变得无法回答。
  • 感谢回复,马上改了
  • 请添加您的触发器代码!代码有什么问题。
  • 您是否只是在努力更新日志表或从其他表中删除?
  • both,我学习了半年,现在包含了一些更难的sql,但是对于一些项目我就是想不出如何将它们放在一起,我知道如何单独删除它们,但是如何触发它使其全部自动化我不知道

标签: sql asp.net sql-server triggers


【解决方案1】:

我相信使用它作为触发器应该可以完成这项工作,这只会填充实际删除的内容,因此如果 artiest 没有被删除,它将在歌曲旁边显示为 null 等。

ALTER TRIGGER [dbo].[TRGremoveSong]
ON [dbo].[Lijst]
AFTER DELETE AS

Begin
   INSERT INTO logtable
   SELECT  sng.titel, art.naam, sng.jaar, positie, top2000jaar
   FROM deleted d
   Outer Apply
   (Select titel, jaar, artiestid from song where not exists (Select * from lijst where songid = d.songid) and songid = d.songid) sng
   Outer Apply
   (Select naam from artiest where not exists (Select * from song where artiestid = sng.artiestid and songid <> d.songid) and artiestid = sng.artiestid) art

DELETE FROM song s where not exists (Select * from lijst where songid = s.songid)
DELETE FROM artiest a where not exists (Select * from song where artiestid = a.artiestid)
End

这是一个示例 SQLFiddle,其中第 9 首歌曲被删除,这是该艺术家的最后一首歌曲:http://sqlfiddle.com/#!6/4405b/1/0

以下将显示删除的所有字段:

ALTER TRIGGER [dbo].[TRGremoveSong]
ON [dbo].[Lijst]
AFTER DELETE AS

Begin
   INSERT INTO logtable
   SELECT  sng.titel, art.naam, sng.jaar, positie, top2000jaar
   FROM deleted d
   Outer Apply
   (Select titel, jaar, artiestid from song where songid = d.songid) sng
   Outer Apply
   (Select naam from artiest where artiestid = sng.artiestid) art

DELETE FROM song s where not exists (Select * from lijst where songid = s.songid)
DELETE FROM artiest a where not exists (Select * from song where artiestid = a.artiestid)
End

这是用于此的 SQLFiddle:http://sqlfiddle.com/#!6/fd6171/1/0

【讨论】:

  • 嘿伙计,抱歉回复晚了,你的触发器看起来很准,但我的日志表中有很多空值。但不是在所有行上。这是我的输出的一部分:puu.sh/ilyxQ/3d68185e3a.png 这是我的触发器:puu.sh/ilyCb/d3d765deeb.png
  • 如果不是最后一首删除的歌曲,您将获得空值。因此,如果您有 3 首歌曲到 1 位艺术家的列表,并且其中 1 首歌曲在 lijst 表中重复 2 次,当您在 lijst 中删除 1 首歌曲 1 次时,它不会删除歌曲表中的歌曲,也不会删除歌曲表中最艺术的歌曲最艺术的桌子。它仍然会记录这一点,但与歌曲和最艺术表相关的字段将填充为空。只有当删除 lijst 中所有出现的歌曲时,删除歌曲表中最艺术的最后一首歌,导致最艺术表上最艺术的歌曲被删除,您才会看到填充的所有字段
  • 好吧,我怎么能总是填充这些字段,因为那是我的意图。删除是正确的,我感谢你
  • 我会告诉你代码的更新,这样它就可以做到这一点,对我来说是裸露的
  • @MaartenHeebink 我答案中的底部代码就是您要寻找的。我留下了顶部以帮助可能正在寻找类似解决方案的任何其他人,或者以防您改变主意希望它如何工作。
【解决方案2】:

您可以将逻辑添加到存储过程中来完成所有这些操作,如下所示:

DECLARE @LIJSTID_TO_DELETE INT = 123
DECLARE @SongID INT
DECLARE @ArtistID INT

-- SET the songid for the row you're going to delete
SELECT @SongID = songid 
FROM LIJST 
WHERE top2000jaar = @LIJSTID_TO_DELETE

-- first deletion
DELETE FROM LIJST 
WHERE top2000jaar = @LIJSTID_TO_DELETE

IF @@ROWCOUNT > 0
    INSERT INTO LOGTABLE.... -- deleted LIJST values

-- set the artist id for the song you are going to delete
SELECT @ArtistID = artiestid
FROM Song 
WHERE songid = @SongID

-- delete the linked song (could use cascade delete if required)
DELETE FROM Song
WHERE songid = @SongID

IF @@ROWCOUNT > 0
    INSERT INTO LOGTABLE.... -- deleted song values

-- Delete the artist if their songs no longer exist
IF NOT EXISTS (SELECT * FROM Song WHERE artiestid = ArtistID )
BEGIN
    DELETE FROM Artiest
    WHERE artiestid = @ArtistID 

    IF @@ROWCOUNT > 0
        INSERT INTO LOGTABLE.... -- deleted artiest values
END

@@ROWCOUNT只是简单的返回上一条语句影响的行数,所以只有删除了一行才会记录。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-08
    • 2020-06-08
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多