주어진 테이블이 여러 다른 부모 테이블 중 하나에 FK 할 수있는 상황이 데이터베이스에서 자주 발생합니다. 문제에 대한 두 가지 해결책을 보았지만 개인적으로 만족 스럽지는 않습니다. 다른 패턴이 궁금하십니까? 더 좋은 방법이 있습니까?
고안된 예
내 시스템에 있다고 가정 해 봅시다 Alerts
. 고객, 뉴스 및 제품과 같은 다양한 개체에 대해 경고를받을 수 있습니다. 주어진 경고는 단 하나의 항목에 대한 것일 수 있습니다. 어떤 이유로 든 고객, 기사 및 제품은 빠르게 이동하거나 현지화되어 있으므로 경고를 생성 할 때 필요한 텍스트 / 데이터를 경고로 가져올 수 없습니다. 이 설정을 통해 두 가지 솔루션을 보았습니다.
참고 : 아래 DDL은 SQL Server 용이지만 내 질문은 모든 DBMS에 적용 가능해야합니다.
해결 방법 1-다중 널 입력 가능 FKey
이 솔루션에서 일대 다 테이블에 연결되는 테이블에는 여러 개의 FK 열이 있습니다 (간단하게하기 위해 아래 DDL에는 FK 생성이 표시되지 않음). 좋은 -이 솔루션에서는 외래 키가 있다는 것이 좋습니다. FK의 Null-optinality는 정확한 데이터를 편리하고 쉽게 추가 할 수있게 해줍니다. BAD 쿼리는 관련 데이터를 가져 오기 위해 N LEFT JOINS 또는 N UNION 문이 필요하기 때문에 좋지 않습니다 . SQL Server에서 특히 LEFT JOINS는 인덱싱 된 뷰를 만드는 것을 금지합니다.
CREATE TABLE Product (
ProductID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_Product Primary Key CLUSTERED (ProductID)
)
CREATE TABLE Customer (
CustomerID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_Customer Primary Key CLUSTERED (CustomerID)
)
CREATE TABLE News (
NewsID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_News Primary Key CLUSTERED (NewsID)
)
CREATE TABLE Alert (
AlertID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
ProductID int null,
NewsID int null,
CustomerID int null,
CONSTRAINT PK_Alert Primary Key CLUSTERED (AlertID)
)
ALTER TABLE Alert WITH CHECK ADD CONSTRAINT CK_OnlyOneFKAllowed
CHECK (
(ProductID is not null AND NewsID is null and CustomerID is null) OR
(ProductID is null AND NewsID is not null and CustomerID is null) OR
(ProductID is null AND NewsID is null and CustomerID is not null)
)
해결 방법 2-각 상위 테이블에서 하나의 FK
이 솔루션에서 각 '상위'테이블에는 경고 테이블에 대한 FK가 있습니다. 부모와 관련된 경고를 쉽게 검색 할 수 있습니다. 아래쪽에는 경고에서 참조하는 사람에 대한 실제 체인이 없습니다. 또한 데이터 모델을 통해 경보가 제품, 뉴스 또는 고객과 연관되지 않은 고아 경보를 사용할 수 있습니다. 다시 한 번, 여러 개의 LEFT JOIN이 연결을 파악합니다.
CREATE TABLE Product (
ProductID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_Product Primary Key CLUSTERED (ProductID)
)
CREATE TABLE Customer (
CustomerID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_Customer Primary Key CLUSTERED (CustomerID)
)
CREATE TABLE News (
NewsID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_News Primary Key CLUSTERED (NewsID)
)
CREATE TABLE Alert (
AlertID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
CONSTRAINT PK_Alert Primary Key CLUSTERED (AlertID)
)
이것이 관계 데이터베이스의 유일한 삶입니까? 더 만족스러운 대체 솔루션이 있습니까?
Alertable
. 말이 되나요?