sql - 将数据插入 SQL Server 2012

标签 sql sql-server-2012

我正在使用 SQL Server 2012

我有两张 table ,PersonCouple , 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

如何解决这个问题?

最佳答案

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

现在,您可以制作您的 ChildOfCoupleId列 NULLable 作为一种解决方案。但坦率地说,我认为使用 CoupleId不是最优的。相反,使用 MotherIdFatherId .这最终会更好,因为它:

  • 不需要您知道这两个元素——如果您只知道一个父元素,则可以输入它。
  • 通过在 Person 中制作 FK 来简化 FK 关系指向Person而不是必须查询才能确定人员的另一个表。
  • 不会强制您为父级定义开始和停止日期 Couple的参与--我注意到你没有调用它 Marriage但您正在使用 HusbandWife .因此,如果您想对真实的、 splinter 的世界进行建模,则不一定要了解这些信息。
  • 将 child 的出身与这对夫妇在一起的确切时间分开。如果一对夫妇结婚、离婚和再婚,那么您要指定 child 是在哪一段婚姻中受孕的。对于简单的血统,这是不必要的——你只需要知道 parent 。如果婚姻无效,但他们设法怀孕了怎么办?那么你将如何存储父子信息?在我们的世界中,出身与夫妻身份是截然不同的事实。

  • 最后,通常最好避免 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)
    );
    

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

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

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

    关于sql - 将数据插入 SQL Server 2012,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14018773/

    相关文章:

    php - 从 SQL Server 2012 和 PHP 填充的动态表中的额外行

    MySQL Sum() 多列

    sql - SQL 中的杂项星形查找字符

    java - 如何将oracle数据库中的值汇总到java中?

    sql - 删除给定键总和为零的行

    sql - super 简单的查询需要 39 秒才能执行

    java - SQL Server : How to get "OUTPUT" from Insert on JAVA?

    c# - 我需要将 XML 节点传递给两个不同 Excel 工作表的存储过程

    sql - Oracle 笛卡尔积与连接

    mysql - 获取两个日期之间的天数、小时数和分钟数及其各自的时间戳