2010-09-16 98 views
3

在我的数据库中,我有一些对应用程序运行很重要的数据(常量,...)。我有通过测试网站生成的测试数据。由于测试数据是可消耗的,因此定期删除它。不幸的是,这两种类型的数据出现在同一张表中,所以我不能做delete from T,但我必须做一个delete from T where IsDev = 0如何确保在SQL Server中不会意外删除一行?

如何确保我不会意外删除非开发数据而忘记放置过滤器?如果发生这种情况,我必须从正在浪费时间的生产备份中恢复。我会需要某种外键,例如在满足某些条件时无法删除的行为。这对确保我的代码不会因为错误而不会造成任何有害影响也很有用。

回答

8

嗯,你可以使用抛出异常的触发器如果任何在deleted元表中的记录有IsDev = 1

CREATE TRIGGER TR_DEL_protect_constants ON MyTable FOR DELETE AS 
BEGIN 
    IF EXISTS(SELECT 1 FROM deleted WHERE IsDev <> 0) 
    BEGIN 
     ROLLBACK 
     RAISERROR('Can''t delete constants', 1, 16) 
     RETURN 
    END 
END 

我猜对语法了一点,但你明白了。

+0

我会在'RAISERROR'之后添加一个'RETURN',以确保触发器执行在那里结束 – 2010-09-16 19:30:19

+0

啊非常好。 。 – usr 2010-09-16 19:31:30

+0

良好的通话,@KM。我也想知道OP是否意味着IsDev <> 1,但人们对术语有不同的看法。 – harpo 2010-09-16 19:32:25

1

保留要保留在单独的管理表中的行的备份

1

根据您想如何透明,使这个,你可以使用一个INSTEAD OF触发器将永远记住你的什么地方。

CREATE TRIGGER TR_IODEL_DevOnly ON YourTable 
INSTEAD OF DELETE 
AS 
BEGIN 
    DELETE FROM t 
     FROM Deleted d 
      INNER JOIN YourTable t 
       ON d.PrimaryKey = t.PrimaryKey 
     WHERE t.IsDev = 0 
END 
1

我建议,而不是从头开始,每次写delete语句,只需创建一个存储过程来完成的缺失和执行。

create procedure ResetT as delete from T where IsDev = 0 
+0

理论上,当然。实际上,有一天有人会忘记使用proc的重要性。然后......最好用触发器来掩护自己。 – 2010-09-16 20:24:34

+0

@Joe Stefanelli - 这就是为什么存储过程应该是唯一有权从表中删除的实体。触发器是编写良好的代码和访问限制的好替代品。 – 2010-09-16 20:31:10

+0

查询并不总是相同的。有时我会删除一部分数据。 – usr 2010-09-18 12:38:16

1

你可以在你的表中创建一个额外的列IS_TEST,重命名TABLE_NAME到TABLE_NAME_BAK,并让只有在IS_TEST设置行显示在它的TABLE_NAME_BAK创建视图TABLE_NAME。将IS_TEST设置为零以保留要保留的数据,并将DEFAULT 1添加到IS_TEST列应完成该作业。它与创建“软删除”所需的过程类似。