1

테이블 간의 간단한 일대 다 관계가있는 데이터베이스 스키마를 디자인하는 방법을 알고 있습니다. 컨벤션이나 모범 사례가 해당 세트의 특정 관계를 기본 컨텍스트로 지정하는 것이 무엇인지 알고 싶습니다. 예를 들어, 한 사람이 많은 신용 카드를 가지고 있습니다. 나는 그것을 모델링하는 방법을 안다. 그 카드 중 하나를 그 사람의 기본 카드로 어떻게 지정합니까? 내가 생각해 낸 해결책은 기껏해야 비관적으로 보입니다.테이블 간의 일대 다 관계에서 기본 관계를 지정하는 규칙은 무엇입니까?


실제 상황을 명확히하려고 노력하겠습니다. (안타깝게도 실제 도메인은 일을 혼동시킬뿐입니다.) 많은 열이있는 각각 2 개의 테이블이 있으며 Person과 Task를 가정 해 봅시다. 나는 또한 단지 몇 가지 속성을 가지고 프로젝트가 있습니다. 한 사람에게는 많은 프로젝트가 있지만 기본 프로젝트가 있습니다. 하나의 프로젝트에는 많은 작업이 있지만 때로는 대체 작업이있는 하나의 기본 작업이 있고 다른 시간에는 기본 작업이없고 대신 작업 시퀀스가 ​​있습니다. 프로젝트의 일부가 아닌 작업은 없지만 엄격하게 금지되지는 않습니다.

PERSON (PERSON_ID, NAME, ...) 
TASK (TASK_ID, NAME, DESC, EST, ...) 
PROJECT (NAME, DESC) 

나는 overcomplexity 또는 순수 악 중 하나를 도입하지 않고 동시에 주요 프로젝트, 주요 작업 및 작업 순서 모두를 모델링하는 방법을 알아낼 수없는 것.

이것은 내가 지금까지 가지고 올 것 중에 최고입니다 :

PERSON (PERSON_ID, NAME, ...) 
TASK (TASK_ID, NAME, DESC, EST, ...) 
PROJECT (PROJECT_ID, PERSON_FK, TASK_FK, INDEX, NAME, DESC) 
PERSON_PRIMARY_PROJECT (PERSON_FK, PROJECT_FK) 
PROJECT_PRIMARY_TASK (PROJECT_FK, TASK_FK) 

그냥 간단한 개념에 대한 너무 많은 테이블처럼 보인다.


다음은 매우 유사한 상황을 다루는 것으로 질문 : Database Design: Circular dependency입니다.

불행히도 상황을 처리하는 방법에 대한 합의가없는 것처럼 보였습니다. "올바른"대답은 데이터베이스 일관성 검사 메커니즘을 비활성화하는 것이 었습니다. 쿨하지 않아.

+1

그 해결책은 무엇인가? –

답변

3

글쎄, 사람이 신용 카드와 2 개의 관계가 있다고 생각됩니다. 하나는 소유하고 다른 하나는 기본 신용 카드로 간주한다는 것입니다. 그건 당신이 일대일과 일 대 다 관계라는 것을 말해줍니다. 일대 다 관계로 인해 일대일 관계의 반환 관계가 이미 신용 카드에 있습니다.

즉, Person의 필드로 primary_cc_id를 추가하고 CreditCard 만 남겨 두었습니다.

+1

순환 참조로 간주되지 않습니까? –

+0

@speedmetal : 순환 참조 일 수도 있지만 나쁜 것입니까? 모든 솔루션에는 데이터 일관성 문제가 있습니다. CreditCard에 비트 필드를 추가하면 기본 카드가 둘 이상인 사람의 위험이 있습니다. 내 솔루션은 사람이 소유하지 않은 기본 카드의 위험을 감수합니다. 내 솔루션은 다소 빨라질 가능성이 있으며 가능한 데이터 일관성 문제를 확인하는 것이 더 쉽다고 생각합니다. – Omnifarious

+0

저의 (제한적) 이해는 순환 참조가 나쁜 것임을 이해합니다. 이 질문을 확인하십시오 : http://stackoverflow.com/questions/1387252/database-design-circular-dependency –

2

두 전략 :

  1. 은 단련 시킨다면 카드를 표시하는 비트 열을 사용합니다.
  2. PrefferedCardTable을 사용하여 각 개인을 자신이 선호하는 카드의 ID와 연관시킵니다.
+0

1. 비트 열이 지저분한 해결책이라고 느꼈습니다. 그냥 냄새 테스트를 통과하지 못했습니다. 2. 나는이 방향으로 갈지 모른다. 다른 테이블이 필요하지 않아야하는 것처럼 보일뿐입니다. 나는 내가 먼저 얻는 다른 아이디어를 볼 것입니다. 감사. –

+0

쿼리 성능, 공간 및 확장 성간에 균형이 맞지 않습니다. 비트 솔루션은 공간이 거의 필요하지 않으며 매우 빠르며 데이터베이스를 최소한으로 확장해야합니다 (새로운 열, 인덱스가없는 추가 테이블 없음). 두 번째 솔루션은보다 깨끗하고 확장 성이 뛰어나지 만 더 많은 작업과 추가 조인이 필요합니다. –

+2

비트 열 솔루션이 마음에 들지 않습니다. 단 하나의 기본 카드의 제약 조건을 잘 표현하지 못하기 때문입니다. 추가 테이블은 person_id의 기본 키를 가지므로 기본적으로 person 테이블에 새 컬럼을 추가합니다. – Omnifarious

0

한 명은 많은 신용 카드를 보유 할 수 있습니다. 그런 다음 각 신용 카드의 식별자를 실제로 특정 신용 카드를 한 개인에게 연결해야합니다. 귀하가 이미 모델에서 만든 것으로 가정합니다 (그 사람을 해당 신용 카드로 연결시키는 ID).

기본 신용 카드 (예 : 기본 신용 카드라고 생각하십니까?) 수동 작업 일 수밖에 없습니다 (예 : 세 번째 테이블이있어서 그 둘을 연결하고 하나의 기본값이됩니다).

Person (SSN, Name) 
CreditCard (CCID, AccountNumber) 
P_CC (SSN, CCID, NoID) 

은 그래서 당신이 신용 카드로 사람을 연결하는 경우, 당신이 속한 신용 카드를 찾아 '1'말하는대로 그런 다음 NOID를 지정, 기본적으로 쿼리를 디자인해야 할 것이다 것을 의미 NoID가 '1'인이 개인에게

물론 이것은 단지 한 가지 방법입니다. 어쩌면 0, 1로 제한하고 신용 카드가 그 사람에게 추가 된 날짜별로 정렬하고 싶을 수도 있습니다.

열과 아이디어에 대해 더 자세히 설명하면 쉽게 알 수 있습니다.

0

그래서 여기 Northwind 및 C# Windows App을 사용해 보았습니다. 단 하나의 쿼리 만 실행했습니다.

내 코드 :

DataClasses1DataContext context = new DataClasses1DataContext(); 
      DataLoadOptions dlo = new DataLoadOptions(); 
      dlo.LoadWith<Product>(b => b.Category); 
      context.LoadOptions = dlo; 

      context.DeferredLoadingEnabled = false; 

      context.Log = Console.Out; 


      List<Product> test = context.Products.ToList(); 


      MessageBox.Show(test[0].Category.CategoryName); 

결과 :

SELECT [t0].[ProductID], [t0].[ProductName], [t0].[SupplierID], [t0].[CategoryID], [t0].[QuantityPerUnit], [t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitsOnOrder], [t0].[ReorderLevel], [t0].[Discontinued], [t2].[test], [t2].[CategoryID] AS [CategoryID2], [t2].[CategoryName], [t2].[Description], [t2].[Picture] 
FROM [dbo].[Products] AS [t0] 
LEFT OUTER JOIN (
    SELECT 1 AS [test], [t1].[CategoryID], [t1].[CategoryName], [t1].[Description], [t1].[Picture] 
    FROM [dbo].[Categories] AS [t1] 
    ) AS [t2] ON [t2].[CategoryID] = [t0].[CategoryID] 
관련 문제