سؤال

لدي إجراء مخزن يقوم بالكثير من الحذف.مئات الآلاف من السجلات.لن يكون قابلاً للتشغيل من التطبيق، ولكن ما زلت أشعر بالقلق من أن أحد عملائي يقوم بتشغيله عن طريق الخطأ (واجهت مشكلات سابقًا بسبب "فضولهم"):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؟ إذا كان بإمكاني شراء المساحة الإضافية ، فسوف أضع علامة "محذوفة" في طاولاتي وعمود آخر محدث. وبهذه الطريقة إذا تم حذف السجل بطريق الخطأ على الأقل ، يمكنني عادة تتبعه واستعادته بسهولة إلى حد ما. مجرد فكرة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top