Navicat 部落格

防止預存程序刪除所有記錄 2020 年 10 月 6 日,由 Robert Gravelle 撰寫

允許某些使用者對資料表執行特定更新或刪除是相當普遍的。像這樣的資料操縱語言(Data Manipulation Language,DML)操作始終存在風險,如果有人在沒有使用 WHERE 子句的情況下意外發出 DELETE 命令,從而刪除資料表中的所有列,就可能會發生事故!幸運的是,你可以採取一些簡單的步驟來防止意外(或故意!)破壞性的 DML 操作。我們將在今天的文章中研究其中的幾個步驟。

危險的刪除程序

首先,讓我們以一個預存程序開始,該預存程序將根據使用者提供的 WHERE 子句刪除資料表中的列。Navicat for SQL Server開發和管理用戶端中顯示的此 SQL Server程序接受 tablewhereclause 參數,並傳回刪除的列數:

delete_from_table_procedure (106K)

在 Navicat 中,我們可以透過「執行」按鈕直接在編輯器中執行一個程序。按一下它會彈出一個對話方塊以輸入參數:

input_param_dialog (21K)

delcnt 指定了我們希望刪除的記錄數目。若將其保留為空白,如果刪除了任何列,交易會回溯並保留列。如果我們輸入一個數字,該程序將在刪除作業之後比較數字與 @@rowcount 伺服器變數,以確定刪除的記錄數目是否符合期望的數目。在我們的例子中,將顯示一段訊息,告訴我們將會刪除多少列:

would_have_been_deleted_message (30K)

如預期的那樣,actcnt 為零,確認實際上沒有刪除任何列:

actcnt_variable (20K)

delcnt 參數充當內建的安全屏障,因為它強制使用者指定他或她希望刪除多少列。我們還可以透過檢查是否提供了 whereclause 參數來增加多一層安全保護:

whereclause_check (17K)

delcnt 變數檢查最大化

不允許空白 WHERE 子句並非沒有缺點,因為沒有方法可以阻止使用者輸入「id not null」之類的東西。關於此安全檢查,我們頂多能說至少檢查只有在使用者故意刪除資料表中的所有列的情況下才會失敗。

因此,也許更好的方案可能是擴大比較受影響(已刪除)列的實際計數和預期計數(@delcnt)的概念。僅需幾行程式碼,我們就可以計算資料表中的列數。如果受影響的列數等於資料表中的總列數,則回溯交易。這可以使用內建的 sp_executesql 預存程序來完成。它支援使用輸入和輸出參數,因此我們可以將 count(*) 函式的結果儲存至變數中。以下是新的程式碼:

delete_from_table_procedure_with_actcnt_check (148K)

現在,如果我們嘗試執行一個將刪除資料除表中所有列的查詢,如下所示:

input_param_dialog_with_destructive_whereclause_param (21K)

...刪除會被阻止:

actcnt_variable_check_validation_message (22K)

總結

雖然沒有可靠的方法來防止由於意外或故意刪除而造成的資料遺失,但是我們採用的每一種對策都有助於將發生災難性事件的機會降至最低。

如果你對 Navicat for SQL Server 感興趣,可以免費 試用 14 天!

Navicat 文章
頻道記錄
分享
部落格封存檔