2010-03-29 37 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秒到半分鐘的時間間隔對我來說似乎很自然。你可以選擇不同的數字。