단일 테이블에 여러 개의 기본 키를 가질 수 있습니까?


답변:


559

테이블에는 두 개 이상의 열로 만들어진 기본 키인 복합 기본 키 가있을 수 있습니다 . 예를 들면 다음과 같습니다.

CREATE TABLE userdata (
  userid INT,
  userdataid INT,
  info char(200),
  primary key (userid, userdataid)
);

업데이트 : 복합 기본 키에 대한 자세한 설명 이있는 링크 가 있습니다.


2
이 예에서 고유 행을 식별 / 찾기 위해서는 BOTH userid 및 userdataid가 필요합니다. OP의 의도가 무엇인지 확실하지 않지만 여기에서 일련의 키 중 하나를 사용하여 행을 고유하게 식별 할 수 있는지 확인하려고했습니다. 예를 들어, 사용자 이름이나 사용자 ID를 가진 고유 한 사용자를 둘 다 필요로하지 않고 싶습니다. 고유 인덱스에 대한 RB의 답변이 거기에 속할 것이라고 생각합니다.
Burrito

1
@Benitok RB.의 답변 에서 언급했듯이 Unique Indexes를 사용하여 찾고있는 작업을 수행 할 수 있습니다 (동일한 테이블의 다른 고유 한 인덱스 열과 독립적 인 고유 한 인덱스 열). 사용 된 정확한 언어 구문에 대한 자세한 내용은 특정 SQL 설명서를 참조하십시오.
4AM

195

기본 키는 하나만 가질 수 있지만 기본 키에는 여러 열이있을 수 있습니다.

테이블에 고유 인덱스를 가질 수도 있습니다. 고유 인덱스는 고유 값을 적용하고 해당 값을 빠르게 쿼리 할 수 ​​있다는 점에서 기본 키와 약간 비슷합니다.


39

테이블에는 여러 개의 후보 키가있을 수 있습니다. 각 후보 키는 UNIQUE이며 함께 사용되며 NOT NULL 인 열 또는 열 집합입니다. 따라서 후보 키의 모든 열에 대한 값을 지정하면 기준을 충족하는 행이 하나 있거나 전혀 행이 없음을 판별하기에 충분합니다.

후보 키는 관계형 데이터 모델의 기본 개념입니다.

하나의 테이블에 여러 키가있는 경우 후보 키 중 하나를 기본 키로 지정하는 것이 일반적입니다. 또한 테이블의 외래 키가 다른 후보 키가 아닌 기본 키를 참조하도록하는 것이 일반적입니다.

이러한 방법을 권장하지만 관계형 모델에는 후보 키 중에서 기본 키를 선택해야하는 것은 없습니다.


5
동의했다. 논리 모델에서 모든 키는 동일합니다 ( '1 차'는 아님). 물리적 구현에서 어떤 키를 PRIMARY KEY로 지정하는지는 중재 및 공급 업체 / 제품에 따라 다릅니다.
08

3
데이터베이스 디자이너에 따라 다릅니다.
Walter Mitty 2016 년

방금 이것이 필요한 유스 케이스를 보았습니다. Entity Framework에서 작성 / 관리 할 테이블이 있습니다. 현재 수집 할 수있는 한 기본 키가 아닌 고유 복합 제약 조건을 지원하지 않습니다. 그러나 복합 기본 키는 지원하지 않습니다. 또한 데이터는 복합 키를 전혀 지원하지 않는 원격 데이터베이스 시스템에 연결됩니다. 나는 EF에서 Composite PK를 만들면서 다른 시스템이 고유하게 식별하는 데 사용할 수있는 nullable이 아닌 GUID 열을 추가했습니다.
Chris Nevill

2
Chris, 관계형 모델에는 기본 키가 필요하지 않습니다. 일부 도구에 필요한지에 대해서는 아무 말도하지 않았습니다. 그러나 나는 당신의 요점을 취합니다.
Walter Mitty

PK를 최소화해야한다는 요구가 있다고 생각합니다. 즉, 각 레코드를 고유하게 식별하기 위해 가장 적은 수의 열을 사용합니다.
gary mar

14

이것은 주요 질문과 @ 칼미의 질문에 대한 답입니다.

여러 개의 자동 생성 열이있는 점은 무엇입니까?

아래 코드에는 복합 기본 키가 있습니다. 해당 열 중 하나가 자동 증분됩니다. 이것은 MyISAM에서만 작동합니다. InnoDB는 " ERROR 1075 (42000) : 테이블 정의가 잘못되었습니다. 하나의 자동 열만있을 수 있으며 키로 정의되어야합니다 "라는 오류 가 발생합니다 .

DROP TABLE IF EXISTS `test`.`animals`;
CREATE TABLE  `test`.`animals` (
  `grp` char(30) NOT NULL,
  `id` mediumint(9) NOT NULL AUTO_INCREMENT,
  `name` char(30) NOT NULL,
  PRIMARY KEY (`grp`,`id`)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;

Which returns:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+

2
기본 키 정의에서 자동 증분 열을 먼저 지정하면 작동합니다. (이것은 아마도 5.6에서 테스트했을 것입니다)
CTarczon

11

(이걸 많이 공부 했어)

후보 키 -테이블 행을 고유하게 식별하는 데 필요한 최소 열 조합입니다.
복합 키 -2 개 이상의 열.

  • 테이블에 여러 개의 후보 키 가 존재할 수 있습니다.
    • 기본 키 - 우리 가 선택한 후보 키 중 하나만
    • 대체 키 - 다른 모든 후보 키
      • 기본 키 및 대체 키는 복합 키일 수 있습니다.

출처 :
https://en.wikipedia.org/wiki/Superkey
https://en.wikipedia.org/wiki/Candidate_key
https://en.wikipedia.org/wiki/Primary_key
https://en.wikipedia.org / wiki / Compound_key


6

다른 사람들이 지적했듯이 다중 열 기본 키를 가질 수 있습니다. 그러나 키에 의해 도입되지 않은 기능적 종속성 이있는 경우 관계를 정상화하는 것을 고려해야 합니다.

예:

Person(id, name, email, street, zip_code, area)

사이에 기능적 의존성이있을 수 있지만 id -> name,email, street, zip_code and area 종종 a zip_code는 a area와 연관 되므로 내부적 으로 기능적 의존성이 있습니다 zip_code -> area.

따라서 다른 테이블로 나누는 것을 고려할 수 있습니다.

Person(id, name, email, street, zip_code)
Area(zip_code, name)

따라서 세 번째 정규형 과 일치 합니다 .


6

기본 키는 "기본"이라는 의미와 논리적 모델과 관련된 잠재 의식적 연관성으로 인해 매우 유감스러운 표기법입니다. 따라서 사용하지 마십시오. 대신 물리적 모델의 대리 키와 논리 모델의 자연 키를 참조합니다.

모든 엔터티에 대한 논리적 모델에는 엔터티에 대한 키를 구성하는 "비즈니스 속성"집합이 하나 이상 있어야합니다. Boyce, Codd, Date 등은 관계형 모델에서 후보 키로 이것을 참조합니다. 그런 다음 이러한 엔티티에 대한 테이블을 작성하면 해당 테이블에서 후보 키가 자연 키가됩니다. 사용자는 테이블에서 행을 고유하게 식별 할 수있는 것은 자연 키를 통해서만 가능합니다. 서로 게이트 키는 항상 사용자에게 숨겨져 야합니다. 대리 키에는 비즈니스 의미가 없기 때문입니다.

그러나 테이블의 실제 모델은 대리 키가 없으면 비효율적입니다. 비 클러스터형 인덱스에 대해 커버되지 않은 열은 일반적으로 키 조회를 통해 클러스터형 인덱스로만 찾을 수 있음을 기억하십시오 (테이블은 잠시 힙으로 구현 됨). 사용 가능한 자연 키가 넓 으면이 (1) 비 클러스터형 리프 노드의 너비가 넓어 져 비 클러스터형 인덱스의 검색 및 스캔에 대한 스토리지 요구 사항과 읽기 액세스가 증가합니다. (2) 클러스터 된 인덱스에서 팬 아웃을 감소시켜 인덱스 높이와 인덱스 크기를 증가시켜 클러스터 된 인덱스에 대한 읽기 및 스토리지 요구 사항을 다시 증가시킵니다. (3) 클러스터형 인덱스에 대한 캐시 요구 사항을 증가시킵니다. 캐시에서 다른 인덱스와 데이터를 추적합니다.

여기서는 "기본 키"로 RDBMS에 지정된 작은 대리 키가 도움이됩니다. 비 클러스터형 인덱스에서 클러스터 된 인덱스로 키를 조회하고 관련 테이블에서 외래 키를 검색하기 위해 클러스터링 키로 설정하면 이러한 모든 단점이 사라집니다. 클러스터형 인덱스 팬 아웃이 다시 증가하여 클러스터형 인덱스 높이 및 크기를 줄이고 클러스터형 인덱스의 캐시로드를 줄이며 모든 메커니즘 (인덱스 스캔, 인덱스 검색, 비 클러스터 키 조회 또는 외래 키 조회)을 통해 데이터에 액세스 할 때 읽기를 줄입니다. 테이블의 클러스터 및 비 클러스터형 인덱스에 대한 스토리지 요구 사항을 줄입니다.

이러한 이점은 서로 게이트 키가 작고 클러스터링 키 모두 인 경우에만 발생합니다. GUID가 클러스터링 키로 사용되는 경우 사용 가능한 가장 작은 자연 키를 사용하는 것보다 상황이 더 나빠질 수 있습니다. 테이블이 힙으로 구성된 경우 8 바이트 (힙) RowID가 키 조회에 사용되며 이는 16 바이트 GUID보다 우수하지만 4 바이트 정수보다 성능이 떨어집니다.

비즈니스 제약으로 인해 GUID를 사용해야하는 경우 더 나은 클러스터링 키를 찾는 것이 좋습니다. 예를 들어 작은 사이트 식별자와 4 바이트 "site-sequence-number"가 실현 가능한 경우 해당 디자인은 Surrogate Key로서 GUID보다 더 나은 성능을 제공 할 수 있습니다.

힙의 결과 (해시 조인)가 선호하는 스토리지를 만들면 더 넓은 클러스터링 키의 비용을 균형 분석에 균형을 맞춰야합니다.

이 예제를 고려하십시오 ::

ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)

튜플 " (P_Id, LastName) "에 고유성 제약 조건이 필요하고 긴 유니 코드 LastName에 4 바이트 정수를 더한 경우 (1)이 제약 조건을 " ADD CONSTRAINT pk_PersonID UNIQUE NONCLUSTERED (P_Id )로 선언적으로 적용하는 것이 바람직합니다. , LastName) "및 (2)는 작은 Surrogate Key를 클러스터형 인덱스 의" 기본 키 "로 별도로 선언합니다 . Anita는 해당 필드를 만들기 위해이 제약 조건에 LastName 만 추가하기를 원할 것입니다.이 필드는 모든 필드가 포함되므로 클러스터형 인덱스에서는 필요하지 않습니다.

SQL Server에서 기본 키를 비 클러스터형으로 지정하는 기능은 "물리적 기본 또는 후보 키"(논리적 모델)의 의미와 실제의 "저장소의 검색 키"라는 의미로 인해 불행한 역사적 상황입니다. 모델. 필자의 이해는 원래 SYBASE SQL Server가 실제 모델의 "저장소의 조회 키"로 힙 또는 클러스터형 인덱스에 상관없이 항상 4 바이트 RowID를 사용했다는 것입니다.


3
이것을 영어로 번역 해 주시겠습니까?
Jasir

3

어떤 사람들은 "기본 키"라는 용어를 사용하여 자동 메커니즘에 의해 생성 된 값을 가져 오는 정수 열을 정확하게 의미합니다. 예를 들어 AUTO_INCREMENTMySQL 또는 IDENTITYMicrosoft SQL Server에서. 이런 의미에서 기본 키를 사용하고 있습니까?

그렇다면 대답은 사용중인 데이터베이스 브랜드에 따라 다릅니다. MySQL에서는이를 수행 할 수 없으며 오류가 발생합니다.

mysql> create table foo (
  id int primary key auto_increment, 
  id2 int auto_increment
);
ERROR 1075 (42000): Incorrect table definition; 
there can be only one auto column and it must be defined as a key

일부 다른 브랜드의 데이터베이스에서는 테이블에 둘 이상의 자동 생성 열을 정의 할 수 있습니다.


5
여러 개의 자동 생성 열이있는 점은 무엇입니까?
Tarnay Kálmán

나는 유스 케이스를 염두에 두지 않지만 필요가 있다면 데이터베이스의 일부 브랜드가 이것을 지원하고 일부는 지원하지 않을 것입니다. 그것이 내가 말하는 전부입니다.
Bill Karwin

1
여기에 주문이 있습니다. 주문 테이블에는 ID (자동 증분)와 외부 ID (해시와 유사한 문자열)가 모두 있으며, 이론적으로 둘 다 "기본"이라고 말할 수 있도록 고유해야합니다. 물론 이것은 이차 고유 인덱스로 수행 할 수 있지만 여전히 합법적 인 사례 (IMHO)입니다.
Nir

2

두 개의 기본 키를 동시에 가질 수는 없습니다. 그러나 (복합 키로 사건을 망쳐 놓지 않았다고 가정하면) 하나의 속성을 고유하게 만드는 것이 필요할 수 있습니다.

CREATE t1(
c1 int NOT NULL,
c2 int NOT NULL UNIQUE,
...,
PRIMARY KEY (c1)
);

그러나 관계형 데이터베이스에서 '슈퍼 키'는 테이블에서 튜플 또는 행을 고유하게 식별하는 속성의 하위 집합입니다. '키'는 키에서 속성을 제거하고 해당 키를 더 이상 '슈퍼 키'로 만들지 않는 추가 속성이있는 '슈퍼 키'입니다 (또는 간단히 '키'는 최소 슈퍼 키입니다). 더 많은 키가 있으면 모두 후보 키입니다. 후보 키 중 하나를 기본 키로 선택합니다. 그렇기 때문에 하나의 관계 또는 테이블에 대한 여러 기본 키에 대해 말하는 것이 충돌하는 이유입니다.


Wikipedia에는 ​​'키'에 대한 정의가 없습니다. 또한 "키에서 속성을 제거하면 해당 키를 더 이상 '슈퍼 키'로 만들지 않습니다"라는 의미는 아닙니다. 슈퍼 키에서 속성을 제거 할 때 여전히 슈퍼 키가 될 수 있습니다.
Manohar Reddy Poreddy

@ManoharReddyPoreddy 예,이 경우 속성 집합은 '키'가 아니라 '슈퍼 키'입니다. 의미하는 속성 집합이 '키'이거나, 집합이 최소화되어야하거나, 집합에서 속성을 제거하면 결과 집합이 '슈퍼 키'가 아닌 추가 속성이 있어야합니다.
Rusiru Adithya Samarasinghe

'key'의 실제 의미는 Candidate_key ( en.wikipedia.org/wiki/Candidate_key )와 같으므로 언급해야 할 수도 있습니다.
Manohar Reddy Poreddy

@ManoharReddyPoreddy 예 나는 이미 내 대답에서 언급했습니다. "더 많은 키가 있으면 모두 후보 키입니다." 어쨌든 검토해 주셔서 감사합니다.
Rusiru Adithya Samarasinghe

1. "더 많은 키가 있으면 모든 키가 후보 키입니다"라고 언급 할 때 ... 그렇지 않으면 다른 의미입니까? ... 2. 다른 부분은 어디에 있습니까? ... 전혀 같은 페이지입니까?
Manohar Reddy Poreddy

1

기본 키는 레코드를 고유하게 식별하고 모든 색인에 사용되는 키입니다. 이것이 하나 이상 가질 수없는 이유입니다. 또한 일반적으로 자식 테이블에 조인하는 데 사용되는 키이지만 필수 사항은 아닙니다. PK의 실제 목적은 데이터 변경 사항이 올바른 레코드에 영향을 미치고 인덱스를 작성할 수 있도록 레코드를 고유하게 식별 할 수 있도록하는 것입니다.

그러나 하나의 기본 키 (복합 PK)에 여러 필드를 넣을 수 있습니다. 이렇게하면 조인 속도가 느려지고 (특히 큰 문자열 유형 필드 인 경우) 인덱스가 커지지 만 일부 자식 테이블에서 조인을 수행 할 필요가 없어 질 수 있습니다. 사례 기준. 이 작업을 수행 할 때 각 필드 자체는 고유하지 않지만 그 조합은 고유합니다. 복합 키의 필드 중 하나 이상이 고유해야하는 경우 고유 한 색인이 필요합니다. 하나의 필드가 고유 한 경우 PK에 더 적합한 후보 일 수 있습니다.

이제는 때때로 PK 후보가 둘 이상 있습니다. 이 경우 PK로 하나를 선택하거나 대리 키를 사용합니다 (개인적으로 대리 키를 선호합니다). 그리고 (이것은 중요합니다!) PK로 선택되지 않은 각 후보 키에 고유 인덱스를 추가합니다. 데이터가 고유해야하는 경우 PK 여부에 관계없이 고유 인덱스가 필요합니다. 이것은 데이터 무결성 문제입니다. (대리 키를 사용하는 경우에도 마찬가지입니다. 사람들은 후보 키에 고유 인덱스를 작성하는 것을 잊어 버리므로 대리 키에 문제가 생깁니다.)

때로는 둘 이상의 대리 키를 원할 때가 있습니다 (보통 PK가있는 경우). 이 경우 원하는 것은 더 많은 PK가 아니며 자동 생성 키가있는 더 많은 필드입니다. 대부분의 DB는 이것을 허용하지 않지만 해결할 수있는 방법이 있습니다. 첫 번째 자동 생성 키 (예 : Field1 * -1)를 기반으로 두 번째 필드를 계산할 수 있는지 또는 두 번째 자동 생성 키가 필요하다는 것은 실제로 관련 테이블을 작성해야한다는 의미입니다. 관련 테이블은 일대일 관계 일 수 있습니다. 상위 테이블에서 하위 테이블로 PK를 추가 한 다음 새 자동 생성 필드를 테이블에 추가 한 다음이 테이블에 적합한 필드를 추가하여이를 적용합니다. 그런 다음 두 키 중 하나를 PK로 선택하고 다른 하나에 고유 인덱스를 넣으십시오 (자동 생성 필드는 PK 일 필요는 없습니다). 부모 테이블에있는 필드에 FK를 추가해야합니다. 일반적으로 하위 테이블에 대한 추가 필드가없는 경우 두 개의 자동 생성 필드가 필요한 이유를 조사해야합니다.


0

내가 할 수있는 것보다 더 좋은 방법으로 좋은 기술 답변을 받았습니다. 이 주제에만 추가 할 수 있습니다.

허용 / 허용되지 않는 것을 원한다면 물러서야합니다.

  1. 허용되지 않는 이유의 핵심을 이해하십시오.
  2. 문서 / 저널 기사 / 웹 등에서 더 많은 내용을 확인하십시오.
  3. 현재 설계를 분석 / 검토하고 주요 결함을 지적합니다.
  4. 새로운 디자인 중에 모든 단계를 고려하고 테스트하십시오.
  5. 항상 기대하고 적응 형 솔루션을 만들어보십시오.

누군가에게 도움이되기를 바랍니다.


1
구체적인 질문에 대한 답변이 아니라 일반적인 조언이지만 유용합니다.
브래드 포드 니드 햄

-3

예, SQL에서는 가능하지만 MsAccess에서 둘 이상의 기본 키를 설정할 수 없습니다. 그런 다음 다른 데이터베이스에 대해 알지 못합니다.

CREATE TABLE CHAPTER (
    BOOK_ISBN VARCHAR(50) NOT NULL,
    IDX INT NOT NULL,
    TITLE VARCHAR(100) NOT NULL,
    NUM_OF_PAGES INT,
    PRIMARY KEY (BOOK_ISBN, IDX)
);

SQL 테이블은 하나의 PK 만 가질 수 있습니다.
philipxy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.