외래 키가 NULL이거나 중복 될 수 있습니까?


325

나를 위해 두 가지를 분명히하십시오.

  1. 외래 키가 NULL 일 수 있습니까?
  2. 외래 키를 복제 할 수 있습니까?

내가 알기로 NULL는 외래 키에 사용해서는 안되지만 일부 응용 프로그램에서는 NULLOracle과 SQL Server 모두 에 입력 할 수 있으며 그 이유를 모르겠습니다.


1
@Adrian : 내 지식으로는 외래 키는 null 일 수 없지만 SQL Server 및 Oracle에서 null을 취합니다. 이유를 설명 할 수 있습니까?

@Jams-내 답변의 링크를 읽으십시오.
JNK

11
답변과 질문이 유용하므로 삭제할 수 없습니다. 개선하기 위해 질문을 자유롭게 편집하십시오.
Jeff Atwood

중복에 대한 질문을 나누십시오. NULL에 관한 것만 아래에 대답하고 있습니다.
reinierpost

답변:


529

짧은 대답 : 예. NULL이거나 중복 될 수 있습니다.

외래 키가 null이어야하거나 고유하거나 고유하지 않아야하는 이유를 설명하고 싶습니다. 먼저 외래 키는 단순히 해당 필드의 값이 다른 테이블 (상위 테이블)에 있어야한다는 것을 기억하십시오. 이것이 전부 FK입니다. 정의에 의한 널은 값이 아닙니다. Null은 값이 무엇인지 아직 알지 못함을 의미합니다.

실제 사례를 보여 드리겠습니다. 판매 제안서를 저장하는 데이터베이스가 있다고 가정하십시오. 각 제안서에는 한 명의 영업 담당자와 한 명의 클라이언트 만 있다고 가정하십시오. 따라서 제안서 테이블에는 두 개의 외래 키가 있습니다. 하나는 클라이언트 ID와 다른 하나는 영업 담당자 ID입니다. 그러나 레코드가 작성 될 때 영업 담당자가 항상 할당되지는 않으므로 (아직 아무도 작업 할 수 없기 때문에) 클라이언트 ID가 채워지지만 영업 담당자 ID는 널일 수 있습니다. 다시 말해, 일반적으로 데이터를 입력 할 때 해당 값을 모르지만 입력해야하는 다른 값을 알고있는 경우 널 FK를 사용할 수 있어야합니다. FK에서 null을 허용하려면 일반적으로 FK가있는 필드에서 null을 허용하면됩니다. 널값은 FK라는 생각과 별개입니다.

고유한지 여부는 테이블이 상위 테이블과 일대일 관계인지 여부와 관련이 있습니다. 이제 일대일 관계인 경우 하나의 테이블에 데이터를 모두 가질 수 있지만 테이블이 너무 넓어 지거나 데이터가 다른 주제에있는 경우 (직원-@tbone이 제공 한 보험 사례) 예를 들어) FK를 사용하여 별도의 테이블을 원합니다. 그런 다음이 FK를 PK (유일성을 보장)로 만들거나 고유 한 제약 조건을 적용하려고합니다.

대부분의 FK는 일대 다 관계이며 필드에 대한 추가 제약없이 FK에서 얻는 것입니다. 예를 들어 주문 테이블과 주문 세부 정보 테이블이 있습니다. 고객이 한 번에 10 개의 품목을 주문하면 FK와 동일한 orderID를 포함하는 1 개의 주문 및 10 개의 주문 세부 사항 레코드가 있습니다.


13
그래서 "할당되지 않은"이라는 가짜 영업 사원을 갖는 것보다 낫습니다.
Thomas Weller

8
의견. 널 (null)은 SQL (mis)이 3VL을 처리하는 방법을 모르는 사람들의 쿼리에서 오류가 발생할 여지를 많이 남겨 둡니다. 특정 r- 테이블에 영업 담당자가 필요하지 않은 경우 해당 레코드를 포함하지 않아도됩니다. 별도의 테이블은 "ProposalAssignedTo"또는 적절한 제약 조건이있는 테이블 일 수 있습니다. 그런 다음 쿼리 작성자는 해당 테이블에 조인하고 제안서에 영업 사원이없는 경우 수행하려는 모든 작업에 대해 자체 로직을 제공 할 수 있습니다. NULL은 단지 "우리가 모른다"를 의미하는 것이 아니라 많은 것들에 사용될 수있다 (이것은 거의 항상 나쁜 생각이다)
N West

26
@nWest, 무능한 사람들이 내 데이터베이스를 쿼리하는 것을 허용하지 않으며 null 처리 방법을 모르는 개발자는 무능합니다. 특정 필드에 대한 초기 데이터 입력 시점에 데이터가 알려지지 않았지만 그 때 다른 필드가 필요한 경우가 있습니다.
HLGEM

28
@ThomasWeller 가짜 영업 사원 ( "할당되지 않음")을 참조하면 문제가 악화됩니다. 영업 담당자 테이블에 여러 열이 있다고 가정합니다. 미 할당 씨의 사회 보험 번호는 무엇입니까? 그는 어느 부서에 할당되어 있습니까? 그의 상사는 누구입니까? "할당되지 않은"영업 사원을 만들면 NULL한 테이블에서 다른 테이블에 여러 개 를 거래 한 것을 신속하게 알 수 있습니다 NULL.
길리

1
@ThomasWeller 또한 인터페이스를 현지화해야 할 경우 문제가 발생합니다.
tobiv


45

말의 입에서 :

외래 키는 일치하는 PRIMARY 또는 UNIQUE 키가 없더라도 모두 NULL 인 키 값을 허용합니다.

외래 키에 대한 제한 없음

외래 키에 다른 제약 조건이 정의되어 있지 않으면 자식 테이블의 여러 행이 동일한 부모 키 값을 참조 할 수 있습니다. 이 모델은 외래 키에 null을 허용합니다. ...

외래 키에 대한 NOT NULL 제약

외래 키에 널이 허용되지 않는 경우, 외래 키에는 널이 허용되지 않으므로 하위 테이블의 각 행이 상위 키의 값을 명시 적으로 참조해야합니다.

자식 테이블의 여러 행은 동일한 부모 키 값을 참조 할 수 있으므로이 모델은 부모 키와 외래 키간에 일대 다 관계를 설정합니다. 그러나 자식 테이블의 각 행에는 부모 키 값에 대한 참조가 있어야합니다. 외래 키에 값이 없으면 (널) 허용되지 않습니다. 이전 섹션의 동일한 예를 사용하여 이러한 관계를 설명 할 수 있습니다. 그러나이 경우 직원에게는 특정 부서에 대한 참조가 있어야합니다.

외래 키에 대한 고유 제한

외래 키에 UNIQUE 제약 조건이 정의되면 자식 테이블의 한 행만 주어진 부모 키 값을 참조 할 수 있습니다. 이 모델은 외래 키에 null을 허용합니다.

이 모델은 부모 키와 외래 키 사이의 일대일 관계를 설정하여 외래 키에서 결정되지 않은 값 (널)을 허용합니다. 예를 들어, 직원 테이블에 회사 보험 계획의 직원 멤버십 번호를 나타내는 MEMBERNO라는 열이 있다고 가정하십시오. 또한 INSURANCE라는 테이블에는 MEMBERNO라는 기본 키가 있으며 테이블의 다른 열은 직원 보험 정책과 관련된 각 정보를 유지합니다. employee 테이블의 MEMBERNO는 외래 키와 고유 키 여야합니다.

  • EMP_TAB와 INSURANCE 테이블 (참조 FOREIGN KEY 제약 조건)간에 참조 무결성 규칙을 시행하려면

  • 각 직원이 고유 한 멤버십 번호를 갖도록 (UNIQUE 키 제한)

외래 키에 대한 UNIQUE 및 NOT NULL 제약 조건

외래 키에 UNIQUE 및 NOT NULL 제약 조건이 모두 정의되어 있으면 자식 테이블의 한 행만 지정된 부모 키 값을 참조 할 수 있으며 외래 키에는 NULL 값이 허용되지 않으므로 자식 테이블의 각 행은 명시 적으로 참조해야합니다. 부모 키의 값

이것 좀 봐:

Oracle 11g 링크


16

그렇습니다. 고위 프로그래머가 위에서 말한 것처럼 외래 키가 null 일 수 있습니다 ... 외래 키가 null이어야하는 다른 시나리오를 추가 할 것입니다. 비디오. 주석 표에는 기본 키 CommentId와 함께 두 개의 외래 키 PicturesId 및 VideosId가있을 수 있습니다. 따라서 동영상에 댓글을 달면 VideosId 만 필요하고 pictureId는 null이됩니다. 사진에 댓글을 달면 PictureId 만 필요하고 VideosId는 null이됩니다 ...


1
이 문제를 해결하는 더 좋은 방법이 있다고 생각합니다. 새 열을 만드는 대신 외래 키 테이블의 id와 이름을 포함하는 "id"와 "type"의 두 열을 가질 수 있습니다. 예를 들어, id = 1, type = Picture는 id가 1 인 Picture 테이블에 대한 링크를 나타냅니다.이 솔루션을 사용하면 이점이 추가 테이블에 주석을 추가 할 때 새 열을 만들 필요가 없습니다. 단점은 db 수준에서 외래 키 제약 조건이 아니며 제약 조건은 앱 수준이어야합니다.
Agent 47DarkSoul

4
@ 에이전트 : 프로덕션 환경에서이 "솔루션"을 사용했습니다. 하지마 끔찍 해요 쿼리가 "유형 1 인 경우이 테이블에 조인하고, 그렇지 않으면 조인하십시오"라는 혼란이됩니다. 우리에게는 악몽이었다. 우리는이 답변이 말한 것을 끝내고 각 조인 유형에 대해 새로운 열을 만들었습니다. 열을 만드는 것이 저렴합니다. 열이 많으면 Toad를 사용하기 어렵지만 이는 Toad의 결함 일뿐입니다.
user128216

1
@FighterJet Rails는이 솔루션으로 복잡한 쿼리조차도 처리 할 수있는 훌륭한 ORM 프레임 워크를 제공합니다.
Agent 47DarkSoul

2
@ 에이전트 : 어쩌면 그럴 수도 있지만 ... 간단하게 만들 수 있다면 왜 복잡하게 만들 수 있습니까? 그리고 "악몽"은 사용하기에 잘못된 단어 일 수 있습니다. 매우 불편했습니다. 우리는 데이터 무결성 문제를 겪지 않았습니다.
user128216

7

그것은 foreign key당신의 관계에서 이것이 어떤 역할을하는지에 달려 있습니다.

  1. 이것이 foreign key또한 key attribute관계에있는 경우 NULL이 될 수 없습니다
  2. 이것이 foreign key관계의 정상적인 속성 인 경우 NULL 일 수 있습니다.

3

다음은 Oracle 구문을 사용하는 예입니다.
먼저 COUNTRY 테이블을 작성하겠습니다 .

CREATE TABLE TBL_COUNTRY ( COUNTRY_ID VARCHAR2 (50) NOT NULL ) ;
ALTER TABLE TBL_COUNTRY ADD CONSTRAINT COUNTRY_PK PRIMARY KEY ( COUNTRY_ID ) ;

PROVINCE 테이블 작성

CREATE TABLE TBL_PROVINCE(
PROVINCE_ID VARCHAR2 (50) NOT NULL ,
COUNTRY_ID  VARCHAR2 (50)
);
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_PK PRIMARY KEY ( PROVINCE_ID ) ;
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_COUNTRY_FK FOREIGN KEY ( COUNTRY_ID ) REFERENCES TBL_COUNTRY ( COUNTRY_ID ) ;

이것은 Oracle에서 완벽하게 실행됩니다. 두 번째 테이블의 COUNTRY_ID 외래 키에는 "NOT NULL"이 없습니다.

이제 PROVINCE 테이블에 행을 삽입하려면 PROVINCE_ID 만 지정하면 충분합니다. 그러나 COUNTRY_ID도 지정하도록 선택한 경우 COUNTRY 테이블에 이미 존재해야합니다.


1

기본적으로 외래 키에는 제약 조건이 없으며 외래 키는 null이거나 중복 될 수 있습니다.

테이블을 만들거나 테이블을 변경하는 동안 고유성 제약 조건을 추가하거나 null이 아닌 경우 null / 중복 값을 허용하지 않습니다.


0

간단히 말해 엔터티 간의 "비 식별"관계는 ER-Model의 일부이며 ER-Diagram을 디자인 할 때 Microsoft Visio에서 사용할 수 있습니다. "0 또는 0보다 큰"유형의 엔터티 또는 "0 또는 1"의 카디널리티를 적용하려면이 옵션이 필요합니다. "일대 다"의 "일"대신 카디널리티에서이 "0"에 유의하십시오.

카디널리티가 "제로"일 수있는 비 식별 관계의 예 (비 식별)는 하나의 엔티티에서 레코드 / 객체를 말할 때입니다. "may"또는 "may not"은 레코드에 대한 참조로 값을가집니다. 다른 Entity-B의 / s

Entity-A의 한 레코드가 다른 Entity-B의 레코드에 자신을 식별 할 가능성이 있으므로 Entity-B에 Entity-B 레코드의 ID 값을 갖는 열이 있어야합니다. Entity-A의 레코드가 Entity-B의 레코드 (또는 오브젝트)를 식별하지 않으면이 열은 "Null"일 수 있습니다.

객체 지향 (실제) 패러다임에서 클래스 B의 오브젝트가 존재하기 위해 클래스 A의 오브젝트에 반드시 의존 (강하게 결합)되지 않는 상황이 있습니다. 이는 클래스 B가 클래스-와 느슨하게 연결되어 있음을 의미합니다 Class-A가 Class-B의 객체 개념을 갖는 것과 달리 Class-A의 객체를 "포함 (Containment)"할 수 있도록하기 위해서는 Class-A의 객체가 나) 창조.

SQL 쿼리 관점에서 Entity-B 용으로 예약 된 외래 키에 대해 "null이 아닌"entity-B의 모든 레코드를 쿼리 할 수 ​​있습니다. 이렇게하면 Entity-A의 행에 대해 해당하는 특정 값을 가진 모든 레코드를 가져 오거나 Null 값을 가진 모든 레코드는 Entity-B의 Entity-A에 레코드가없는 레코드가됩니다.


-1

나는 우리가 테이블에 가질 수있는 카디널리티를 고려하는 것이 낫다고 생각합니다. 가능한 최소 카디널리티 0을 가질 수 있습니다. 선택 사항 인 경우 관련 테이블에서 튜플의 최소 참여는 0이 될 수 있습니다. 이제 외부 키 값이 널 (null)이되도록해야합니다.

그러나 정답은 모두 비즈니스에 달려 있다는 것입니다.


-3

외래 키의 개념은 기본 테이블에 이미 존재하는 값을 참조하는 개념을 기반으로합니다. 이것이 다른 테이블에서 외래 키라고하는 이유입니다. 이 개념을 참조 무결성이라고합니다. 외래 키가 널 필드로 선언되면 참조 무결성의 논리를 위반하게됩니다. 무엇을 의미합니까? 기본 테이블에있는 것만 참조 할 수 있습니다. 따라서 외래 키 필드를 null로 선언하는 것은 잘못이라고 생각합니다.


"아무것도"를 참조하거나 아직 그 가치 NULL를 모르지만 참조 무결성이 말하는 것은 "무언가"를 참조하면 거기에 있어야한다는 것입니다.
yaxe

-7

한 테이블의 외래 키도 다른 테이블의 기본 키라고 생각하므로 null을 허용하지 않으므로 외래 키에 null 값이 있는지에 대해서는 의문의 여지가 없습니다.

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