将数据插入SQL Server 2012

Moh*_*nem 5 sql sql-server-2012

我正在使用SQL Server 2012

我有两个表,Person并且Couple,Person具有从外键Couple,并Couple具有从"人"的外键.

当我尝试向每个表插入数据时,会发生错误,因为每个表都有来自另一个表的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
Run Code Online (Sandbox Code Playgroud)

怎么解决这个?

Eri*_*ikE 3

你不能要求所有人都有父母,因为你会陷入父母递归的无限循环。也就是说,必须有一对没有父母的“亚当和夏娃”夫妇才能成为所有孩子的父母。

现在,您可以将ChildOfCoupleId列设置为 NULL,作为一种解决方案。但坦率地说,我认为使用CoupleId并不是最佳选择。相反,使用MotherIdFatherId。这最终更好,因为它:

  1. 不需要您知道这两个元素——如果您只知道一个父元素,则可以输入它。

  2. 通过使 FK 指向PersonPerson不是另一个必须查询以确定人员的表来简化 FK 关系。

  3. 不强迫您为父母Couple的参与定义一个定义的开始和停止日期——我注意到您没有调用它,Marriage而是使用了Husbandand Wife。因此,如果你想对真实的、破碎的世界进行建模,就必须不一定知道这些信息。

  4. 将孩子的出身与夫妻在一起的确切时间分开。如果一对夫妇结婚、离婚和再婚,那么您将指定孩子是在哪次婚姻期间怀上的。对于简单的血统来说,这是不必要的——你只需要知道父母。如果婚姻无效,但他们成功怀上了孩子怎么办?那么你将如何存储父子信息呢?在我们的世界中,出身与夫妻身份是不同的事实。

最后,通常最好避免可空列。您可以通过创建一个新表来完成此操作,例如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)
);
Run Code Online (Sandbox Code Playgroud)

您必须在(ParentId, IsMale)表中添加唯一约束或唯一索引Person才能为其创建 FK。IsMale作为 PK/FK 的一部分使用可确保您恰好得到一位母亲和一位父亲。

虽然这种设计可能看起来很笨重,但从长远来看,它将带来真正的好处。一个人的父亲或母亲的知识是通过插入行而不是更新可空列来编码的。如果没有行,则父级未知。

这种设计也很容易适应记录不同类型的父母:遗传、出生、收养。一个人可以有两个遗传父母和一个亲生母亲。然后,通过一系列灾难性事件,所有父母都被杀害并被收养(甚至不止一次)。因此,您需要更改 PK,然后将ParentTypeIDFromDateToDate列添加到表中。需要进一步调整以限制不正当关系的表达(例如“亲生父亲”)。