5

SQLServer2012を使用しています

2つのテーブルがPersonありCouplePersonは「Person」からの外部キーと「Person」からの外部キーCoupleCouple持っています。

それぞれにデータを挿入しようとすると、各テーブルに他のテーブルのFKがあり、最初は両方が空であるため、エラーが発生します。

CREATE TABLE [dbo].[Couple](
    [CoupleId] [int] IDENTITY(1,1) NOT NULL,
    [HusbandPersonId] [int] NOT NULL,
    [WifePersonId] [int] NOT NULL,
    [StartDate] [date] NOT NULL,
    [EndDate] [date] NOT NULL,
 CONSTRAINT [PK_Couple] PRIMARY KEY CLUSTERED 
(
    [CoupleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[Person](
    [PersonId] [int] IDENTITY(1,1) NOT NULL,
    [ChildOfCoupleId] [int] NOT NULL,
    [CityOfBirth] [int] NOT NULL,
    [CityOfPermanentResidence] [int] NOT NULL,
    [CityOfCurrentResidence] [int] NOT NULL,
    [FirstName] [varchar](20) NOT NULL,
    [LastName] [varchar](20) NOT NULL,
    [BirthDate] [date] NOT NULL,
    [DeathDate] [date] NOT NULL,
    [IsMale] [bit] NOT NULL,
 CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
(
    [PersonId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY

ALTER TABLE [dbo].[Couple]  WITH CHECK ADD  CONSTRAINT [FK_Couple_Person] FOREIGN KEY([HusbandPersonId])
REFERENCES [dbo].[Person] ([PersonId])
GO
ALTER TABLE [dbo].[Couple] CHECK CONSTRAINT [FK_Couple_Person]
GO
ALTER TABLE [dbo].[Couple]  WITH CHECK ADD  CONSTRAINT [FK_Couple_Person1] FOREIGN KEY([WifePersonId])
REFERENCES [dbo].[Person] ([PersonId])
GO
ALTER TABLE [dbo].[Couple] CHECK CONSTRAINT [FK_Couple_Person1]
GO
ALTER TABLE [dbo].[Person]  WITH CHECK ADD  CONSTRAINT [FK_Person_Couple] FOREIGN KEY([ChildOfCoupleId])
REFERENCES [dbo].[Couple] ([CoupleId])
GO
ALTER TABLE [dbo].[Person] CHECK CONSTRAINT [FK_Person_Couple]
GO

これを解決する方法は?

4

2 に答える 2

3

親の再帰の無限ループに遭遇するため、すべての人に親がいる必要はありません。つまり、すべての子供の親になるには、親のいない「アダムとイブ」のカップルが必要です。

ChildOfCoupleIdこれで、 1 つの解決策として列を NULLableにすることができます。しかし、率直に言って、使用CoupleIdは最適ではないと思います。代わりに、 と を使用MotherIdFatherIdます。これは最終的に次のように優れています。

  1. 両方の要素を知っている必要はありません。一方の親しか知らない場合は入力できます。

  2. 個人を特定するためにクエリを実行する必要がある別のテーブルではなく、Personポイント内の FK を作成することにより、FK の関係を簡素化します。Person

  3. Couple親の関与の開始日と終了日を定義することを強制するものではありませMarriageん。したがって、実際の壊れた世界をモデル化したい場合は、その情報を必ずしも知っている必要はありません。HusbandWife

  4. 夫婦が一緒だった正確な時期から子供の親子関係を解きほぐします。カップルが結婚、離婚、再婚した場合、どの結婚の間に子供が妊娠したかを特定しています。単純な血統の場合、これは不要です。親を知る必要があるだけです。結婚が無効になったが、子供を妊娠できた場合はどうなりますか? では、親子情報をどのように保存しますか?私たちの世界では、親子関係はカップルの状態とは別の事実です。

最後に、多くの場合、NULL 可能な列は避けるのが最善です。次のような新しいテーブルを作成することで、これを実現できますParentage

CREATE TABLE dbo.Parentage (
   PersonID int NOT NULL
      CONSTRAINT FK_Parentage_Person
      FOREIGN KEY REFERENCES dbo.Person (PersonID),
   ParentID int NOT NULL,
   ParentIsMale bit NOT NULL,
   CONSTRAINT PK_Parentage PRIMARY KEY CLUSTERED (PersonID, ParentIsMale),
   CONSTRAINT FK_Parentage_Parent FOREIGN KEY (ParentID, ParentIsMale)
      REFERENCES dbo.Person (ParentID, IsMale)
);

FK を作成するに(ParentId, IsMale)は、テーブルに一意の制約または一意のインデックスを追加する必要があります。PersonPK/FK の一部として使用IsMaleすると、確実に 1 人の母親と 1 人の父親が得られます。

この設計は不格好に見えるかもしれませんが、長い目で見れば真のメリットをもたらします。個人の父親または母親の知識は、NULL 可能な列を更新するのではなく、行を挿入することによってエンコードされます。行がない場合、親は不明です。

この設計は、さまざまな種類の親 (遺伝、出生、養子) の記録にも簡単に適用できます。人は 2 人の遺伝的両親と生みの母親を持つことができます。その後、一連の悲惨な出来事により、すべての親が殺され、養子縁組されました(複数回)。ParentTypeIDそのため、PK を変更してから、、、FromDateおよびToDate列をテーブルに追加する必要があります。不適切な関係が表示されないようにするには、さらに調整が必要です (「生みの父親」など)。

于 2012-12-27T20:46:46.850 に答える
0

このスキーマの変更を真剣に検討する必要があると思います。データを挿入するときの問題に加えて、データを削除しようとするとまったく同じ問題が発生します。marc_c が提供する解決策は、 null を使用することである程度は役立ちますが、最善の方法ではありません。あなたができる最善のことは、別のテーブルをデザインに持ち込み、そこにカップルへの後方参照を作成することです。

于 2012-12-24T09:04:13.207 に答える