كيف يمكنك تخزين أنشطة الأعمال في قاعدة بيانات SQL؟

StackOverflow https://stackoverflow.com/questions/1931581

  •  20-09-2019
  •  | 
  •  

سؤال

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

أحد الحلول التي أفكر فيها هو استخدام جدول واحد لكل سجل ليتم تتبعه. هنا مثال مبسط:

CREATE TABLE ActivityTypes
(
    TypeId              int IDENTITY(1,1)       NOT NULL,
    TypeName            nvarchar(50)            NOT NULL,

    CONSTRAINT PK_ActivityTypes          PRIMARY KEY (TypeId),
    CONSTRAINT UK_ActivityTypes          UNIQUE (TypeName)
)

INSERT INTO ActivityTypes (TypeName) VALUES ('WidgetRotated');
INSERT INTO ActivityTypes (TypeName) VALUES ('WidgetFlipped');
INSERT INTO ActivityTypes (TypeName) VALUES ('DingBatPushed');
INSERT INTO ActivityTypes (TypeName) VALUES ('ButtonAddedToDingBat');

CREATE TABLE Activities
(
    ActivityId          int IDENTITY(1,1)       NOT NULL,
    TypeId              int                     NOT NULL,
    AccountId           int                     NOT NULL,
    TimeStamp           datetime                NOT NULL,

    CONSTRAINT PK_Activities                      PRIMARY KEY (ActivityId),
    CONSTRAINT FK_Activities_ActivityTypes        FOREIGN KEY (TypeId)
                                                  REFERENCES ActivityTypes (TypeId),
    CONSTRAINT FK_Activities_Accounts             FOREIGN KEY (AccountId)
                                                  REFERENCES Accounts (AccountId)
)

CREATE TABLE WidgetActivities
(
    ActivityId          int                     NOT NULL,
    WidgetId            int                     NOT NULL,

    CONSTRAINT PK_WidgetActivities                  PRIMARY KEY (ActivityId),
    CONSTRAINT FK_WidgetActivities_Activities       FOREIGN KEY (ActivityId)
                                                    REFERENCES Activities (ActivityId),
    CONSTRAINT FK_WidgetActivities_Widgets          FOREIGN KEY (WidgetId)
                                                    REFERENCES Widgets (WidgetId)
)

CREATE TABLE DingBatActivities
(
    ActivityId          int                     NOT NULL,
    DingBatId           int                     NOT NULL,
    ButtonId            int,

    CONSTRAINT PK_DingBatActivities                  PRIMARY KEY (ActivityId),
    CONSTRAINT FK_DingBatActivities_Activities       FOREIGN KEY (ActivityId)
                                                     REFERENCES Activities (ActivityId),
    CONSTRAINT FK_DingBatActivities_DingBats         FOREIGN KEY (DingBatId)
                                                     REFERENCES DingBats (DingBatId)
    CONSTRAINT FK_DingBatActivities_Buttons          FOREIGN KEY (ButtonId)
                                                     REFERENCES Buttons (ButtonId)
)

يبدو هذا الحل جيدًا لجلب جميع الأنشطة التي تم إعطاؤها معرفًا عن عنصر واجهة مستخدم أو Dingbat ، ومع ذلك لا يبدو جيدًا لجلب جميع الأنشطة ثم محاولة تحديد السجل الذي يشيرون إليه.

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

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

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

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

تبحث عن بعض الأفكار الأخرى وكيف تتنازل تلك الأفكار بين جهود البرمجة ، وتكامل البيانات ، والأداء ، والمرونة في الإبلاغ.

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

المحلول

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

CREATE TABLE Objects   -- Bad table name, should be more specific
(
     object_id     INT          NOT NULL,
     name          VARCHAR(20)  NOT NULL,
     CONSTRAINT PK_Application_Objects PRIMARY KEY CLUSTERED (application_id)
)

CREATE TABLE Widgets
(
     object_id     INT           NOT NULL,
     height        DECIMAL(5, 2) NOT NULL,
     width         DECIMAL(5, 2) NOT NULL,
     CONSTRAINT PK_Widgets PRIMARY KEY CLUSTERED (object_id),
     CONSTRAINT FK_Widgets_Objects
     FOREIGN KEY (object_id) REFERENCES Objects (object_id)
)

CREATE TABLE Dingbats
(
     object_id     INT           NOT NULL,
     label         VARCHAR(50)   NOT NULL,
     CONSTRAINT PK_Dingbats PRIMARY KEY CLUSTERED (object_id),
     CONSTRAINT FK_Dingbats_Objects
     FOREIGN KEY (object_id) REFERENCES Objects (object_id)
)

الآن لأنشطتك:

CREATE TABLE Object_Activities
(
     activity_id     INT          NOT NULL,
     object_id       INT          NOT NULL,
     activity_type   INT          NOT NULL,
     activity_time   DATETIME     NOT NULL,
     account_id      INT          NOT NULL,
     CONSTRAINT PK_Object_Activities PRIMARY KEY CLUSTERED (activity_id),
     CONSTRAINT FK_Object_Activities_Objects
     FOREIGN KEY (object_id) REFERENCES Objects (object_id),
     CONSTRAINT FK_Object_Activities_Activity_Types
     FOREIGN KEY (activity_type) REFERENCES Activity_Types (activity_type),
)

CREATE TABLE Dingbat_Activities
(
     activity_id     INT     NOT NULL,
     button_id       INT     NOT NULL,
     CONSTRAINT PK_Dingbat_Activities PRIMARY KEY CLUSTERED (activity_id),
     CONSTRAINT FK_Dingbat_Activities_Object_Activities
     FOREIGN KEY (activity_id) REFERENCES Object_Activities (activity_id),
     CONSTRAINT FK_Dingbat_Activities_Buttons
     FOREIGN KEY (button_id) REFERENCES Object_Activities (button_id),
)

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

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

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

نصائح أخرى

سأخرج على أحد الأطراف وأخذ بعض التخمينات البرية حول ما تحاول تحقيقه حقًا.

أنت تقول إنك تحاول تتبع "أنشطة المتجر" سأفترض أن لديك الأنشطة التالية: شراء عنصر جديد بيع العنصر الشطب

حسنًا ، لهذه الأنشطة ، تحتاج إلى بعض الجداول المختلفة: واحدة للمخزون ، وواحد للإدارات ، وواحدة للموظفين

يمكن أن يكون لجدول المخزون المعلومات التالية:

inventory:
  item_id (pk)
  description (varchar)
  number_in_stock (number)
  cost_wholesale (number)
  retail_price (number)
  dept_id (fk)

department:
  dept_id (pk)
  description (varchar)

employee
  emp_id (pk)
  first_name (varchar)
  last_name (varchar)
  salary (number)
  hire_date (date)
  fire_date (date)

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

عندما تقوم بتوظيف موظف جديد ، يمكنك إضافة سجل منهم إلى طاولة الموظفين. عندما تدفع لهم ، يمكنك الاستيلاء على راتبهم من عمود الراتب. عندما تطلق النار عليهم ، تملأ هذا العمود لسجلهم (وتوقف عن دفعهم).


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

عند تصميم قاعدة بيانات ، فإن السؤال الذي تحتاج إلى طرحه هو "ماذا علي أن أفعل؟" إنها "ما هي المعلومات التي أحتاجها لتتبعها؟"

إجابة جديدة ، استنادًا إلى تفسير مختلف للسؤال.

هل تحاول فقط الاحتفاظ بقائمة لما حدث؟ إذا كنت بحاجة فقط إلى قائمة مطلوبة بالأحداث الماضية ، فأنت بحاجة فقط إلى جدول واحد:

action_list
  action_list_id (pk)
  action_desc (varchar)

event_log:
  event_log_id (pk)
  event_time (timestamp)
  action_list_id (fk)
  new_action_added (fk)
  action_details_or_description (varchar)

في هذا ، سيكون Action_List شيئًا مثل:

1   'WidgetRotated'
2   'WidgetFlipped'
3   'DingBatPushed'
4   'AddNewAction'
5   'DeleteExistingAction'

سيكون event_log قائمة بالأنشطة التي حدثت ، ومتى. أحد أفعالك هو "إضافة إجراء جديد" وسيتطلب ملء عمود "new_action_added" على جدول الحدث في أي وقت يتخذ فيه الإجراء "إضافة إجراء جديد".

يمكنك إنشاء إجراءات للتحديث ، وإزالتها ، وإضافة ، إلخ.

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

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

ماذا عن سجلات SQL؟

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

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