正如标题所示,如果没有WHERE子句,则我们希望防止-至少通过手动接口-UPDATE和DELETE语句在特定的SQL Server(2008或更高版本)数据库或表上执行。
有可能吗?
答案 0 :(得分:4)
可以。这并不理想,但是您可以创建表触发器来评估每个UPDATE
和DELETE
以确定它们将影响多少行。
Erik Darling在Brent Ozar's blog上写了关于它的博客。无论是他还是我都不一定会推荐它,但是如果情况非常迫切,那将是可行的。
这里是链接中的相关代码,以防万一,Brent停业。他很轻浮。
CREATE OR ALTER TRIGGER dbo.UseAWhereClauseNextTime
ON dbo.TriggerTest
FOR UPDATE, DELETE
AS
BEGIN
DECLARE @rc INT = @@ROWCOUNT;
DECLARE @table_rows INT = ( SELECT row_count
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.TriggerTest')
AND index_id IN ( 0, 1 ));
IF EXISTS ( SELECT 1 FROM Inserted ) AND EXISTS ( SELECT 1 FROM Deleted )
BEGIN
IF (( @rc * 100 ) / ( @table_rows )) >= 98
BEGIN
RAISERROR('USE A WHERE CLAUSE DUMMY', 0, 1) WITH NOWAIT;
ROLLBACK;
END;
END;
IF NOT EXISTS ( SELECT 1 FROM Inserted ) AND EXISTS ( SELECT 1 FROM Deleted )
IF ( ( @table_rows = 0 )
OR ( @table_rows > 0
AND (( @rc * 100 ) / ( @table_rows + @rc )) >= 98 ))
BEGIN
RAISERROR('USE A WHERE CLAUSE DUMMY', 0, 1) WITH NOWAIT;
ROLLBACK;
END;
END;
GO
带有(( @rc * 100 ) / ( @table_rows )) >= 98
的两个子句将“不良”语句的阈值设置为受影响表的98%,Erik指出这是任意的,但也是可配置的。
答案 1 :(得分:2)
我认为您是在问错问题。您要防止删除删除所有行(或较高百分比的行)的删除,而不是阻止不具有WHERE
子句的删除。
无论是恶意的,草率的,有意的还是无意的,我都可以轻松地取消对显式WHERE
子句的任何分析,并且仍然删除所有行。
DELETE dbo.table WHERE 1 = 1;
DELETE dbo.table WHERE key_column > 0;
无论有意还是无意,我都可以解雇,不阅读或不小心按下Enter键,或者对插件提供的任何弹出式窗口进行错误的鼠标单击,仅因为插件向我发出警告,我就不会并不意味着它会阻止我做我尝试做的事情。
当然,如果您认为缺少WHERE
子句意味着它将删除所有行,那么您可以错误地阻止仅影响一行的查询。即使没有找到WHERE
子句,以下所有语句也应限制为一个受影响的行(或更多具有联系的行):
DELETE TOP (1) dbo.table;
;WITH RowToDelete AS
(
SELECT key_column FROM dbo.table
GROUP BY key_column
HAVING (key_column = 1)
)
DELETE RowToDelete;
;WITH RowToDelete AS
(
SELECT key_column, rn = ROW_NUMBER() OVER (ORDER BY key_column)
FROM dbo.table
)
DELETE TOP (1) RowToDelete;
如果您想实际上防止意外删除所有行,则可以按照另一个答案中的建议在触发器中执行此操作,只要记住触发器就可以了,并请注意,这对truncate
或drop
或transfer
没有帮助。
答案 2 :(得分:0)
如果您在谈论 Microsoft SQL Server Management Studio ,那么您可以选择使用名为SSMSBoost的插件。
有了它,当您运行DELETE
而没有WHERE
时,您将始终得到警告。现在,我不确定100%是否可以为UPDATE
进行配置,但可能是。