【问题标题】:Inserting data into SQL Server 2012将数据插入 SQL Server 2012
【发布时间】:2012-12-24 08:06:39
【问题描述】:

我正在使用 SQL Server 2012

我有两个表,PersonCouplePerson 有一个来自 Couple 的外键,Couple 有一个来自“Person”的外键。

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

如何解决?

【问题讨论】:

  • 为什么你需要给两个表相互提供外键?
  • 最好把表格定义贴出来。
  • 一些 DBMS 允许您将约束定义为 deferred,以便在提交事务时而不是在运行 insert 时评估它们。不确定 SQL Server 2012 是否有这样的功能。
  • @ypercube 代码已插入问题中
  • 使ChildOfCoupleId 上的Person 可以为空- 毕竟,您并不总是手头有所有这些信息。这样,您可以将Person 插入表中,而无需指定CoupleId(如果信息可用,可以稍后添加)

标签: sql sql-server-2012


【解决方案1】:

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

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

  1. 不要求您同时知道两个元素 - 如果您只知道一个父元素,则可以输入。

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

  3. 不会强迫您为父母 Couple 的参与定义开始和停止日期——我注意到您没有将其称为 Marriage,但您使用的是 Husband 和 @ 987654330@。因此,如果您想对真实的、破碎的世界进行建模,则不一定要知道这些信息。

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

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

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

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

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

【讨论】:

    【解决方案2】:

    我认为您必须认真考虑更改此架构。除了插入数据的问题外,当您尝试删除数据时,您也会遇到完全相同的问题。 marc_c 给出的解决方案,使用 null 有助于一些,但不是最好的事情。你能做的最好的就是把另一张桌子带进你的设计中,并在那里做你对情侣的参考。

    【讨论】:

      猜你喜欢
      • 2015-08-09
      • 1970-01-01
      • 1970-01-01
      • 2017-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      相关资源
      最近更新 更多