SQL2005:테이블을 여러 테이블에 연결하고 참조 무결성을 유지하시겠습니까?

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

문제

내 데이터베이스를 단순화하면 다음과 같습니다.

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 to SQL을 사용하여 개발 측면에서 문제가 발생할 수도 있습니다.

이 문제에 대한 우아한 해결책이 있습니까? 아니면 궁극적으로 함께 무언가를 해킹해야 합니까?

화상

도움이 되었습니까?

해결책

고유한 MessageId와 메시지에 대해 저장해야 하는 다양한 속성을 포함하는 하나의 메시지 테이블을 만듭니다.

Table: Message
Fields: Id, TimeReceived, MessageDetails, WhateverElse...

QuoteMessage 및 JobMessage라는 두 개의 링크 테이블을 만듭니다.여기에는 각각 견적/작업에 대한 외래 키와 메시지라는 두 개의 필드만 포함됩니다.

Table: QuoteMessage
Fields: QuoteId, MessageId

Table: JobMessage
Fields: JobId, MessageId

이러한 방식으로 한 곳에서만 메시지의 데이터 속성을 정의했지만(모든 메시지에 걸쳐 쉽게 확장하고 쿼리할 수 있음) 견적 및 작업을 원하는 수의 메시지에 연결하는 참조 무결성도 갖습니다.실제로 견적과 작업 모두에 연결될 수 있습니다. 같은 메시지(귀하의 비즈니스 모델에 적합한지는 잘 모르겠지만 적어도 데이터 모델은 옵션을 제공합니다).

다른 팁

내가 생각할 수 있는 유일한 다른 방법은 Id와 TypeId가 모두 포함된 기본 메시지 테이블을 갖는 것입니다.그런 다음 하위 테이블(QuoteMessage 및 JobMessage)은 MessageId 및 TypeId 모두에서 기본 테이블을 참조하지만 적절한 MessageTypeId만 적용하기 위해 CHECK CONSTRAINTS도 포함합니다.

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

JobMesssage 및 QuoteMessage 테이블과 비교하여 이것이 무엇을 제공합니까?메시지를 일류 시민으로 승격시켜 단일 테이블에서 모든 메시지를 읽을 수 있습니다.그 대신 메시지에서 관련 견적 또는 작업까지의 쿼리 경로는 조인이 1회 더 필요합니다.그것이 좋은 균형인지 아닌지는 앱 흐름에 따라 다릅니다.

DRY를 위반하는 2개의 동일한 테이블에 관해서는 - 나는 그것에 매달리지 않을 것입니다.DB 설계에서는 DRY보다는 정규화에 더 중점을 둡니다.모델링하는 두 항목이 동일한 속성(열)을 가지고 있지만 실제로는 다른 항목(테이블)인 경우 유사한 스키마를 가진 여러 테이블을 갖는 것이 합리적입니다.서로 다른 것들을 함께 섞는 것보다 훨씬 낫습니다.

@번스

Ian의 답변 (+1)이 정확합니다. [참고 참조].다대다 테이블 사용 QUOTEMESSAGE 가입하다 QUOTE 에게 MESSAGE 가장 정확한 모델이지만 고아가 됩니다. MESSAGE 기록.

이것은 그 중 하나입니다 희귀한 트리거를 사용할 수 있는 경우.그러나 단일이 보장되도록 주의가 필요합니다. MESSAGE 레코드는 두 가지 모두와 연관될 수 없습니다. 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

Ian에게 참고하세요. 테이블 정의에 오타가 있는 것 같습니다. JobMessage, 열이 있어야 하는 위치 JobId, MessageId (?).귀하의 견적을 편집하고 싶지만 그 수준의 평판을 얻으려면 몇 년이 걸릴 수 있습니다!

메시지 테이블에 QuoteId 및 JobId 필드를 모두 포함하면 안 되는 이유는 무엇입니까?아니면 메시지가 견적이나 작업 중 하나에 관한 것이어야 하고 둘 다에 관한 것이 아니어야 합니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top