외래 키를 기본 키로 사용해도 괜찮습니까?


103

두 개의 테이블이 있습니다.

  • 사용자 (사용자 이름, 비밀번호)
  • 프로필 (profileId, 성별, 생년월일, ...)

현재 저는이 방법을 사용하고 있습니다. 각 프로필 레코드에는 외래 키로 "userId"라는 필드가 있습니다. User 테이블에 연결 가 있습니다. 사용자가 등록하면 그의 프로필 레코드가 자동으로 생성됩니다.

내 친구 제안과 혼동됩니다. "userId"필드를 외래기본 키로 사용하고 "profileId"필드를 삭제합니다. 어떤 접근 방식이 더 낫습니까?


3
Entity Framework는 zeroOrOne (및 1) 대 1 관계에 대해 코드를 먼저 생성합니다. 그래서 ... 가능합니다. 그게 최선의 방법인가요 ... 또 다른 질문입니다. 그러나 그것은 유효합니다. 나는 내 자신의 데이터베이스를 만드는 동안 그렇게 한 적이 없다 (그러나 나는 그것을 생각조차하지 않았다).
Raphaël Althaus

답변:


132

외래 키는 거의 항상 "중복 허용"이므로 기본 키로 적합하지 않습니다.

대신 테이블의 각 레코드를 고유하게 식별하는 필드를 찾거나 기본 키 역할을 할 새 필드 (자동 증가 정수 또는 GUID)를 추가하십시오.

이에 대한 유일한 예외 는 연결된 테이블 의 외래 키와 기본 키가 하나이고 동일한 일대일 관계가있는 테이블입니다.


74
두 개의 외래 키로 구성된 복합 기본 키는 다 대다 관계를 구현하는데도 완벽합니다.
rightfold

1
@rezadru : rightfold에 동의하지 않을 수는 없지만 대리 키가 거의 항상 더 나은 선택입니다.
Robert Harvey 19

4
외래 키에 대한 어떤 것도 일대 다 (또는 기록 된대로 "중복 허용")임을 지시하지 않습니다. 키 제약 조건과 고유성은 데이터베이스에서 두 개의 개별 개념이며 인덱스를 추가하는 것처럼 쉽게 혼합 될 수 있습니다 (세 번째 개별 개념이 됨).
blindguy

40

기본 키는 항상 고유해야하며 테이블이 일대 다 관계인 경우 외래 키는 고유하지 않은 값을 허용해야합니다. 테이블이 일대 다 관계가 아닌 일대일 관계로 연결된 경우 외래 키를 기본 키로 사용하는 것이 좋습니다. 동일한 사용자 레코드에 둘 이상의 관련 프로필 레코드가있을 가능성이있는 경우 별도의 기본 키를 사용하고 그렇지 않으면 보유한 것을 유지하십시오.


11

예, 기본 키가 외래 키인 것은 합법적입니다. 이것은 드문 구조이지만 다음에 적용됩니다.

  • 1 : 1 관계. 서로 다른 권한과 권한이 테이블 수준에서만 적용되기 때문에 두 테이블을 하나로 병합 할 수 없습니다 (2017 년 현재 이러한 데이터베이스는 이상 할 수 있음).

  • 1 : 0..1 관계. 프로필은 사용자 유형에 따라 존재하거나 존재하지 않을 수 있습니다.

  • 성능이 문제이며 디자인이 파티션 역할을합니다. 프로필 테이블은 거의 액세스되지 않거나 별도의 디스크에서 호스팅되거나 사용자 테이블과 비교하여 다른 샤딩 정책이 있습니다. 밑줄이있는 스토리지가 원주 형이면 의미가 없습니다.


테이블을 자주 조인하면 성능이 저하되어 1 개의 테이블이 더 좋다는 일반적인 권장 사항으로 이어집니다. 어떤 경우에는 데이터가 조인되지 않고 항상 개별적으로 액세스되며, 1 : 1 관계를 가진 두 개의 테이블을 갖는 것이 조직적인 이점이있을 수 있습니다.
blindguy

4

일대일 관계를 갖는 것은 일반적으로 나쁜 습관으로 간주됩니다. 이는 데이터를 하나의 테이블에 표시하고 동일한 결과를 얻을 수 있기 때문입니다.

그러나 참조하는 테이블에 대해 이러한 변경을 수행 할 수없는 경우가 있습니다. 이 경우 외래 키를 기본 키로 사용하는 데 문제가 없습니다. 자동 증분 고유 기본 키와 외래 키로 구성된 복합 키가 있으면 도움이 될 수 있습니다.

현재 사용자가 로그인하여 앱에 사용할 등록 코드를 생성 할 수있는 시스템을 개발 중입니다. 이유 때문에 사용자 테이블에 필요한 열을 간단히 추가 할 수는 없습니다. 그래서 나는 코드 테이블과 함께 일대일 경로를 내려갈 것입니다.


2
모든 데이터를 동일한 테이블에 추가 열로 포함하면 많은 이점이 있다는 데 대부분 동의합니다. wrt this .. "단지 하나의 테이블에 데이터를 표시하고 동일한 결과를 얻을 수 있습니다.".. : 별도의 테이블을 갖는 것이 유용 할 수 있습니다 (예 : 프로파일 테이블 항목이 선택 사항 인 경우). 예를 들어 모든 은행 고객이 인터넷 뱅킹 등록을하지 않았을 수 있습니다. 이 경우 IB 등록 테이블을 사용하여 다른 테이블이 추가 하위 레코드를 갖지 못하도록 제한 할 수 있습니다. 여기서도 IB 등록 테이블에 대한 새 PK로 수행 할 수 있습니다.
Teddy

1
@Teddy 마찬가지로 나는 당신이 말한 것에 대부분 동의합니다. 그러나 원래 질문에서 그들은 "... 그의 프로필 레코드가 자동으로 생성됩니다 ..."라고 말하며 이는 프로필 테이블이 선택 사항이 아님을 의미합니다. 프로필 테이블이 선택 사항 인 상황에서는 별도의 테이블로 사용할 수 있습니다. 그러나 다시 동일한 테이블에서 nullable 열을 사용할 수 있습니다.
Tshsmith

1
별도의 두 번째 테이블을 사용하면 두 번째 테이블에 항목이있는 사람에게만 허용되는 세 번째 테이블의 항목을 방지 할 수 있습니다.
Teddy

물론입니다.하지만 1 : 1 테이블을 병합하면 null 값을 가진 사람들이 세 번째 (기술적으로 두 번째) 테이블에 액세스하는 것을 방지 할 수 있습니다. 하지만 OP가 묻는 질문에는 "... 가입 할 때 .. ... 자신의 프로필 기록이 자동으로 생성됩니다 ..."라는 줄이 포함되어 있습니다.
Tshsmith

이것을 고려하는 주된 이유는 데이터웨어 하우징에서 팩트 테이블과 차원 테이블을 분리하는 것이 좋은 습관이기 때문입니다. 별도의 팩트 및 차원 테이블은 PowerPivot, PowerBI 및 Tableau와 같은 소프트웨어로 작업 할 때 유용한 단서입니다.
Marco Rosas 2017 년

4

예, 해당 테이블 간의 일대일 관계의 경우 외래 키가 기본 키가 될 수 있습니다.


2
이것은 수퍼 타입 ​​서브 타입 설계에도 유용합니다. 하위 유형 테이블 기본 키는 수퍼 유형 테이블에 대한 외래 키 참조 여야합니다.
axelioo

2

나는 그렇게하지 않을 것입니다. 나는 profileID테이블의 기본 키로 유지 합니다.Profile

외래 키는 두 테이블 간의 참조 제약 일뿐입니다.

다른 테이블에서 참조하는 외래 키의 대상으로 기본 키가 필요하다고 주장 할 수 있습니다. 외래 키는 어떤 테이블의 기본 키 열에서 발견 된 값을 보유 할 수있는 테이블 (해당 테이블의 기본 키는 말할 것도없고 반드시 후보 키일 필요는 없음)에있는 하나 이상의 열 집합입니다. 다른 테이블. 따라서 외래 키와 일치하는 기본 키가 있어야합니다. 아니면 우리가해야합니까? 기본 키 / 외래 키 쌍에서 기본 키의 유일한 목적은 참조 된 기본 키를 보유하는 "외부"테이블에 대한 참조 무결성을 유지하기 위해 명확한 조인을 제공하는 것입니다. 이렇게하면 외래 키가 참조하는 값이 항상 유효합니다 (또는 허용되는 경우 null).

http://www.aisintl.com/case/primary_and_foreign_key.html


1
아마도-User.UserID와 Profile.UserID 사이에 FK 제약 조건이있는 경우 Profile.UserID에 대한 인덱스를 갖는 것이 좋습니다. Profile 테이블의 기본 클러스터형 인덱스를 만들어 두 번째 인덱스를 절약하고 데이터베이스 엔진에 불필요한 작업을 많이하지 않는 이유는 무엇입니까?
리버스 엔지니어

1

비즈니스와 시스템에 따라 다릅니다.

사용자 ID가 고유하고 항상 고유 한 경우 userId를 기본 키로 사용할 수 있습니다. 하지만 시스템을 확장하고 싶다면 일이 어려워 질 것입니다. 테이블 프로필에 외래 키를 추가하는 대신 테이블 프로필과의 관계를 만들기 위해 테이블 ​​사용자에 외래 키를 추가하는 것이 좋습니다.


0

짧은 대답 : DEPENDS ....이 특별한 경우에는 괜찮을 수 있습니다. 그러나 전문가들은 매번 반대 할 것을 권장합니다. 귀하의 경우를 포함하여.

왜?

키가 해당 테이블에 대해 외부 (다른 테이블에서 시작됨) 인 경우 테이블에서 거의 고유하지 않습니다. 예를 들어, 동일한 유형의 항목이 다른 주문에 존재할 가능성이 높기 때문에 항목 ID는 ITEMS 테이블에서는 고유하지만 ORDERS 테이블에서는 고유하지 않을 수 있습니다. 마찬가지로 주문 ID는 ORDERS 테이블에서 고유 할 수 있지만 여러 라인 항목이있는 주문이 존재할 수있는 ORDER_DETAILS와 같은 다른 테이블에서는 그렇지 않을 수 있으며 특정 주문의 특정 항목에 대해 쿼리하려면 두 개의 연결이 필요합니다. 이 테이블의 PK로 FK (order_id 및 item_id).

저는 DB 전문가는 아니지만 자동 생성 된 값을 PK로 논리적으로 정당화 할 수 있다면 그렇게 할 것입니다. 이것이 실용적이지 않다면 두 개 (또는 그 이상)의 FK 연결이 PK 역할을 할 수 있습니다. 그러나 단일 FK 값이 PK로 정당화 될 수있는 경우는 생각할 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.