是否有“你确定”存储过程执行? :)

时间:2010-03-29 15:06:28

标签: sql stored-procedures dialog confirm

我有一个存储过程正在执行大量删除操作。成千上万的记录。它不会从应用程序中运行,但我担心的是,我的一个客户意外地运行它(由于他们的“好奇心”,我之前遇到了问题):D

是。有备份和类似的东西,但我在想......不要吓唬他们......有没有办法问用户“你确定吗?”在执行之前? :) 感谢

8 个答案:

答案 0 :(得分:7)

我猜你可以有一个名为“确认”的参数,要求传入一个特定的字符串(例如,“我知道我在做什么”),如果没有设置,或设置不正确,从程序返回而不执行主代码。不完全是你想要的,但这是一个选择。

例如 - (未经测试且可能非常糟糕的语法)

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

答案 1 :(得分:6)

简而言之,没有。

该理论认为,任何有权查找并能够运行存储过程的人都应该被允许。最好限制权限,以便那些具有过度好奇心的人没有权限来运行它。

另一个不太安全的选项是需要一个需要作为参数传递的预定义秘密 - 当然他们可以通过编写存储过程的脚本来找到秘密...

当然,另一点是:如果它不可调用,为什么要包括它?毕竟,当你来做管理类型的任务时,你可以将这些语句编写成一个文件,你可以在自己的机器上保持安全

答案 2 :(得分:3)

使用多层次的方法:

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'或RETURN 999。

答案 3 :(得分:2)

您可以在sproc中添加@reallyReallyReallyDelete参数作为安全措施:如果设置为YesYesYes,则实际提交事务。

答案 4 :(得分:1)

您可以使用名为@UserKnowsWhatTheyAreDoing的位输入,并在执行前检查它是否为真。如果它是假的,打印一条友好的消息并从程序中正常返回

答案 5 :(得分:1)

该过程可能需要具有特定值的参数,例如'Yes I know what I'm doing'。或者它可能会寻找一个特殊的表格,其中包含类似的确认和最近的时间戳。

答案 6 :(得分:1)

这是另一种方法,我认为这种方法适用于直接由用户而不是应用程序调用过程的特定情况。

我必须说,与大多数其他建议相比,它为用户提出了更少的麻烦,而开发人员的建议更多(可能是不成比例)。你决定它是否适合你。

无论如何,这里有。

首先,创建一个特殊的表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秒到半分钟的间隔对我来说似乎很自然。你可以选择不同的数字。

答案 7 :(得分:0)

您是否真的要从数据库中删除它们?如果我能负担得起额外的空间,我会在我的表格和最后更新的列中放置一个“已删除”标记。这样,如果记录被意外删除,至少我通常可以追踪它并相当容易地恢复它。只是一个想法。