Можно ли предотвратить выполнение операторов UPDATE или DELETE без предложения WHERE? - PullRequest
0 голосов
/ 27 ноября 2018

Как видно из заголовка, мы хотели бы предотвратить - по крайней мере, через ручной интерфейс - выполнение операторов UPDATE и DELETE в определенной БД или таблице SQL Server (2008 или выше), если у них нет предложения WHERE.

Возможно ли это?

Ответы [ 3 ]

0 голосов
/ 27 ноября 2018

Можно.Это не идеально, но вы можете создавать триггеры таблиц для оценки каждого UPDATE и DELETE, чтобы определить, на сколько строк они будут влиять.

Эрик Дарлинг писал об этом в блоге Брента Озара .Ни он, ни я не обязательно порекомендовали бы это, но если ситуация достаточно отчаянная, ну, это бы сработало.

Вот соответствующий код по ссылке, на случай, если, знаете, Брент закроет магазин.Он легкомыслен.

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% затронутой таблицы, что, как замечает Эрик, является произвольным, но также настраиваемым.

0 голосов
/ 27 ноября 2018

Я думаю, вы задаете не тот вопрос.Вы хотите предотвратить удаление, которое удаляет все строки (или некоторые высокие% строк), а не удаление, которое не имеет предложения 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.

0 голосов
/ 27 ноября 2018

Если вы говорите о Microsoft SQL Server Management studio , то у вас есть возможность использовать плагин с именем SSMSBoost .

. С ним вы всегда получитепредупреждение, когда вы работаете DELETE без WHERE.Теперь я не уверен на 100%, можно ли это настроить для UPDATE, но, вероятно, да.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...