null 열이 기본 키의 일부일 수 있습니까?


15

SQL Server 2012 데이터베이스를 개발 중이며 일대일 관계에 대한 질문이 있습니다.

나는 두 개의 테이블을 가지고 CodesHelperCodes. 코드에는 0 개 또는 1 개의 도우미 코드가있을 수 있습니다. 이 두 테이블과 그 관계를 작성하는 sql 스크립트입니다.

CREATE TABLE [dbo].[Code]
(
    [Id] NVARCHAR(20) NOT NULL, 
    [Level] TINYINT NOT NULL, 
    [CommissioningFlag] TINYINT NOT NULL, 
    [SentToRanger] BIT NOT NULL DEFAULT 0, 
    [LastChange] NVARCHAR(50) NOT NULL, 
    [UserName] NVARCHAR(50) NOT NULL, 
    [Source] NVARCHAR(50) NOT NULL, 
    [Reason] NVARCHAR(200) NULL, 
    [HelperCodeId] NVARCHAR(20) NULL,
    CONSTRAINT [PK_Code] PRIMARY KEY CLUSTERED
    (
        [Id] ASC
    ),
    CONSTRAINT [FK_Code_LevelConfiguration]
       FOREIGN KEY ([Level])
        REFERENCES [dbo].[LevelConfiguration] ([Level]),
    CONSTRAINT [FK_Code_HelperCode]
       FOREIGN KEY ([HelperCodeId])
        REFERENCES [dbo].[HelperCode] ([HelperCodeId])
)

CREATE TABLE [dbo].[HelperCode]
(
    [HelperCodeId] NVARCHAR(20) NOT NULL, 
    [Level] TINYINT NOT NULL, 
    [CommissioningFlag] TINYINT NOT NULL, 
    [LastChange] NVARCHAR(50) NOT NULL,
    CONSTRAINT [PK_HelperCode] PRIMARY KEY CLUSTERED
    (
        [HelperCodeId] ASC
    ),
    CONSTRAINT [FK_HelperCode_LevelConfiguration]
       FOREIGN KEY ([Level])
        REFERENCES [dbo].[LevelConfiguration] ([Level])
)

그 맞습니까?

코드와 도우미 코드는 서로 다른 엔터티입니다. HelperCode는 사용되거나 (코드가 아닌 코드를 참조하거나) 하나의 코드 만 참조 할 수 있습니다.

아마도 Code.HelperCodeId는 코드 테이블 기본 키의 일부 여야합니다. 그러나 null 열이 기본 열의 일부인지 확실하지 않습니다. 이렇게하면 둘 이상의 코드가 동일한 HelperCode를 참조하지 않도록하고 싶습니다.


1
HelperCodeIdPK에 참여 하고 싶 습니까? 두 개 이상의 코드가 동일한 HelperCode를 참조하지 못하도록하려고합니까?
Andriy M

예, 두 개 이상의 코드가 동일한 HelperCode를 참조하지 않도록하고 싶습니다. 다른 옵션은 HelperCodeId열을 고유 로 설정하는 것 입니다.
VansFannel

@ypercube 전체 SQL 문장을 답변으로 추가해 주시겠습니까? 나는 SQL에서 자주 일하지 않으며 어떻게 해야할지 모르겠다. 감사.
VansFannel

개념적으로, DBMS 엔지니어는 전체 관계형 데이터 모델에 반대하지 않고 기본 키에 NULL을 허용 할 수 없었습니다. 관계형 모델은 관계형 데이터베이스를 매우 유용하게 만드는 요소 중 하나입니다. 이 측면에 관심이 있거나 없을 수도 있지만 향후 방문자를 지적하는 것이 중요합니다.
Walter Mitty

@WalterMitty PK에 null 값이 있으면 RDBMS가 제공하는 값을 파괴하는 이유를 이해하지 못했습니다. 나는 여러 번 들었습니다. 정교하게 할 수 있습니까?
usr

답변:


24

제목의 질문에 대답하려면 아니오, 모든 기본 열은이어야 NOT NULL합니다.

그러나 테이블 디자인을 변경하지 않고 Code (HelperCodeId)열에 필터링 된 인덱스를 추가 할 수 있습니다 .

CREATE UNIQUE INDEX 
    FUX_Code_HelperCodeId
ON dbo.Code 
    (HelperCodeId) 
WHERE 
    HelperCodeId IS NOT NULL ;

WHERE HelperCodeId IS NOT NULLSQL-Server가 고유 제약 조건 및 고유 인덱스에서 null을 처리하는 방식 때문에 필터 ( )가 필요합니다. 필터가 없으면 SQL-Server는 NULLin로 둘 이상의 행을 허용하지 않습니다 HelperCodeId.


또 다른 디자인은 제거 될 수 HelperCodeId에서 Code하고 저장합니다 세 번째 테이블 추가 Code- HelperCode관계를. 두 엔티티 사이의 관계는 0 또는 1 대 0 또는 제로 또는 하나 인 것 같습니다 (둘 다 코드는 HelperCode를 가질 수없고 HelperCode는 코드없이 사용될 수 있음).

CREATE TABLE [dbo].[Code]
(
    [Id] NVARCHAR(20) NOT NULL, 
    [Level] TINYINT NOT NULL, 
    [CommissioningFlag] TINYINT NOT NULL, 
    [SentToRanger] BIT NOT NULL DEFAULT 0, 
    [LastChange] NVARCHAR(50) NOT NULL, 
    [UserName] NVARCHAR(50) NOT NULL, 
    [Source] NVARCHAR(50) NOT NULL, 
    [Reason] NVARCHAR(200) NULL, 
    -- 
    -- removed:   [HelperCodeId] NVARCHAR(20) NULL,
    -- 
    CONSTRAINT [PK_Code] PRIMARY KEY CLUSTERED
    (
        [Id] ASC
    ),
    CONSTRAINT [FK_Code_LevelConfiguration]
       FOREIGN KEY ([Level])
        REFERENCES [dbo].[LevelConfiguration] ([Level]),
) ;

HelperCode 변경되지 않은 상태로 유지 :

CREATE TABLE [dbo].[HelperCode]
(
    [HelperCodeId] NVARCHAR(20) NOT NULL, 
    [Level] TINYINT NOT NULL, 
    [CommissioningFlag] TINYINT NOT NULL, 
    [LastChange] NVARCHAR(50) NOT NULL,
    CONSTRAINT [PK_HelperCode] PRIMARY KEY CLUSTERED
    (
        [HelperCodeId] ASC
    ),
    CONSTRAINT [FK_HelperCode_LevelConfiguration]
       FOREIGN KEY ([Level])
        REFERENCES [dbo].[LevelConfiguration] ([Level])
) ;

추가 테이블에는 UNIQUE모든 코드가 (최대) 하나의 HelperCode와 관련되고 각 HelperCode가 (최대) 하나의 코드와 관련되도록하기 위해 두 개의 제약 (또는 하나의 기본 및 하나의 고유)이 있습니다. 두 열은 다음과 NOT NULL같습니다.

CREATE TABLE [dbo].[Code_HelperCode]
(
    [CodeId] NVARCHAR(20) NOT NULL, 
    [HelperCodeId] NVARCHAR(20) NOT NULL, 
    CONSTRAINT [UQ_Code_HelperCode_CodeId]
       UNIQUE (CodeId),
    CONSTRAINT [UQ_Code_HelperCode_HelperCodeId]
       UNIQUE (HelperCodeId),
    CONSTRAINT [FK_HelperCode_Code]
       FOREIGN KEY ([CodeId])
        REFERENCES [dbo].[Code] ([Id]),
    CONSTRAINT [FK_Code_HelperCode]
       FOREIGN KEY ([HelperCodeId])
        REFERENCES [dbo].[HelperCode] ([HelperCodeId])
) ;

감사합니다. 원한다면 디자인을 변경할 수 있습니다. 많이 배울 수있었습니다.
VansFannel

디자인 해 주셔서 감사합니다. 이 테이블은 다 대다 관계에서만 사용된다고 생각했기 때문에 새 테이블을 추가하지 않았습니다.
VansFannel

0

대신 고유 제한 조건을 사용하십시오. 아마도 ANSI 표준이 null을 기본 키로 유효하지 않다고 선언했지만 표준을 본 적이 없으며 이것을 확인하기 위해 그것을 구입하고 싶지 않습니다.

null 키를 가지지 않는 것은 개발자가 어떤 식 으로든 믿지 않는 것 중 하나 인 것 같습니다. 채워지지 않은 콤보 상자에 대한 툴팁 및 관련 데이터가 포함 된 조회 테이블에 도움이된다는 것을 알기 때문에 선호합니다.

Null 값은 변수가 설정되지 않았 음을 나타내고 빈 값은 값이 과거에 설정되었음을 나타냅니다. 물론 이것은 응용 프로그램에 대해 정의하는 개발자의 책임이지만 빈 기본 키는 허용하지만 null 기본 키는 허용하지 않는 것이 무의미합니다.

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