因此,连续第二天,有人清除了整个数据表,而不是他们试图删除的那一行,因为他们没有合格的where子句。
我一直在mgmt工作室选项上下,但找不到确认选项。我知道其他数据库的其他工具也有它。
答案 0 :(得分:16)
我建议您总是首先使用WHERE子句编写SELECT语句并执行它以实际查看DELETE命令将删除哪些行。然后使用相同的WHERE子句执行DELETE。这同样适用于UPDATE。
答案 1 :(得分:13)
在工具>选项>查询执行> SQL Server> ANSI下,您可以启用隐式交易选项,这意味着您无需显式包含“开始交易”命令。
明显的缺点是你可能忘记在最后添加一个Commit(或Rollback),或者更糟糕的是,你的同事默认会在每个脚本的末尾添加Commit。
你可以把马带到水中......
您可能会建议他们在执行任何之前总是进行临时备份(具体取决于数据库的大小)以防万一。
答案 2 :(得分:4)
在运行BEGIN TRANSACTION
声明之前尝试使用DELETE
。
然后您可以选择COMMIT
或ROLLBACK
相同。
答案 3 :(得分:4)
首先,这是审计表的用途。如果您知道谁删除了所有记录,您可以限制其数据库权限或从性能角度处理它们。在我办公室做这件事的最后一个人目前正在试用期。如果她再次这样做,她将被释放。如果您有权访问生产数据并确保您不会造成任何伤害,那么您就有责任。这是一个性能问题和技术问题一样多。你永远不会找到一种方法来防止人们犯下愚蠢的错误(数据库无法知道你是否意味着删除表a或删除表id = 100并且确认将被大多数人自动命中)。您只能通过确保运行此代码的人员负责并通过制定策略来帮助他们记住该做什么来尝试减少它们。对您的公交数据不负责任的行为(特别是在发出警告后)的员工应被解雇。
其他人已经建议我们采取哪些措施来防止这种情况发生。我总是在一个删除中嵌入一个select,我正在从查询窗口运行,以确保它只删除我想要的记录。我们在生产中更改,插入或删除数据的所有代码都必须包含在事务中。如果是手动运行,则在看到受影响的记录数之前,不要运行回滚或提交。
使用嵌入式选择删除的示例
delete a
--select a.* from
from table1 a
join table 2 b on a.id = b.id
where b.somefield = 'test'
但即便是这些技术也无法阻止所有人为错误。不了解数据的开发人员可能会运行选择,但仍然不明白它正在删除太多记录。在事务中运行可能意味着当人们忘记提交或回滚并锁定系统时,您会遇到其他问题。或者人们可能会把它放在一个交易中并且仍然没有考虑就像他们会在消息框上点击确认(如果有的话)。最好的预防方法是从这些错误中快速恢复。从审计日志表中恢复往往比从备份中恢复更快。此外,您还可以分辨出哪些错误以及哪些记录受到影响(可能您没有删除整个表,但是您的where子句出错并且您删除了一些错误的记录。)
在大多数情况下,生产数据不应随时更改。您应该编写更改脚本并首先在dev上进行检查。然后在prod上,您所要做的就是运行脚本而不进行任何更改,而不是突出显示并一次运行一个小块。现在,在现实世界中,这并不总是可行的,因为有时候您正在修复仅在现在需要修复的产品上打破的东西(例如,当您的客户都没有登录因为关键数据被删除时)。在这种情况下,您可能无法首先在开发人员上再现问题,然后编写修复程序。当您遇到这些类型的问题时,您可能需要直接修复prod并且您应该只有dbas或数据库分析师,或者配置管理器或通常负责prod数据的其他人执行修复而不是开发人员。一般而言,开发人员不应该访问prod。
答案 4 :(得分:3)
在SSMS 2005中,您可以在工具|选项|查询执行| SQL Server | ANSI ...下检查SET IMPLICIT_TRANSACTIONS
下启用此选项。这将需要提交以影响未来连接的更新/删除查询。
对于当前查询,请转到“查询”|“查询选项”|“执行”|“ANSI”并选中相同的框。
This page也有SSMS 2000的说明,如果你正在使用它。
正如其他人所指出的那样,这不会解决根本原因:在您创建的每个新查询的末尾粘贴COMMIT几乎一样容易,因为它首先触发查询。
答案 5 :(得分:2)
这就是为什么我相信你应该永远:
1在部署到生产之前,使用在开发人员数据库上测试的存储过程
2选择删除前的数据
3使用面试和绩效评估流程的屏幕开发人员:)
4对他们执行/不删除的数据库表的基本性能评估
5将生产数据视为有毒并且非常害怕
答案 6 :(得分:2)
因此,连续第二天,有人清除了整个数据表,而不是他们试图删除的那一行,因为他们没有合格的where子句 < / p>
可能唯一的解决方案是将某人替换为其他人;)。否则他们总会找到他们的解决方法
最终限制该人员的数据库访问权限,并为他们提供获取where子句中使用的参数的存储过程,并授予他们执行该存储过程的权限。
答案 7 :(得分:1)
穿上你最好的Trogdor和Burninate,直到他们学会放入WHERE子句。
最好的建议是在测试时获取数据库中的muckety-mucks以使用事务。它在防止“呐喊”时刻方面走了很长的路。需要注意的是,现在你必须告诉他们COMMIT或ROLLBACK,因为他们肯定会至少锁定你的数据库一次。
答案 8 :(得分:1)
将其锁定:
REVOKE
删除所有表格的权利。
加入审计触发器和审计表。
创建参数化删除SP,并仅根据需要授予执行权限。
答案 9 :(得分:0)
是否有办法在不提供SQL原始访问权限的情况下为用户提供所需的结果?如果您至少有一个单独的“WHERE”输入框,您可以将其默认为“WHERE 1 = 0”或其他。
我认为必须有办法从交易日记中支持这些。但可能并非没有将所有东西都推回去,然后有选择地重新应用在致命错误之后发生的任何事情。
另一个丑陋的选择是创建一个触发器,将所有DELETE(可能超过一些最小数量的记录)写入日志表。