1

私は、Jeff Smith の「SQL Server でのテーブル継承の実装」で説明されている手法に従っています(これは、この種の構造を実装するための事実上のアプローチのようです)。実表には、その3 つのサブタイプ表、、Peopleと 1 : 0..1 の関係があります。これは、従来、サブタイプ テーブルの主キーをベース テーブルへの外部キーとして定義することによって行われていました。StudentsTeachersParents

サブタイプ間で排他性を強制する (同じ人が同時に生徒と教師になるのを防ぐ) ために、作成者PersonTypeIDは永続化された計算列として各サブタイプ テーブルに追加し、それをベース テーブルの外部キー制約に含めることをお勧めします。

CREATE TABLE PersonType 
(
    PersonTypeID INT PRIMARY KEY,
    Description  VARCHAR(10)
);

INSERT INTO PersonType 
VALUES (1, 'Student'),
       (2, 'Teacher'),
       (3, 'Parent');

CREATE TABLE People 
( 
    PersonID     INT PRIMARY KEY,
    PersonTypeID INT REFERENCES PersonType (PersonTypeID), 
    Name         VARCHAR(10),
    UNIQUE (PersonID, PersonTypeID)
)

CREATE TABLE Students 
( 
    PersonID INT PRIMARY KEY, 
    PersonTypeID AS 1 PERSISTED, -- student 
    EnrollmentDate DATETIME, 
    FOREIGN KEY (PersonID, PersonTypeID) REFERENCES People (PersonID, PersonTypeID) 
) 

CREATE TABLE Teachers 
( 
    PersonID INT PRIMARY KEY, 
    PersonTypeID AS 2 PERSISTED, -- teacher 
    HireDate DATETIME, 
    FOREIGN KEY (PersonID, PersonTypeID) REFERENCES People (PersonID, PersonTypeID) 
) 

CREATE TABLE Parents 
( 
    PersonID INT PRIMARY KEY, 
    PersonTypeID AS 3 PERSISTED, -- parents 
    DifficultyScore INT, 
    FOREIGN KEY (PersonID, PersonTypeID) REFERENCES People (PersonID, PersonTypeID) 
) 

ただし、このアプローチには多くの問題があります。

  1. 各サブタイプ テーブルで追加の列を無駄にします。
  2. 実表に一意制約を追加する必要があります。これにより、より多くのスペースが浪費され (一意のインデックスとして実装されるため)、ベース テーブルへの更新が遅くなります。
  3. 外部キー制約には、(1 つではなく) 2 つの列のチェックが含まれるため、サブタイプ テーブルへの更新が遅くなります。

私の仮説は、代わりにスカラー関数を介してチェック制約を使用して一意性を強制する方がよいというものです。これにより、余分な列と一意のインデックスのための無駄なストレージがなくなり、ベース テーブルへの更新が高速化され、複合外部キーと同じパフォーマンスがサブタイプ テーブルへの更新で達成される可能性があります。

CREATE TABLE People 
( 
    PersonID     INT PRIMARY KEY,
    PersonTypeID INT REFERENCES PersonType (PersonTypeID), 
    Name         VARCHAR(10)
)

CREATE FUNCTION GetPersonTypeID (@PersonID INT)
RETURNS INT
AS
BEGIN
    RETURN 
    (
        SELECT PersonTypeID 
        FROM People
        WHERE PersonID = @PersonID
    )
END;

CREATE TABLE Students 
( 
    PersonID INT PRIMARY KEY REFERENCES People (PersonID) 
        CHECK (dbo.GetPersonTypeID(PersonID) = 1),
    EnrollmentDate DATETIME
) 

CREATE TABLE Teachers 
( 
    PersonID INT PRIMARY KEY REFERENCES People (PersonID)
        CHECK (dbo.GetPersonTypeID(PersonID) = 2),
    HireDate DATETIME
) 

CREATE TABLE Parents 
( 
    PersonID INT PRIMARY KEY REFERENCES People (PersonID)
        CHECK (dbo.GetPersonTypeID(PersonID) = 3),
    DifficultyScore INT
) 

このアプローチを使用しない理由はありますか?

4

1 に答える 1