Sql 保留表的卷影副本,同时保留从原始表中删除的记录

Sql 保留表的卷影副本,同时保留从原始表中删除的记录,sql,sql-server,Sql,Sql Server,对于SQL专家来说,这可能很容易,但SQL(尽管我可以使用它)并不是我真正喜欢的东西 我在DB里有一张桌子。(我们称之为计算机) 大约一万行。25列。1唯一键:列资产 有时,外部程序会删除一行或多行,但不应该这样做,因为我们仍然需要知道这些行中的一些信息,然后才能真正删除项目 我们无法控制外部应用程序的行为,因此我们提出了不同的想法: 我们希望创建第二个相同的表(COMPUTERS\u BACKUP),并首先用计算机的一对一副本填充该表。 之后,每天一次将新记录从计算机复制到计算机备份中,并在计

对于SQL专家来说,这可能很容易,但SQL(尽管我可以使用它)并不是我真正喜欢的东西

我在DB里有一张桌子。(我们称之为计算机)
大约一万行。25列。1唯一键:列资产

有时,外部程序会删除一行或多行,但不应该这样做,因为我们仍然需要知道这些行中的一些信息,然后才能真正删除项目

我们无法控制外部应用程序的行为,因此我们提出了不同的想法:

我们希望创建第二个相同的表(COMPUTERS\u BACKUP),并首先用计算机的一对一副本填充该表。
之后,每天一次将新记录从计算机复制到计算机备份中,并在计算机备份中更新原始记录发生更改的记录(资产列永远不会更改)

这样,我们可以保留从计算机上删除的记录的最后状态


是否有人可以为可以计划每天运行一次的存储过程提供代码?我可能自己能解决这个问题,但这需要几个小时左右的时间,我的时间非常紧迫。

在删除之前触发
事件可以帮助您保护此表:

CREATE TRIGGER backup_row_before_delete ON COMPUTERS_Table FOR Delete
as 
    INSERT INTO Computers_Backup
    SELECT deleted.* from deleted 

如果只想保留某些列,可以更改
deleted.col1、deleted.col2的
deleted.

只需为insert computers表创建一个触发器即可

CREATE TRIGGER newComputer
ON [Computers]
AFTER INSERT
Begin

INSERT INTO COMPUTERS_BACKUP
  SELECT * FROM Inserted

End
CREATE TRIGGER computerDeleted ON [Computers] AFTER DELETE
Begin

INSERT INTO Computers_BACKUP
  SELECT * FROM Deleted

End
当您将新计算机插入到computers表中时,它会工作,并且它还会将记录插入到bakcup表中

当您更新计算机时,也可以使用更新触发器更改计算机备份

CREATE TRIGGER newComputer
ON [Computers]
AFTER UPDATE
Begin
//can access before updating the record through SELECT * FROM Deleted
//can access after updating the record through SELECT * FROM Inserted
UPDATE Computers_BACKUP SET
 (attributes) = inserted.(attribute)
WHERE id = inserted.id

End
最后,我想当原始记录从computers表中删除时,您不想删除备份。您可以通过使用触发器检查更多示例

从计算机表中删除记录时

CREATE TRIGGER newComputer
ON [Computers]
AFTER INSERT
Begin

INSERT INTO COMPUTERS_BACKUP
  SELECT * FROM Inserted

End
CREATE TRIGGER computerDeleted ON [Computers] AFTER DELETE
Begin

INSERT INTO Computers_BACKUP
  SELECT * FROM Deleted

End

如果您在应用程序中从未从该表中删除记录(仅更新),那么一个可能的解决方案是引入
而不是delete
触发器

CREATE TRIGGER tg_computers_delete ON computers
INSTEAD OF DELETE AS
DELETE computers WHERE 1=2;
它将阻止删除记录


这里是演示。

除了创建触发器之外,您还可以研究启用,这在SQL Server Enterprise Edition中提供。它可能是一个超调,但应该提到,您可能会发现它对其他表和对象很有用

将删除一行或多行,但不应该这样做

那么您就有权限和完整性问题了

你当然可以使用触发器来记录删除(当然还有更新),但我不建议你使用它来保存一份原本不想删除的内容

如果必须,请删除权限;如果可以,请增强数据完整性。如果没有您的模式,很难确切地说出是如何实现的


最后,在适当的时候,使用(而不是)触发器检查阻止删除所需的任何条件。

为什么不添加一个
delete
触发器来记录删除的行?您可能可以在
APP_NAME()
上进行筛选,只记录被有问题的应用程序删除的行。是否在应用程序中删除该表中的行?@MartinSmith这也是我的第一反应,但是。。。我没有讲述这个漏洞的故事:表实际上被截断,然后由外部应用程序重新填充。愚蠢的设计,但我们必须接受它。@peterm是的。应用程序有一个清理功能。我们也可以将其更改为清理备份表。恐怕这不是SQL Server语法:(这不是有效的SQL Server语法。
CREATE TRIGGER backup\u row\u before\u delete ON COMPUTERS\u Table FOR delete AS INSERT INTO COMPUTERS\u backup SELECT*FROM DELETED;
我不是SQL高手,但我怀疑这会在truncate Table上触发。请参见上文。如果您愿意,它应该是
FOR delete
TRIGGER,而不是
Update
当然若要保留刚刚删除的记录,您必须只写入已删除的触发器以插入备份表。但在您的问题中,您已写入以保留整个表副本,这可能会导致在您尝试插入已存在的已删除记录时不插入已删除的记录。我可能会误解。我将更新我的回答。然后应该有3个触发器插入、更新和删除删除,每次更改都有时间标签。是的,如果你想跟踪computers表的整个更改,你应该有insert、update和Delete触发器。我喜欢这样。由于computers表被截断,然后被另一个表的大量插入重新生成,Delete触发器对我没有帮助,但我没有想过滥用insert和update触发器类似这样的触发器。(我意识到插入触发器会对大容量插入造成很大的性能影响,但CPU很便宜。我可以为运行SQL server的VM分配更多的电源。)请参阅我对MartinSmith的评论。这不是权限/完整性问题。我们获得了原始表的副本,我们的应用程序将其用于不同的目的。只是我们对数据的使用有稍微不同的要求。实际上,原始应用程序的行为在几周前发生了变化。我们对数据的使用没有改变。依赖于此提供的数据是几年前犯下的一个愚蠢的设计错误。现在我正试图处理后果。