هل هناك "هل أنت متأكد" لتنفيذ الإجراء المخزن؟:)
-
23-09-2019 - |
سؤال
لدي إجراء مخزن يقوم بالكثير من الحذف.مئات الآلاف من السجلات.لن يكون قابلاً للتشغيل من التطبيق، ولكن ما زلت أشعر بالقلق من أن أحد عملائي يقوم بتشغيله عن طريق الخطأ (واجهت مشكلات سابقًا بسبب "فضولهم"):D
نعم.هناك نسخ احتياطية وأشياء من هذا القبيل، ولكن كنت أفكر ....لا لتخويفهم..هل هناك طريقة لسؤال المستخدم "هل أنت متأكد؟" قبل تنفيذها؟:) شكرًا
المحلول
أعتقد أنه يمكن أن يكون لديك معلمة تسمى "تأكيد" تتطلب سلسلة محددة (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
نصائح أخرى
باختصار ، لا.
تقول النظرية أنه ينبغي السماح لأي شخص لديه أذونات للعثور على إجراء مخزن. سيكون من الأفضل تقييد الأذونات حتى لا يكون لدى أولئك الذين لديهم فضول زائد الأذونات لتشغيل هذا.
والخيار الآخر ، الأقل أمانًا ، هو طلب سر محدد مسبقًا يجب تمريره كمعلمة - بالطبع يمكنهم فقط نص الإجراء المخزن للعثور على السر على الرغم من ...
بالطبع ، ستكون النقطة الأخرى هي: إذا لم تكن قابلة للاتصال ، فلماذا تضمها؟ بعد كل شيء ، عندما تأتي للقيام بمهام نوع المسؤول ، يمكنك أن تتم كتابة العبارات كملف يمكنك الحفاظ عليه آمنًا على جهازك الخاص
استخدم نهجًا متعدد الطبقات:
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
...
لمعلوماتك ، يجب أن يكون الرمز الخاص "رمز خاص" أو إرجاع 999.
يمكنك إضافة ملف @reallyReallyReallyDelete
المعلمة إلى sproc والتي ستكون بمثابة مقياس السلامة: إذا تم تعيينه على YesYesYes
سوف يرتكب المعاملة بالفعل.
يمكنك استخدام المدخلات قليلا تسمى @UserKnowsWhatTheyAreDoing
وتحقق لمعرفة ما إذا كان هذا صحيحًا قبل التنفيذ. إذا كانت خاطئة ، فقم بطباعة رسالة ودية والعودة بأمان من الإجراء
قد يتطلب الإجراء وسيطة ذات قيمة محددة ، مثل 'Yes I know what I'm doing'
. أو قد يبحث عن صف جدول خاص مع تأكيد مماثل وجهاز زمني حديث.
إليك طريقة أخرى، والتي أعتقد أنها مناسبة لحالة معينة عندما يتم استدعاء الإجراء من قبل المستخدم مباشرة وليس من التطبيق.
يجب أن أقول أنه يقترح مشكلة أقل للمستخدم بينما يسبب المزيد (ربما بشكل غير متناسب) للمطور مقارنة بمعظم الاقتراحات الأخرى.عليك أن تقرر ما إذا كان يناسبك.
على أية حال، هنا يذهب.
أولاً، قم بإنشاء جدول خاص، 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 ثانية إلى نصف دقيقة قد يبدو طبيعيًا تمامًا بالنسبة لي.يمكنك اختيار أرقام مختلفة بدلا من ذلك.
هل تحتاج حقًا إلى حذفها من DB؟ إذا كان بإمكاني شراء المساحة الإضافية ، فسوف أضع علامة "محذوفة" في طاولاتي وعمود آخر محدث. وبهذه الطريقة إذا تم حذف السجل بطريق الخطأ على الأقل ، يمكنني عادة تتبعه واستعادته بسهولة إلى حد ما. مجرد فكرة.