외래 키가있는 테이블 열이 NULL 일 수 있습니까?


235

다른 테이블에 여러 ID 열이있는 테이블이 있습니다.

거기에 데이터를 넣을 때만 외래 키가 무결성을 유지하기를 원합니다 . 나중에 해당 열을 채우려면 업데이트를 수행하면 제약 조건도 확인해야합니다.

(이것은 데이터베이스 서버에 따라 다를 수 있습니다 .MySQL & InnoDB 테이블 유형을 사용하고 있습니다)

나는 이것이 합리적인 기대라고 생각하지만 내가 틀렸다면 나를 바로 잡으십시오.


6
MySQL에 대해서는 잘 모르지만 MS SQL Server는 원하는 의미로 외래 키를 Null 허용 할 수 있습니다. 나는 이것이 표준 행동이라고 생각합니다.
Jeffrey L Whitledge

1
외래 키는 mySQL에서 기본적으로 null이 될 수 없으므로 이유는 간단합니다. 무언가를 참조하고 null로 설정하면 데이터 무결성이 느려집니다. 테이블 세트를 작성할 때 널을 NOT으로 허용 한 다음 외래 키 제한 조건을 적용하십시오. 업데이트시 null을 설정할 수 없으며 오류를 보내야하지만이 열을 업데이트하지 않고 변경 해야하는 필드 만 업데이트 할 수 있습니다.
JoelBonetR

답변:


245

예, 값이 NULL이 아닌 경우에만 제한 조건을 적용 할 수 있습니다. 다음 예제를 통해 쉽게 테스트 할 수 있습니다.

CREATE DATABASE t;
USE t;

CREATE TABLE parent (id INT NOT NULL,
                     PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (id INT NULL, 
                    parent_id INT NULL,
                    FOREIGN KEY (parent_id) REFERENCES parent(id)
) ENGINE=INNODB;


INSERT INTO child (id, parent_id) VALUES (1, NULL);
-- Query OK, 1 row affected (0.01 sec)


INSERT INTO child (id, parent_id) VALUES (2, 1);

-- ERROR 1452 (23000): Cannot add or update a child row: a foreign key 
-- constraint fails (`t/child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY
-- (`parent_id`) REFERENCES `parent` (`id`))

첫 번째 삽입은에 NULL을 삽입하기 때문에 전달됩니다 parent_id. parent테이블에 존재하지 않는 값을 삽입하려고했기 때문에 외래 키 제약 조건으로 인해 두 번째 삽입이 실패 합니다.


16
부모 테이블은 id INT NOT NULL로 선언 할 수도 있습니다.
것입니다

@CJDennis 한 행만 null ID를 갖도록 만들면 다른 행의 대체 값으로 사용될 수 있습니다. (더 많은 열을 사용하는 경우 DB에서 더 잘 작동 할 수 있지만) 나중에 값이 원래 "default"로 설정되었는지 (null을 사용하여) 설정되었는지 또는 "default"와 동일한 값. 널 ID가있는 행을 가짐으로써이 행이 일반 행으로 사용되지 않음을 명확하게 표시하고 다른 행에 일종의 동적 기본값을 제공하는 방법으로 행을 사용할 수 있습니다.
Ouroborus 2012

1
난 생각 parent_id INT NULL(자세하게) 부분은 동일parent_id int default null

Java 사용자를위한 참고 사항 : ibatis 또는 다른 ORM을 사용하고 클래스 멤버 int대신 기본 요소를 사용하는 Integer경우 기본값은 절대로 null이되지 않지만 0이되고 제한 조건에 실패합니다.
Jim Ford

32

삽입 할 때 null 열 값을 구체적으로 NULL로 선언해야한다는 것을 알았습니다. 그렇지 않으면 빈 문자열이 아닌 제약 조건 위반 오류가 발생합니다.


8
이것을 허용하기 위해 열에서 기본값 NULL을 설정할 수 없습니까?
Kevin Coulombe

예, 대부분의 언어에서 NULL은 빈 문자열과 다릅니다. 처음에는 미묘하지만 기억하는 것이 중요합니다.
Gary

이봐 Backslider, 당신은 "(빈 문자열과 반대)"라고 말하지만, 당신은 당신이 빈 문자열의 값을 삽입한다고 생각하지는 않지만, 대신에 당신의 Value에 대한 값을 지정하지 않았다고 생각합니다. 모두? 즉, 당신의 열을 언급하지 INSERT INTO {table} {list_of_columns}않습니까? 그것이 저에게 사실이기 때문입니다. 열에 대한 언급을 생략하면 오류가 발생하지만 명시 적으로 NULL로 설정하고 명시 적으로 설정하면 오류가 수정됩니다. 내가 맞다면 @Gary의 의견이 적용되지 않는다고 생각하지만 (빈 문자열을 의미하지 않았기 때문에) @Kevin Coulombe의 도움이 될 수 있습니다 ...
The Red Pea

예, @KevinCoulombe의 제안은 Entity Framework Core의 Migration 스크립트를 사용하여이 작업을 수행하는 방법을 설명 했습니다.
Red Pea

NULL 외래 키를 포함하는 레코드를 업데이트 할 때 명시 적이라는 이론적 근거는 문자열 유형 (varchar 등)에만 적용됩니다. 그렇지 않으면 빈 문자열이 기본값으로 전달 될 수 있기 때문입니다. 이는 MySQL의 경우이며 업데이트시 무결성 오류가 발생합니다.
CodeMantle

4

예, 예상대로 작동합니다. 불행히도, MySQL 매뉴얼 에서 이것에 대한 명시 적 진술을 찾는 데 어려움을 겪고있는 것 같습니다 .

외래 키는 다른 테이블에 값이 있어야 함을 의미합니다. NULL 은 값이 없음을 나타내므로 열을 NULL로 설정하면 제약 조건을 적용하려고 시도하는 것이 적합하지 않습니다.


설계 상 외래 키는 NULL이 아닌 일부 키 (기본)를 참조해야하지만 개발 단계에서 먼저 자식 테이블에 여러 데이터를 삽입해야 할 때 누가 참조 할 것인지 모릅니다 (부모 테이블) . 이것이 NULL 값이 허용되는 이유입니다. 생산에서 NULL을 갖는 것은 대략적으로 말할 수있는 설계 흐름이 될 것입니다.
vimal krishna

2

위의 작동하지만 작동하지 않습니다. ON DELETE CASCADE 참고

CREATE DATABASE t;
USE t;

CREATE TABLE parent (id INT NOT NULL,
                 PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (id INT NULL, 
                parent_id INT NULL,
                FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE

) ENGINE=INNODB;


INSERT INTO child (id, parent_id) VALUES (1, NULL);
-- Query OK, 1 row affected (0.01 sec)

4
'위'의 의미는 무엇입니까? 다른 답변을 참조하는 경우 주문이 변경 될 수 있습니다.
d219

2

예, 값은 NULL 일 수 있지만 명시 적이어야합니다. 나는 이전에도 이와 같은 상황을 경험했으며, 왜 이런 일이 발생했는지 잊어 버리기 쉬우므로 수행해야 할 일을 기억하는 데 약간의 시간이 걸립니다.

제출 된 데이터가 빈 문자열로 캐스트되거나 해석되면 실패합니다. 그러나 INSERTING 또는 UPDATING 일 때 명시 적으로 값을 NULL로 설정하면 좋습니다.

그러나 이것은 프로그래밍의 재미입니다. 우리 자신의 문제를 만들고 고친다! 건배!


1

이 문제를 해결하는 또 다른 방법은 다른 테이블에 DEFAULT 요소를 삽입하는 것입니다. 예를 들어, 다른 테이블에서 uuid = 00000000-0000-0000-0000-000000000000에 대한 참조는 조치가 없음을 나타냅니다. 또한 코드 로직에 영향을주지 않으려면 해당 id의 모든 값을 "중립"으로 설정해야합니다 (예 : 0, 빈 문자열, null).


2
이것은 같은 것이 아닙니다. 기본값 또는 "중립"값은 값이없는 NULL과 동일하지 않습니다. NULL에 대한 기본값의 장점을 논의하지 않고, 당신의 문구는 약간 섞여 있습니다. "이 문제를 해결하는 또 다른 방법은 다른 테이블에 null 요소를 삽입하는 것입니다." "이 방법을 해결하는 또 다른 방법은 다른 테이블에 DEFAULT 요소를 삽입하는 것입니다"
blindguy

0

나는 또한이 문제를 고수했다. 그러나 외래 키를로 정의하여 간단히 해결했습니다 unsigned integer. 아래 예제를 찾으십시오.

CREATE TABLE parent (
   id int(10) UNSIGNED NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (
    id int(10) UNSIGNED NOT NULL,
    parent_id int(10) UNSIGNED DEFAULT NULL,
    FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE
) ENGINE=INNODB;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.