多くの削除を行っているストアド プロシージャがあります。何十万ものレコード。アプリケーションから実行することはできませんが、それでも、私のクライアントの 1 つが誤ってそれを実行するのではないかと心配しています (私は以前、彼らの「好奇心」のために問題を抱えていました) :D
はい。バックアップなどはありますが、私は考えていました....それらを怖がらせないように...ユーザーに「よろしいですか?」と尋ねる方法はありますか? 実行する前に?:) ありがとう
多くの削除を行っているストアド プロシージャがあります。何十万ものレコード。アプリケーションから実行することはできませんが、それでも、私のクライアントの 1 つが誤ってそれを実行するのではないかと心配しています (私は以前、彼らの「好奇心」のために問題を抱えていました) :D
はい。バックアップなどはありますが、私は考えていました....それらを怖がらせないように...ユーザーに「よろしいですか?」と尋ねる方法はありますか? 実行する前に?:) ありがとう
特定の文字列(たとえば、「私は何をしているのか知っています」)を渡す必要がある「確認」と呼ばれるパラメーターを使用できると思います。設定されていない場合、または正しく設定されていない場合は、メインコードを実行せずに手順を実行します。まさにあなたが望んでいたものではありませんが、それはオプションです。
例-(テストされておらず、おそらくひどい構文)
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つの安全性の低いオプションは、パラメーターとして渡す必要がある事前定義されたシークレットを要求することです-もちろん、ストアドプロシージャをオフにしてシークレットを見つけるスクリプトを作成することもできます...
もちろん、もう 1 つのポイントは、呼び出し可能でない場合、なぜそれを含めるのかということです。結局のところ、管理者タイプのタスクを実行するときは、自分のマシンで安全に保つことができるファイルとしてステートメントをスクリプト化することができます。
多層的なアプローチを使用します。
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 がヒットします。
@reallyReallyReallyDelete
安全対策として機能するパラメーターを sproc に追加できます: に設定されている場合、YesYesYes
実際にトランザクションをコミットします。
プロシージャには、 のような特定の値を持つ引数が必要な場合があります'Yes I know what I'm doing'
。または、同様の確認と最近のタイムスタンプを持つ特別なテーブルの行を探す場合があります。
これは、アプリケーションからではなく、ユーザーがプロシージャを直接呼び出す場合に適していると私が考えるさらに別のアプローチです。
他のほとんどの提案と比較して、開発者にとっては(おそらく、不均衡に)より多くの(おそらく、不均衡に)ユーザーにとってはより少ない問題を提案することを言わなければなりません. 似合うかどうかはあなたが決めてください。
とにかく、ここに行きます。
最初に、CriticalCalls
クリティカル プロシージャの呼び出しを登録する特別なテーブル を作成します。テーブルは次のような構造になります。
SPID int,
ProcName sysname,
CallTime datetime
基本的に、重要な SP は 2 回呼び出す必要があるという考え方です。最初に呼び出しを登録し、意図の確認として一定の時間内に呼び出しを繰り返すようにユーザーに通知します。それは実際にタスクの完了に進みます。
したがって、すべての重要な手順の開始部分には、次のロジックがあります。
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 */
実際には、必要なすべての変更を含め、 を使用したCheckCriticalCalls
すべての操作に専用の SP (以下に名前を付けます) を使用するのが最善だと思います。チェックするプロシージャの名前を受け取り、指定されたプロシージャが実際の操作を実行する必要があるかどうかを示す一種のフラグを返します。CriticalCalls
CheckCriticalCalls
したがって、次のようになります。
EXECUTE @result = CheckCriticalCalls 'ThisProcedureName';
IF @result = -1 BEGIN
PRINT 'Call me again';
RETURN;
END;
... /* go on with the task */
間隔の下限を設定する背後にある考え方は、ユーザーが重要な手順を自動的に 2 回呼び出すのを防ぐためです。つまり、2 つの同一EXECUTE...
の行を 1 つのバッチで実行することです。もちろん、上限は 1) 重要な操作を実行するというごく最近の意図をユーザーが確実に確認できるようにするために必要です。2) の既存のレコードがCriticalCalls
、同じ SPID を持つ過去のセッションから実際に残っている場合、実行を防ぎます。
したがって、基本的には、1 ~ 2 秒から 30 分までの間隔は、私には非常に自然に思えます。代わりに別の数字を選択することもできます。
呼び出されたビット入力を使用して、@UserKnowsWhatTheyAreDoing
実行前に真かどうかを確認できます。false の場合は、わかりやすいメッセージを出力し、手順から正常に戻ります
DBからそれらを本当に削除する必要がありますか? 余分なスペースがあれば、テーブルと最後に更新された列に「削除済み」フラグを付けます。このようにして、レコードが誤って削除された場合でも、通常はそれを追跡してかなり簡単に復元できます。ちょっとした考え。