2010-03-29 38 views
6

我有一个存储过程,这是做了很多删除。数十万条记录。它不会从应用程序运行,但我仍然担心,我的一个客户意外地运行它(由于他们的“好奇心”,我之前有问题):D有没有存储过程执行的“你确定”吗? :)

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

+10

为什么不为您的存储过程设置权限?这样,只有授权用户才能运行它。 – 2010-03-29 15:10:43

+0

@精英绅士:我不是说授权用户有时可能希望感觉像人类而不是机器。这个特殊情况表明,有些开发人员并不介意将用户视为凡人。 :) – 2011-01-23 23:51:08

回答

7

我想你可以有一个参数称为“确认”,需要一个特定的字符串(e,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 
+0

它可以运行,但我认为它很快会变成一个“复制并粘贴和忽略参数” – 2010-03-29 15:11:55

+4

同意,但没有什么可以阻止他们绕过任何东西,如果他们直接访问该sproc。最好在整个事情上添加适当的访问/执行安全性。 – ZombieSheep 2010-03-29 15:14:34

+0

+1我完全同意,这是一个纪律问题 – 2010-03-29 15:16:04

6

总之,没有。

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

其他的,不太安全,选择是需要一个预定义的秘密,需要作为一个参数传递 - 当然他们可能只是脚本存储过程中去寻找秘密,但...

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

1

您可以使用称为@UserKnowsWhatTheyAreDoing的位输入并检查它是否为在执行之前为true。如果它是假的,打印一条友好的消息,并从过程中优雅地返回

2

您可以将一个@reallyReallyReallyDelete参数添加到作为安全措施的存储区中:如果设置为YesYesYes将实际提交该事务。

1

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

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 
... 

FYI,特殊码必须是 'SpecialCode' 或RETURN 999被击中。

0

你需要从数据库中真正删除它们吗?如果我可以承担额外的空间,我会在我的表格中添加一个“已删除”标志,并在最后更新一列。这样,如果一条记录被意外删除,至少我通常可以将其记录下来并相当容易地恢复。只是一个想法。

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秒到半分钟的时间间隔对我来说似乎很自然。你可以选择不同的数字。