سؤال

لنفترض أن لدي جدول قاعدة بيانات يحتوي على عمود توقيت في آخر مرة تم تحديثها أو إدراجها. الذي سيكون من الأفضل:

  1. لديك تحديث الزناد الحقل.
  2. اطلب من البرنامج الذي يقوم بتعيين الحقل الإدراج/التحديث.

يبدو أن الخيار الأول هو الأسهل لأنني لست مضطرًا حتى إلى إعادة ترجمة للقيام بذلك ، لكن هذه ليست صفقة ضخمة حقًا. بخلاف ذلك ، أواجه مشكلة في التفكير في أي أسباب للقيام بها على الآخر. أي اقتراحات؟

هل كانت مفيدة؟

المحلول

يمكن أن يكون الخيار الأول أكثر قوة لأن قاعدة البيانات ستحافظ على الحقل. هذا يأتي مع النفقات العامة المحتملة لاستخدام المشغلات.

إذا كان بإمكانك كتابة تطبيقات أخرى إلى هذا الجدول في المستقبل ، عبر واجهاتها الخاصة ، فسأذهب مع الزناد حتى لا تكرر هذا المنطق في أي مكان آخر.

إذا كان التطبيق الخاص بك إلى حد كبير ، أو سيصل أي تطبيقات أخرى إلى قاعدة البيانات من خلال نفس Datalayer ، فأنا أتجنب هذا الكابوس الذي يمكن أن يحفز المنطق ووضع المنطق مباشرة في Datalayer (SQL ، ORM ، Procs المخزنة ، إلخ. ).

بالطبع ، يجب عليك التأكد من أن المصدر الخاص بك (تطبيقك ، أجهزة الكمبيوتر الخاصة بالمستخدمين ، خادم SQL الخاص بك) دقيق في كلتا الحالتين.


فيما يتعلق لماذا لا أحب المشغلات:

ربما كنت طفحًا عن طريق وصفهم كابوسًا. مثل كل شيء آخر ، فهي مناسبة في الاعتدال. إذا كنت تستخدمها لأشياء بسيطة للغاية مثل هذه ، فيمكنني الحصول على متنها.

عندما يصبح رمز الزناد معقدًا (ومكلفًا) الذي يؤدي إلى بدء الكثير من المشكلات. إنها ضريبة مخفية على كل استعلام إدراج/تحديث/حذف تقوم بتنفيذها (اعتمادًا على نوع الزناد). إذا كانت هذه الضريبة مقبولة ، فيمكنها أن تكون الأداة المناسبة للوظيفة.

نصائح أخرى

لم تذكر 3. استخدم إجراءً مخزنًا لتحديث الجدول. يمكن أن يضع الإجراء الطوابع الزمنية حسب الرغبة.

ربما هذا غير ممكن بالنسبة لك ، لكنني لم أره المذكور.

أود أن أقول الزناد فقط في حالة استخدام شخص ما إلى جانب تطبيقك لتحديث الجدول ، وربما تريد أيضًا أن يكون لديك lastupdatedby واستخدام suser_sname () لذلك ، بهذه الطريقة يمكنك معرفة من قام بالتحديث

طالما أنني أستخدم DBMs في مشغلاتها ، فإنني دائمًا ما أذهب مع خيار الزناد. إنها تتيح لـ DBMs رعاية أكبر عدد ممكن من الأشياء ، والتي عادة ما تكون أمرًا جيدًا.

تعمل تأكد من أي ظرف من ظهور عمود الطابع الزمني للقيمة الصحيحة. سيكون النفقات العامة ضئيلة.

الشيء الوحيد الذي سيكون ضد المشغلات هو قابلية النقل. إذا لم تكن هذه مشكلة ، فلا أعتقد أن هناك سؤالًا في الاتجاه الذي يجب أن يذهب إليه.

أنا مؤيد للإجراءات المخزنة لكل شيء. يمكن أن يحتوي التحديث الخاص بك على getDate () للعمود.

وأنا لا أحب مشغلات هذا النوع من التحديث. عدم رؤية المشغلات يميل إلى التسبب في الارتباك.

هذا يبدو وكأنه منطق العمل بالنسبة لي ... سأكون أكثر تخلصًا من وضع هذا في الكود. دع قاعدة البيانات تدير تخزين البيانات ... لا أكثر ولا أقل.

المشغلات هي نعمة ولعنة.

البركة: يمكنك استخدامها لتمكين جميع أنواع فحص القيد المخصص وإدارة البيانات دون معرفة أو تغيير أنظمة الواجهة الخلفية.

لعنة: أنت لا تعرف ما يحدث وراء ظهرك. قضايا التزامن/deadlocks حسب كائنات إضافية يتم إحضارها إلى المعاملات التي لم يكن متوقعًا من الناحية الأصلية. سلوك الوهمية بما في ذلك تغييرات بيئة الجلسة ، عدد غير موثوق به. الإفراط في التشغيل للظروف .. عقوبات ساخنة/عقوبات في الأداء.

الإجابة على هذا السؤال (تواريخ التحديث ضمنيًا (الزناد) أو بشكل صريح (رمز)) الأوزان بشكل كبير على السياق. وض .

إذا كنت تستخدم الزناد لتغيير التزامن أو لم يكن لديك أي تحكم في التعليمات البرمجية التي تنفذ الزناد أكثر منطقية.

نصيحتي حول الزناد استخدامها لتوخي الحذر. تتيح لك معظم الأنظمة تصفية التنفيذ بناءً على العملية وتغيير الحقول. يمكن أن يكون للاستخدام السليم لـ "قبل" VS "بعد" المشغلات تأثيرات أداء كبيرة.

أخيرًا ، يمكن لبعض الأنظمة قادرة على تنفيذ مشغل واحد على تغييرات متعددة (صفوف متعددة تم تنفيذها في معاملة) يجب أن يكون الكود الخاص بك مستعدًا لتطبيق نفسه كتحديث كبير على صفوف متعددة.

عادةً ما أقول أن تفعل ذلك جانب قاعدة البيانات ، لكن ذلك يعتمد على تطبيقك. إذا كنت تستخدم LINQ-to-SQL ، يمكنك فقط تعيين الحقل كطابع زمني وجعل DAL الخاص بك يستخدم حقل الطابع الزمني للتزامن. إنه يتولى ذلك لك تلقائيًا ، لذا فإن التكرار رمز هو حدث غير.

إذا كنت تكتب DAL بنفسك ، فسأكون أكثر عرضة للتعامل مع هذا على جانب قاعدة البيانات لأنه يجعل كتابة واجهات المستخدم أكثر مرونة - على الرغم من أنني من المحتمل أن أفعل ذلك في إجراء مخزن "يحتوي على" الجمهور " "الوصول والجداول المقفلة - لا تريد فقط أي مهرج قادم وتجاوز إجراءك المخزن عن طريق الكتابة إلى الجداول مباشرة ... ما لم تكن تخطط لجعل DAL مكونًا مستقلًا يجب أن يستخدمه أي تطبيق مستقبلي للوصول إليه قاعدة البيانات ، وفي هذه الحالة ، يمكنك تدوينها مباشرة في DAL - بالطبع ، يجب عليك القيام بذلك فقط إذا كان بإمكانك ضمان أن كل شخص يصل إلى قاعدة البيانات يقوم بذلك من خلال مكون DAL الخاص بك.

إذا كنت ستسمح للوصول "العام" إلى قاعدة البيانات بإدراجها في الجداول ، فسيتعين عليك الذهاب مع الزناد لأنه بخلاف ذلك ، يمكن لأي شخص إدراج/تحديث حقل واحد في الجدول ولا يمكن تحديث الحقل المحدث أبدًا .

سأحصل على التاريخ في قاعدة البيانات ، أي الزناد ، الإجراء المخزن ، إلخ هناك أدوات الإبلاغ ، والمقتطفات ، و SQL للمستخدم ، وما إلى ذلك. هناك أيضًا تحديثات وتصحيحات تتم من قبل DBA بأن التطبيق لن يوفر التاريخ أيضًا.

لكن بصراحة السبب الأول لن أفعل ذلك من التطبيق هو أنه ليس لديك أي تحكم في التاريخ/الوقت على جهاز العميل. قد يعودون ذلك للحصول على المزيد من أيام التجربة على شيء ما أو قد يرغبون فقط في القيام بأشياء سيئة لبرنامجك.

يمكنك القيام بذلك بدون الزناد إذا كانت قاعدة البيانات الخاصة بك تدعم القيم الافتراضية في الحقول. على سبيل المثال ، في SQL Server 2005 لدي جدول مع حقل تم إنشاؤه مثل هذا:

create table dbo.Repository
   (
    ...
   last_updated     datetime default getdate(),
    ...
   )

ثم يترك رمز الإدراج هذا الحقل خارج قائمة حقل إدراج.

لقد نسيت أن هذا يعمل فقط في أول إدراج - لديّ مشغل تحديث أيضًا ، لتحديث حقول التاريخ ووضع نسخة من السجل المحدث في جدول السجل الخاص بي - والذي سأقوم بنشره ... لكن المحرر يظل يخطئ في الخارج على الكود الخاص بي ...

أخيراً:

create trigger dbo.Repository_Upd on dbo.Repository instead of update
as
--**************************************************************************
--   Trigger: Repository_Upd
--    Author: Ron Savage
--      Date: 09/28/2008
--
-- Description:
-- This trigger sets the last_updated and updated_by fields before the update
-- and puts a copy of the updated row into the Repository_History table.
--
-- Modification History:
-- Date        Init  Comment
-- 10/22/2008  RS    Blocked .prm files from updating the history as they
--                   get updated every time the cfg file is run.
-- 10/21/2008  RS    Updated the insert into the history table to use the
--                   d.last_updated field from the Repository table rather
--                   than getdate() to avoid micro second differences.
-- 09/28/2008  RS    Created.
--**************************************************************************
begin
   --***********************************************************************
   -- Update the record but fill in the updated_by, updated_system and
   -- last_updated date with current information.
   --***********************************************************************
   update cr set
      cr.filename           = i.filename,
      cr.created_by         = i.created_by,
      cr.created_system     = i.created_system,
      cr.create_date        = i.create_date,
      cr.updated_by         = user,
      cr.updated_system     = host_name(),
      cr.last_updated       = getdate(),
      cr.content            = i.content
   from
      Repository cr

      JOIN Inserted i
         on (i.config_id = cr.config_id);


   --***********************************************************************
   -- Put a copy in the history table
   --***********************************************************************
   declare @extention varchar(3);
   select @extention = lower(right(filename,3)) from Inserted;

   if (@extention <> 'prm')
      begin
      Insert into Repository_History
         select
            i.config_id,
            i.filename,
            i.created_by,
            i.created_system,
            i.create_date,
            user           as updated_by,
            host_name()    as updated_system,
            d.last_updated,
            d.content
         from
            Inserted i

            JOIN Repository d
               on (d.config_id = i.config_id);
      end
end

رون

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