Есть ли «вы уверены» для выполнения хранимой процедуры? :) - PullRequest
6 голосов
/ 29 марта 2010

У меня есть хранимая процедура, которая делает много удалений. Сотни тысяч записей. Он не будет запущен из приложения, но все же, я обеспокоен тем, что один из моих клиентов случайно запустил его (у меня раньше были проблемы из-за их "любопытства"): D

Да. есть резервные копии и тому подобное, но я подумал ... не пугать их ... есть ли способ спросить пользователя "ты уверен?" перед тем как его выполнить? :) спасибо

Ответы [ 8 ]

7 голосов
/ 29 марта 2010

Полагаю, у вас может быть параметр «подтверждение», требующий передачи определенной строки (например, «Я знаю, что я делаю»), если она не установлена ​​или установлена ​​неправильно, просто возврат из процедуры без выполнения основного кода. Не совсем то, что вы хотели, но это вариант.

например - (непроверенный и, вероятно, ужасный синтаксис)

CREATE PROCEDURE dbo.mySproc (
@Confirmation Varchar(100)
) AS
BEGIN
    if(@Confirmation <> 'I know what I am doing')
    BEGIN
        return;
    END
    DELETE from table_name where condition
END
6 голосов
/ 29 марта 2010

Короче, нет.

Теория гласит, что любому, у кого есть права на поиск и возможность запуска хранимой процедуры, должно быть разрешено. Было бы лучше ограничить разрешения, чтобы у людей с чрезмерным любопытством не было разрешений для запуска этого.

Другой, менее безопасный вариант - требовать предварительно определенный секрет, который необходимо передать в качестве параметра - конечно, они могут просто отключить хранимую процедуру, чтобы найти секрет, хотя ...

Конечно, другой момент: если он не вызывается, зачем его включать? В конце концов, когда вы приступаете к выполнению задач типа администратора, операторы могут быть записаны в виде файла, который вы можете сохранить в безопасности на своем компьютере

3 голосов
/ 29 марта 2010

использовать многоуровневый подход:

1) контроль выполнения безопасности, как:

GRANT EXECUTE ON [dbo].[yourProcedure] TO [userxyz]

2) используйте действительно описательное / страшное имя процедуры, например

CREATE PROCEDURE Will_Delete_All_Your_Data ...

3) поместите большой привлекательный комментарий в начале хранимой процедуры

--NOTE, will delete all of your data--
--NOTE, will delete all of your data--
--NOTE, will delete all of your data--
--NOTE, will delete all of your data--
--NOTE, will delete all of your data--

4) сделать так, чтобы пользователь передавал запутанный специальный код доступа:

CREATE PROCEDURE Will_Delete_All_Your_Data
(
    @SpecialCode varchar(30)
)

IF @SpecialCode!=CHAR(83)+CHAR(112)+CHAR(101)+CHAR(99)+CHAR(105)+CHAR(97)+CHAR(108)+CHAR(67)+CHAR(111)+CHAR(100)+CHAR(101)
BEGIN
    RETURN 999
END
...

К вашему сведению, специальный код должен быть 'SpecialCode', или нажмите 911 *.

2 голосов
/ 29 марта 2010

Вы можете добавить параметр @reallyReallyReallyDelete в sproc, который будет служить мерой безопасности: если он установлен на YesYesYes, то фактически совершит транзакцию.

1 голос
/ 24 января 2011

Вот еще один подход, который, я думаю, подходит для конкретного случая, когда процедура должна вызываться пользователем напрямую, а не из приложения.

Я должен сказать, что он предлагает меньше проблем для пользователя, а больше (возможно, непропорционально) для разработчика по сравнению с большинством других предложений. Вы сами решаете, подходит ли вам это.

Во всяком случае, здесь идет.

Сначала вы создаете специальную таблицу, CriticalCalls, для регистрации вызовов критических процедур. Таблица будет иметь такую ​​структуру:

SPID int,
ProcName sysname,
CallTime datetime

По сути, идея состоит в том, что критический SP должен вызываться дважды: сначала он регистрирует свой вызов и информирует пользователя повторить вызов в течение определенного интервала времени в качестве подтверждения своего намерения, а во втором вызове, если сделанный соответствующим образом, он фактически выполняет свою задачу.

Таким образом, начальная часть каждой критической процедуры будет иметь такую ​​логику:

IF NOT EXISTS (
  SELECT *
  FROM CriticalCalls
  WHERE SPID = @@SPID AND ProcName = @ThisProcName
    AND GETDATE() - CallTime BETWEEN @LowerCallTimeLimit AND @UpperCallTimeLimit
    /* the actual test for the time interval might be somewhat different */
) BEGIN
  ...  /* upsert CriticalCalls with the current time stamp */
  PRINT 'To proceed, please call this procedure again within...';
  RETURN;
END;

DELETE FROM CriticalCalls WHERE SPID = @@SPID AND ProcName = @ThisProcName;

...  /* proceed with your critical task */

На самом деле, я думаю, было бы лучше использовать специальный SP (названный CheckCriticalCalls ниже) для всех манипуляций с CriticalCalls, включая все необходимые модификации. CheckCriticalCalls получит имя проверяемой процедуры и вернет флаг, показывающий, должна ли указанная процедура выполнять свою реальную операцию.

Так что это может выглядеть примерно так:

EXECUTE @result = CheckCriticalCalls 'ThisProcedureName';
IF @result = -1 BEGIN
  PRINT 'Call me again';
  RETURN;
END;

...  /* go on with the task */

Идея установки нижнего предела интервала заключается в том, чтобы просто запретить пользователю дважды вызывать критическую процедуру автоматически, т. Е. Путем выполнения двух идентичных EXECUTE... строк в одном пакете. Конечно, верхний предел необходим для 1) обеспечения того, чтобы пользователь подтвердил свое недавнее намерение выполнить критическую операцию; 2) предотвратить выполнение, если существующая запись в CriticalCalls фактически оставлена ​​там из прошлого сеанса с тем же SPID.

Так что, в принципе, интервал от 1-2 секунд до полминуты показался бы мне вполне естественным. Вместо этого вы можете выбрать другие цифры.

1 голос
/ 29 марта 2010

Для процедуры может потребоваться аргумент с определенным значением, например 'Yes I know what I'm doing'. Или он может искать строку в специальной таблице с аналогичным подтверждением и недавней отметкой времени.

1 голос
/ 29 марта 2010

Вы можете использовать битовый ввод с именем @UserKnowsWhatTheyAreDoing и проверить, верно ли это перед выполнением. Если значение равно false, напечатайте дружеское сообщение и изящно вернитесь из процедуры

0 голосов
/ 29 марта 2010

Вам нужно ДЕЙСТВИТЕЛЬНО удалить их из БД? Если я смогу позволить себе дополнительное место, я добавлю флаг «Удаленный» в свои таблицы и последний обновленный столбец. Таким образом, если запись была случайно удалена, по крайней мере, я обычно могу отследить и восстановить ее довольно легко. Просто мысль.

...