10

因此,连续第二天,有人清除了整个数据表,而不是他们试图删除的一行,因为他们没有限定的 where 子句。

我一直在调整 mgmt studio 选项,但找不到确认选项。我知道其他数据库的其他工具也有。

4

10 回答 10

17

我建议您始终首先使用 WHERE 子句编写 SELECT 语句并执行它以实际查看您的 DELETE 命令将删除哪些行。然后只需使用相同的 WHERE 子句执行 DELETE。这同样适用于更新。

于 2008-11-11T16:33:56.940 回答
13

在 Tools>Options>Query Execution>SQL Server>ANSI 下,您可以启用 Implicit Transactions 选项,这意味着您不需要显式包含 Begin Transaction 命令。

这样做的明显缺点是您可能会忘记在末尾添加 Commit(或 Rollback),或者更糟糕的是,您的同事默认情况下会在每个脚本的末尾添加 Commit。

你可以把马牵到水边...

您可能会建议他们在执行任何操作之前始终进行临时备份(取决于数据库的大小)以防万一。

于 2008-11-11T16:24:28.423 回答
5

在运行语句BEGIN TRANSACTION之前尝试使用 a 。DELETE

然后你可以选择COMMITROLLBACK相同。

于 2008-11-11T16:15:35.807 回答
3

在 SSMS 2005 中,您可以在 Tools|Options|Query Execution|SQL Server|ANSI ... check 下启用此选项SET IMPLICIT_TRANSACTIONS。这将需要提交来影响未来连接的更新/删除查询。

对于当前查询,转到查询|查询选项|执行|ANSI 并选中相同的框。

如果您使用的是 SSMS 2000,此页面也有说明。

正如其他人所指出的那样,这并不能解决根本原因:在您创建的每个新查询的末尾粘贴 COMMIT 几乎与首先触发查询一样容易。

于 2008-11-11T16:29:07.340 回答
3

首先,这就是审计表的用途。如果您知道谁删除了所有记录,您可以限制他们的数据库权限或从性能角度处理它们。在我办公室做这件事的最后一个人目前正在试用期。如果她再次这样做,她将被放开。如果您有权访问生产数据并确保您不会造成伤害,那么您就有责任是其中之一。这是一个性能问题,也是一个技术问题。您永远不会找到防止人们犯愚蠢错误的方法(数据库无法知道您是要删除表 a 还是删除 id = 100 的表 a 并且大多数人会自动点击确认)。您只能通过确保运行此代码的人员负责并制定政策来帮助他们记住要做什么来尝试减少它们。

其他人建议我们采取哪些措施来防止这种情况发生。我总是在我从查询窗口运行的删除中嵌入一个选择,以确保它只会删除我想要的记录。我们在生产中更改、插入或删除数据的所有代码都必须包含在事务中。如果它是手动运行的,则在看到受影响的记录数之前不要运行回滚或提交。

使用嵌入式选择删除的示例

delete a
--select a.* from 
from table1 a 
join table 2 b on a.id = b.id
where b.somefield = 'test'

但即使是这些技术也不能防止所有的人为错误。不了解数据的开发人员可能会运行 select 并且仍然不了解它正在删除太多记录。当人们忘记提交或回滚并锁定系统时,在事务中运行可能意味着您会遇到其他问题。或者人们可能将它放在一个事务中并且仍然不假思索地点击提交,就像如果有一个消息框他们会点击确认一样。最好的预防措施是有一种方法可以快速从此类错误中恢复。从审计日志表中恢复往往比从备份中恢复更快。另外,您还可以知道谁犯了错误以及哪些记录受到了影响(也许您没有删除整个表,但您的 where 子句是错误的,并且您删除了一些错误的记录。)

在大多数情况下,不应即时更改生产数据。您应该编写更改脚本并首先在 dev 上检查它。然后在 prod 上,您所要做的就是在不做任何更改的情况下运行脚本,而不是一次突出显示并运行小块。现在在现实世界中,这并不总是可能的,因为有时您只在需要修复的产品上修复损坏的东西(例如,当您的客户都无法登录时,因为关键数据已被删除)。在这种情况下,您可能无法先在 dev 上重现问题,然后再编写修复程序。当您遇到这些类型的问题时,您可能需要直接在 prod 上进行修复,并且您应该只有 dbas 或数据库分析师、配置经理或其他通常负责 prod 数据的人而不是开发人员来修复。

于 2008-11-11T18:45:59.450 回答
2

因此,连续第二天,有人清除了整个数据表,而不是他们试图删除的一行,因为他们没有合格的 where 子句

可能唯一的解决方案是用其他人替换某人。否则他们总会找到解决方法

最终限制该人的数据库访问,并为他们提供存储过程,该存储过程采用 where 子句中使用的参数,并授予他们执行该存储过程的访问权限。

于 2008-11-11T18:28:19.297 回答
2

这就是为什么我认为您应该始终:

1 在部署到生产之前使用在开发数据库上测试的存储过程

2 选择删除前的数据

3 使用面试和绩效评估流程筛选开发人员 :)

4 基于他们删除/不删除多少数据库表的性能评估

5 把生产数据当作有毒的,非常害怕

于 2008-11-11T16:25:52.713 回答
1

穿上你最好的 Trogdor 和 Burninate,直到他们学会使用 WHERE 子句。

最好的建议是让那些在数据库中乱七八糟的垃圾在测试时使用事务。它对防止“哎呀”时刻大有帮助。需要注意的是,现在您必须告诉他们 COMMIT 或 ROLLBACK,因为他们肯定会至少锁定您的数据库一次。

于 2008-11-11T16:27:49.743 回答
1

锁定它:

REVOKE删除所有表的权限。

放入审计触发器和审计表。

创建参数化删除 SP 并仅授予根据需要执行的权限。

于 2008-11-11T18:59:18.847 回答
0

难道没有办法在不提供对 SQL 的原始访问权限的情况下为用户提供他们需要的结果吗?如果您至少有一个单独的“WHERE”输入框,则可以将其默认为“WHERE 1 = 0”或其他内容。

我认为也必须有一种方法可以将这些从事务日志中删除。但可能并非没有回滚所有内容,然后有选择地重新应用致命错误之后出现的任何内容。

另一个丑陋的选择是创建一个触发器,将所有 DELETE(可能超过某个最小记录数)写入日志表。

于 2008-11-11T18:55:04.830 回答