Существует ли “вы уверены” для выполнения хранимой процедуры?:)

StackOverflow https://stackoverflow.com/questions/2538960

Вопрос

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

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

Это было полезно?

Решение

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

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

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

Другие советы

Короче говоря, нет.

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

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

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

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

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", иначе будет сбит ВОЗВРАТ 999.

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

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

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

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

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

В любом случае, поехали.

Сначала вы создаете специальную таблицу, 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 секунд до полуминуты показался бы мне вполне естественным.Вместо этого вы могли бы выбрать другие цифры.

Вам действительно нужно удалять их из базы данных?Если я смогу позволить себе дополнительное пространство, я поставлю флаг "Удалено" в своих таблицах и последний обновленный столбец.Таким образом, если запись случайно удалена, по крайней мере, я обычно могу отследить ее и восстановить довольно легко.Просто мысль.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top