2008-11-06 5 views
2

테이블 구조가 있습니다. 나는 최선의 방법을 만드는 방법을 잘 모릅니다.외래 키를 참조하는 복합 테이블

기본적으로 나는 두 개의 테이블, tblSystemItems 및 tblClientItems가 있습니다. '항목'을 참조하는 열이있는 세 번째 테이블이 있습니다. 문제는이 열이 시스템 항목이나 클라이언트 항목을 참조해야한다는 것입니다. 시스템 항목에는 1..2^31 범위의 키가 있지만 클라이언트 항목에는 -1 .. -2^31 범위의 키가 있으므로 충돌이 발생하지 않습니다.

항목을 쿼리 할 때마다 두 테이블의 내용 사이에 UNION ALL을 수행하는 뷰를 통해이를 수행합니다.

따라서 뷰를 항상 고유하게 유지하면서 뷰가 항상 두 테이블의 합집합이되므로 외래 키 참조를 뷰의 결과로 만들고 싶습니다. 그러나 내가 견해를 언급 할 수 없기 때문에 나는 이것을 할 수 없다.

이제 외래 키를 삭제할 수 있으며 모든 것이 정상입니다. 그러나, 난 정말 일부 참조 검사 및 계단식 삭제/null 기능을 설정하고 싶습니다. 트리거 외에, 이것을 할 방법이 있습니까?

+0

피트 (Pete)의 사랑을 위해 "TBL"로 표를 붙이지 마십시오. 그것은 총체적이고 구역질이 나고 동시에 두려울 것입니다. –

답변

1

늦게 답변을 드려 죄송합니다. 주말염의 심각한 사례에 시달렸습니다.

클라이언트 테이블과 시스템 테이블 모두에서 PKs를 포함시키기 위해 세 번째 테이블을 사용하는 경우 - 동기화가 복잡하고 앱이 세 번째 테이블을 알아야합니다.

또 다른 문제는 아이템이나 시스템 또는 클라이언트를 참조해야하는 세 번째 테이블이 있는데 문제가되지 않는다는 것입니다. 테이블을 분리한다는 것은 기본적으로 ClientItemID와 SystemItemID라는 두 개의 열이 필요하다는 것을 의미합니다. 각 열에는 각 테이블에 대해 null 허용 가능성이있는 제약 조건이 있습니다.

결국 다른 해결책을 선택했습니다. 모든 문제는 클라이언트 항목을 망치지 않고 충돌을 피하는 등의 방식으로 테이블에 새로운 시스템 항목을 쉽게 동기화 할 수있었습니다.

결국 테이블 하나만 만들게되었습니다. Items에는 "SystemItem"이라는 비트 열이 있습니다.이 열은 분명히 명백합니다. 내 개발/시스템 데이터베이스에서 PK를 int identity (1,1)로 사용했습니다. 클라이언트 데이터베이스에서 테이블을 만든 후 ID 키는 (-1, -1)로 변경됩니다. 즉, 시스템 항목이 긍정적 인 상태 일 때 클라이언트 항목이 부정적으로 표시됩니다.

동기화의 경우 IDENTITY INSERT ON을 사용하여 나머지를 동기화하는 동안 (SystemItem = 1) 기본적으로 무시됩니다. 따라서 클라이언트 항목을 완전히 무시하고 충돌을 피하면서 동기화 할 수 있습니다. 또한 클라이언트 항목과 시스템 항목을 모두 다루는 단 하나의 "항목"테이블을 참조 할 수 있습니다. 명심해야 할 것은 표준 클러스터 키를 수정하여 클라이언트가 새 항목을 삽입 할 때 모든 종류의 페이지 재구성 (클라이언트 업데이트 대 시스템 업데이트가 99 %/1 %와 같은 경우)을 피하기 위해 내림차순으로 지정하는 것입니다.

0

아마도 두 테이블의 모든 기본 키를 저장하는 tblItems 테이블이 필요할 것입니다. 항목을 삽입하려면 항목이 tblSystemItems 테이블에 입력되면 PK가 tblItems 테이블에 입력되도록 두 단계가 필요합니다.

세 번째 테이블에는 FK to tblItems가 있습니다. tblItems는 다른 두 항목 테이블의 부모입니다. 항목을 쿼리하려면 tblItems, tblSystemItems 및 tblClientItems 사이에 JOIN을 작성해야합니다.

[편집 - 아래 의견] tblSystemItems 및 tblClientItems가 자체 PK를 제어하는 ​​경우에도 여전히 허용 할 수 있습니다. 처음에는 tblSystemItems에 삽입 한 다음 tblItems에 삽입합니다. 당신이 Hibernate 같은 도구를 사용하여 상속 구조를 구현할 때 당신은 이런 식으로 끝날 것이다.

+0

하지만 tblSystemItems 테이블에 변경을 푸시하면 tblItems 테이블을 포함하는 PK를 동기화하는 번거 로움이 있습니다. 최적의 방법으로 tblSystemItems 테이블을 클라이언트 항목과 완전히 독립적으로 작동시키고 싶습니다. –

0

당신은 고유 ID (DB 생성 - 순서, 자동 증가 (Autoinc) 등)을 만들 수있는 항목을 참조하는 테이블을, 당신은 시스템 항목 및 클라이언트 항목을 참조하는 두 개의 추가 열 (tblSystemItemsFKtblClientItemsFk)를 만들 각각 일부 데이터베이스는 nullable 인 외래 키를 가질 수 있습니다.

ORM을 사용하는 경우 열 정보 만 기반으로 클라이언트 항목과 시스템 항목을 쉽게 구분할 수 있습니다 (ID 중복 방지를 위해 음수 식별자가 필요하지 않음).

더 많은 bakcground/context를 사용하면 최적의 솔루션을 결정하는 것이 더 쉽습니다.

+0

* 일부 데이터베이스 만 널 (null) 외래 키를 가질 수 있습니까? * 일부 데이터베이스만으로도 OUTER JOIN을 할 수 있습니까? – Powerlord

0

Item이라는 테이블을 PK ItemiD로 추가하고 ItemType = "System"또는 "Client"라는 단일 열에 ClientItems 테이블 PK (ClientItemId)와 SystemItems PK (SystemItemId)를 둘 다 Item에 대한 FK로 만듭니다. .ItemId, (이러한 관계는 0-1)

다음 항목을 참조하는 세 번째 테이블에서이 추가 (항목) 테이블에서 itemId를 참조하는 FK 제약 조건 만 있습니다.

삽입을 구현하는 저장 프로 시저를 사용하는 경우 항목을 삽입하는 저장된 proc를 먼저 Items 테이블에 새 레코드를 삽입 한 다음 해당 테이블의 자동 생성 된 PK 값을 사용하여 실제 데이터 레코드 시스템이 Items 테이블 ItemId 열에 삽입 한 자동 생성 (ID) 값을 사용하여 동일한 저장된 proc 호출의 일부로 SystemItems 또는 ClientItems (해당 항목에 따라 다름)에 저장합니다.

이것을 "하위 분류"라고합니다.

0

저는 테이블 디자인에 의문을 품고 있습니다. 나는 그것이 옳다는 확신이 없다. 세 번째 테이블은 세부 정보를 제공 할 수도 있지만 기본 키가 실제로는 ITEM 테이블에 있고, FOREIGN 키가 시스템 및 클라이언트 항목 테이블에있는 것임을 알 수는 없습니다. 그런 다음 Item에서 시스템 및 클라이언트 항목 테이블로 바로 바깥 조인을 수행하면 모든 제약 조건이 정상적으로 작동합니다.

0

나는 내가 사용하고있는 데이터베이스에서 비슷한 상황에 처해있다. 각 테이블에 EntityID라고하는 "후보 키"가 있습니다. 그런 다음 다른 테이블 중 둘 이상에있는 항목을 참조해야하는 테이블이 있으면 해당 행을 참조하기 위해 EntityID를 사용합니다. EntityID가 Entity 테이블의 기본 키이고 다른 모든 EntityID가 FKs가되도록 모든 참조를 교차시키는 엔티티 테이블이 있지만 엔티티 테이블을 자주 사용하지 않습니다.

관련 문제