2012-12-24 70 views
5

我與SQL Server 2012數據插入到SQL Server 2012

工作,我有兩個表,PersonCouplePerson具有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 

如何解決這個問題?

+2

爲什麼很小的時候需要互相提供兩個表的外鍵? – Azzy

+4

發佈表定義會更好。 –

+0

某些DBMS允許您將約束定義爲* deferred *,以便在您提交事務時評估它們,而不是在運行「insert」時進行評估。不確定SQL Server 2012是否具有這樣的功能。 –

回答

3

你不能要求所有的人都有父母,因爲你會遇到無限循環的父母遞歸。也就是說,你必須有一個無父母的「亞當和夏娃」夫婦成爲所有孩子的父母。

現在,您可以將您的ChildOfCoupleId列作爲一個解決方案爲NULLable。但坦率地說,我認爲使用CoupleId並不是最佳選擇。相反,使用MotherIdFatherId。這是最好的,因爲它:

  1. 不需要你知道這兩個元素 - 如果你只知道一個父母它可以進入。

  2. 簡化通過使FKS在PersonPerson而不是必須進行查詢以確定他的另一表中的FK關係。

  3. 不強迫你有明確的起點和父Couple的介入停止日期 - 我注意到你不叫它Marriage,但使用的是HusbandWife。所以如果你想模擬真實的,破碎的世界,那麼不一定知道這些信息是必須的。

  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表,以創建一個FK,將其添加唯一約束或唯一索引上(ParentId, IsMale)。使用IsMale作爲PK/FK的一部分,確保你得到正好一個母親和一個父親。

雖然這種設計看起來笨重,但從長遠來看,它將提供真正的好處。一個人的父親或母親的知識通過插入一行來編碼,而不是更新一個NULLable列。如果沒有行,那麼父級是未知的。

這個設計也很容易適應記錄不同種類的父母:遺傳,出生,收養。一個人可能有2個遺傳父母和一個生母。然後,通過一系列災難性事件,所有父母都被殺害並被採納(甚至超過一次)。因此,您需要更改PK,然後將ParentTypeID,FromDateToDate列添加到表中。進一步的調整將有必要限制不恰當的關係被表示(如「生父」)。

0

我認爲你必須認真考慮改變這個模式。除了插入數據的問題之外,當您嘗試刪除數據時,您將遇到完全相同的問題。 marc_c給出的解決方案,使用null有助於一些,但不是最好的做法。你可以做的最好的事情是把另一張桌子帶進你的設計中,並讓你的背景引用一對。