如何实现双向引用表?

时间:2012-06-19 20:21:31

标签: sql sql-server database tsql

我有一张桌子学校和一张桌子老师有一对多的关系。然而,其中一位教师是学校的原则,只有一位教师才是学校的原则。所以我想在School表中保存教师ID(原则)如下:

CREATE TABLE School (
    ID INT PRIMARY KEY,
    Name VARCHAR(40),
    PrincipleID INT FOREIGN KEY REFERENCES Teacher.ID
)

CREATE TABLE Teacher (
    ID INT PRIMARY KEY,
    Name VARCHAR(40),
    SchoolID INT FOREIGN KEY REFERENCES School.ID
)

我知道我可以放弃学校表中的外键引用,但这不是一个选项。

我应该在创建表后创建引用吗?如果是,怎么样?

4 个答案:

答案 0 :(得分:3)

另一种解决方案是创建一个新表,让我们说只有两个字段的SchoolsPrinciples:

CREATE TABLE SchoolsPrinciples
(
  SchoolId int,
  TeacherId int,
  CONSTRAINT uc_SchoolTeacher UNIQUE (SchoolId, TeacherId)
)

一个独特的约束让你每个学校只能获得一位教师。

答案 1 :(得分:2)

构建表时,您需要将约束添加为单独的alter语句。另请注意,在创建外键时,应仅指定表名,而不是引用的列(主键隐含该列)。

CREATE TABLE School (
    ID INT PRIMARY KEY,
    Name VARCHAR(40),
    PrincipleID INT);

CREATE TABLE Teacher (
    ID INT PRIMARY KEY,
    Name VARCHAR(40),
    SchoolID INT 
      CONSTRAINT FK_Teacher_School 
      FOREIGN KEY REFERENCES School);

ALTER TABLE School add
    CONSTRAINT FK_School_Teacher 
    FOREIGN KEY (PrincipleID) REFERENCES Teacher;

添加数据时,您需要将PrincipleID字段设置为单独的更新:

insert into School (ID, Name)
values (1, 'Blarg Elementary');

insert into Teacher (ID, Name, SchoolID)
values (1, 'John Doe', 1),
       (2, 'Bob Smith', 1),
       (3, 'Adam Walker', 1);

update School set PrincipleID = 2 where ID = 1;

答案 2 :(得分:1)

IsPrincipal表上放置一个布尔Teacher。或者添加第三个关系表

CREATE TABLE SchoolPrincipals (
  INT SchoolID PRIMARY KEY FOREIGN KEY REFERENCES School.ID,
  INT TeacherID FOREIGN KEY REFERENCES Teacher.ID
)

保持一切都整洁,没有痛苦的删除逻辑。

答案 3 :(得分:1)

您可以将教师表中的列作为

  1. IsPrincipal其中只有一行的值与引用的值相同 作者:jonnyGold,

          This can be checked by triggers.
                        OR
          You can use filtered index if using Sql Server 2008.
               Create unique filtered index where SchoolID, IsPrincipal 
               is NOT NULL and are unique
    
  2. 老板,其中包含校长ID因此创建employee manager relationship,在您的情况下不适合。
  3. CREATE TABLE EmpManager (    TeacherID int    SchoolID int    IsPrincipal位 ) 并使用过滤索引或触发器来处理场景。

    修改

    CREATE TABLE [dbo].[Teacher](
        [ID] [int] NOT NULL primary key,
        [Name] [varchar](40) NULL,
        [SchoolID] [int] NULL,
    ) 
    GO
    
    CREATE TABLE [dbo].[School](
        [ID] [int] NOT NULL primary key,
        [Name] [varchar](40) NULL,
        [PrincipleID] [int] NULL,
    )
    GO
    
    ALTER TABLE [dbo].[Teacher]  WITH CHECK ADD  CONSTRAINT [FK_Teacher_School] FOREIGN KEY([SchoolID])
    REFERENCES [dbo].[School] ([ID])
    GO
    
    ALTER TABLE [dbo].[School]  WITH CHECK ADD  CONSTRAINT [FK_School_Teacher] FOREIGN KEY([PrincipleID])
    REFERENCES [dbo].[Teacher] ([ID])
    GO
    

    enter image description here

    更好的设计应该是ADC建议的

    enter image description here