SQL2005 : 테이블을 여러 테이블에 연결하고 Ref Integrity를 ​​유지 하시겠습니까?


3

다음은 데이터베이스의 단순화입니다.

Table: Property 
Fields: ID, Address 

Table: Quote 
Fields: ID, PropertyID, BespokeQuoteFields... 

Table: Job 
Fields: ID, PropertyID, BespokeJobFields...

그런 다음 Quote Job 테이블과 관련된 다른 테이블이 있습니다.

이제 사용자가 작업 및 견적과 관련하여 고객이 남긴 전화 메시지를 녹음 할 수있는 Message 테이블을 추가해야합니다.

두 개의 동일한 테이블 ( QuoteMessage JobMessage)을 만들 수 있지만 이는 DRY 원칙에 위배되며 지저분 해 보입니다.

하나의 메시지 테이블을 만들 수 있습니다 :

Table: Message 
Fields: ID, RelationID, RelationType, OtherFields...

그러나 이것은 참조 무결성을 적용하기 위해 제약 조건을 사용하지 못하도록합니다. 나는 또한 나중에 SQL에 Linq를 사용하여 devlopment 측면과 문제를 만드는 forsee 수 있습니다.

이 문제에 대한 우아한 해결책이 있습니까? 아니면 궁극적으로 함께 해킹해야할까요?

번즈

4

고유의 MessageID와 당신이 메시지를 저장하는 데 필요한 다양한 속성을 포함하는 하나 개의 메시지 테이블을 만듭니다.

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

두 개의 링크 테이블 (QuoteMessage 및 JobMessage)을 생성하십시오. 여기에는 각각 두 개의 필드, 견적/작업 외래 키 및 메시지가 포함됩니다. 당신은 단지 한 곳에서 메시지의 데이터 속성을 정의 이런 식으로

Table: QuoteMessage 
Fields: QuoteId, MessageId 

Table: JobMessage 
Fields: JobId, MessageId 

는 (연장하고, 모든 메시지를 통해 쿼리를 쉽게 만들기), 그러나 당신은 또한에 따옴표와 채용 정보를 연결하는 참조 무결성을 임의의 수의 메시지. 실제로 견적과 작업 모두 메시지에 연결할 수 있습니다 (비즈니스 모델에 적합한 지 확실하지 않지만 적어도 데이터 모델은 옵션을 제공합니다).


1

내가 생각할 수있는 유일한 다른 방법은 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가 적고 정규화가 더 중요합니다. 모델링하는 두 가지가 동일한 속성 (열)을 가지고 있지만 실제로는 다른 것들 (테이블) 인 경우 유사한 스키마를 가진 여러 테이블을 갖는 것이 합리적입니다.서로 다른 것들을 뒤섞는 것보다 훨씬 낫다.


1

@burns 이안 답변 (+1)

[참고 참조] 올. 많은 테이블을 QUOTEMESSAGE에 사용하면 QUOTE에서 MESSAGE이 가장 정확한 모델이지만 고아가 된 MESSAGE 레코드는 그대로 남습니다.

이것은 희귀 한 사람이 트리거를 사용할 수있는 경우 중 하나입니다. 단 하나의 MESSAGE 레코드가 QUOTEJOB과 연관 될 수 없도록하려면주의를 기울여야합니다. 이안에

create trigger quotemessage_trg 
on quotemessage 
for delete 
as 
begin 

delete 
from [message] 
where [message].[msg_id] in 
    (select [msg_id] from Deleted); 

end 

주, 나는 열 JobId, MessageId을해야 JobMessage의 테이블 정의에 오타가 있다고 생각 (?). 나는 당신의 견적을 편집 하겠지만, 저의 명성을 얻으려면 몇 년이 걸릴 수도 있습니다!


0

메시지 테이블에 QuoteId와 JobId 필드가 모두있는 것은 아닙니까? 아니면 메시지가 견적이나 직업에 관한 것이지 둘 다에 관한 것이 아닙니다.