SQL2005:ربط جدول بجداول متعددة والاحتفاظ بتكامل المرجع؟
-
09-06-2019 - |
سؤال
فيما يلي تبسيط لقاعدة البيانات الخاصة بي:
Table: Property Fields: ID, Address Table: Quote Fields: ID, PropertyID, BespokeQuoteFields... Table: Job Fields: ID, PropertyID, BespokeJobFields...
ثم لدينا جداول أخرى تتعلق يقتبس و وظيفة الجداول بشكل فردي.
أحتاج الآن إلى إضافة أ رسالة جدول حيث يمكن للمستخدمين تسجيل الرسائل الهاتفية التي تركها العملاء فيما يتعلق بالوظائف وعروض الأسعار.
يمكنني إنشاء جدولين متطابقين (رسالة الاقتباس و رسالة الوظيفة)، ولكن هذا ينتهك مبدأ DRY ويبدو فوضويًا.
يمكنني إنشاء واحدة رسالة طاولة:
Table: Message Fields: ID, RelationID, RelationType, OtherFields...
لكن هذا يمنعني من استخدام القيود لفرض التكامل المرجعي الخاص بي.يمكنني أيضًا أن أتوقع حدوث مشكلات في جانب التطوير باستخدام Linq إلى SQL لاحقًا.
هل هناك حل أنيق لهذه المشكلة، أم أنني سأضطر في النهاية إلى اختراق شيء ما معًا؟
الحروق
المحلول
قم بإنشاء جدول رسائل واحد، يحتوي على معرف رسالة فريد والخصائص المتنوعة التي تحتاج إلى تخزينها للرسالة.
Table: Message
Fields: Id, TimeReceived, MessageDetails, WhateverElse...
قم بإنشاء جدولي ارتباطات - QuoteMessage وJobMessage.ستحتوي هذه على حقلين فقط، المفاتيح الخارجية للاقتباس/الوظيفة والرسالة.
Table: QuoteMessage
Fields: QuoteId, MessageId
Table: JobMessage
Fields: JobId, MessageId
بهذه الطريقة، تكون قد حددت خصائص بيانات الرسالة في مكان واحد فقط (مما يجعل من السهل التوسع والاستعلام عبر جميع الرسائل)، ولكن لديك أيضًا التكامل المرجعي الذي يربط عروض الأسعار والوظائف بأي عدد من الرسائل.في الواقع، يمكن ربط كل من الاقتباس والوظيفة بـ نفس الرسالة (لست متأكدًا مما إذا كان ذلك مناسبًا لنموذج عملك، ولكن على الأقل نموذج البيانات يمنحك الخيار).
نصائح أخرى
الطريقة الأخرى الوحيدة التي يمكنني التفكير فيها هي الحصول على جدول رسائل أساسي، يحتوي على معرف وTypeId.تشير الجداول الفرعية الخاصة بك (QuoteMessage وJobMessage) بعد ذلك إلى الجدول الأساسي في كل منMessageId وTypeId - ولكن يجب أيضًا التحقق من القيود عليها لفرض messageTypeId المناسب فقط.
Table: Message
Fields: Id, MessageTypeId, Text, ...
Primary Key: Id, MessageTypeId
Unique: Id
Table: MessageType
Fields: Id, Name
Values: 1, "Quote" : 2, "Job"
Table: QuoteMessage
Fields: Id, MessageId, MessageTypeId, QuoteId
Constraints: MessageTypeId = 1
References: (MessageId, MessageTypeId) = (Message.Id, Message.MessageTypeId)
QuoteId = Quote.QuoteId
Table: JobMessage
Fields: Id, MessageId, MessageTypeId, JobId
Constraints: MessageTypeId = 2
References: (MessageId, MessageTypeId) = (Message.Id, Message.MessageTypeId)
JobId = Job.QuoteId
ما الذي يشتريه لك هذا، مقارنةً بجدول JobMessage وQuoteMessage فقط؟فهو يرفع مستوى الرسالة إلى مواطن من الدرجة الأولى، بحيث يمكنك قراءة جميع الرسائل من جدول واحد.في المقابل، فإن مسار الاستعلام الخاص بك من الرسالة إلى عرض الأسعار أو الوظيفة ذي الصلة بها يبعد مسافة انضمام واحدة أخرى.يعتمد الأمر نوعًا ما على تدفق تطبيقك سواء كانت هذه مقايضة جيدة أم لا.
أما بالنسبة للطاولتين المتطابقتين اللتين تنتهكان DRY - فلن أتوقف عن ذلك.في تصميم قاعدة البيانات، لا يتعلق الأمر بالجفاف بقدر ما يتعلق بالتطبيع.إذا كان الشيئان اللذان تقوم بتصميمهما لهما نفس السمات (الأعمدة)، لكنهما في الواقع شيئان مختلفان (الجداول) - فمن المعقول أن يكون لديك جداول متعددة بمخططات مماثلة.أفضل بكثير من عكس دمج الأشياء المختلفة معًا.
@الحروق
إجابة إيان (+1) صحيحة [انظر الملاحظة].استخدام العديد من الجداول QUOTEMESSAGE
لينضم QUOTE
ل MESSAGE
هو النموذج الأصح، لكنه سيترك يتيماً MESSAGE
السجلات.
هذا هو واحد من هؤلاء نادر الحالات التي يمكن فيها استخدام الزناد.ومع ذلك، يجب توخي الحذر لضمان أن يكون واحدًا MESSAGE
لا يمكن ربط السجل بكل من a QUOTE
و أ JOB
.
create trigger quotemessage_trg
on quotemessage
for delete
as
begin
delete
from [message]
where [message].[msg_id] in
(select [msg_id] from Deleted);
end
ملاحظة لإيان، أعتقد أن هناك خطأ مطبعي في تعريف الجدول JobMessage
, ، حيث يجب أن تكون الأعمدة JobId, MessageId
(؟).أود أن أقوم بتعديل عرض الأسعار الخاص بك ولكن قد يستغرق الأمر بضع سنوات حتى أكتسب هذا المستوى من السمعة!
لماذا لا يكون لديك حقلي QuoteId وJobId في جدول الرسائل فقط؟أو هل يجب أن تكون الرسالة بخصوص عرض أسعار أو وظيفة وليس كليهما معًا؟