定义外键时出错

时间:2014-02-16 17:11:14

标签: sql sql-server database foreign-keys data-integrity

我定义了以下两个数据库表:

CREATE TABLE [dbo].[Classrooms] (
  [ID]               INT          IDENTITY (1, 1) NOT NULL,
  [SystemAccount_ID] INT          NOT NULL,
  [ClassroomName]    VARCHAR (30) NOT NULL,
  CONSTRAINT [PK_Table] PRIMARY KEY CLUSTERED ([ID]),
  CONSTRAINT [FK_Classrooms_SystemAccount] FOREIGN KEY ([SystemAccount_ID]) REFERENCES [dbo].[SystemAccounts] ([ID])
);

CREATE TABLE [dbo].[Students] (
   [ID]               INT          IDENTITY (1, 1) NOT NULL,
   [SystemAccount_ID] INT          NOT NULL,
   [Classroom_ID]     INT          NULL,
   [PhotoID]          INT          NULL,
   [FirstName]        VARCHAR (20) NOT NULL,
   [LastName]         VARCHAR (40) NOT NULL,
   [NewsTemplate]     TINYINT      NOT NULL,
   CONSTRAINT [PK_Students] PRIMARY KEY CLUSTERED ([ID] ASC),
   CONSTRAINT [FK_Students_Classrooms] FOREIGN KEY ([Classroom_ID]) REFERENCES [dbo].[Classrooms] ([ID]),
   CONSTRAINT [FK_Students_SystemAccounts] FOREIGN KEY ([SystemAccount_ID]) REFERENCES [dbo].[SystemAccounts] ([ID])
);

数据模型详情:

  • 学生通过Classroom_ID FK
  • 属于零个或一个教室
  • 学生通过SystemAccount_ID FK
  • 属于一个系统帐户
  • 教室通过SystemAccount_ID FK属于一个系统帐户(暗示系统帐户可以有零个或多个教室)

我尝试做的是在学生被添加到教室时(通过在Students表中设置Classroom_ID键)强制执行教室属于与学生相同的系统帐户。我可以在业务逻辑层轻松强制执行此操作,但后来我要求每个程序员都记得这样做。理想情况下,我可以在数据层执行此操作作为约束。

我尝试在学生表中添加FK约束:

CONSTRAINT [FK_Students_ToTable] FOREIGN KEY ([SystemAccount_ID]) REFERENCES [Classrooms]([SystemAccount_ID])

这导致SQL Server的以下错误称赞:

  

由于验证错误,无法继续更新   请更正以下错误,然后重试。

     

SQL71516 ::引用的表'[dbo]。[Classrooms]'不包含与外键中的引用列列表匹配的主键或候选键。如果引用的列是计算列,则应该保留它。

我尝试了一些不同的东西,但我的SQL mojo并不足以破解这个问题。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

UNIQUE中的两列组合中添加Classrooms约束:

CREATE TABLE [dbo].[Classrooms] (
  [ID]               INT          IDENTITY (1, 1) NOT NULL,
  [SystemAccount_ID] INT          NOT NULL,
  [ClassroomName]    VARCHAR (30) NOT NULL,
  CONSTRAINT [PK_Table] 
    PRIMARY KEY CLUSTERED ([ID]),
  CONSTRAINT [FK_Classrooms_SystemAccount] 
    FOREIGN KEY ([SystemAccount_ID]) 
    REFERENCES [dbo].[SystemAccounts] ([ID]),
  CONSTRAINT [UQ_Classrooms_ID_SystemAccount_ID] 
    UNIQUE ([SystemAccount_ID], [ID])
);

然后,在Students表格中,将两个FOREIGN KEY约束合并为一个,或者在您的情况下(因为Classroom_ID可以取消),将FK更改为Classroom使用两列的组合:

CREATE TABLE [dbo].[Students] (
  [ID]               INT          IDENTITY (1, 1) NOT NULL,
  [SystemAccount_ID] INT          NOT NULL,
  [Classroom_ID]     INT          NULL,
  [PhotoID]          INT          NULL,
  [FirstName]        VARCHAR (20) NOT NULL,
  [LastName]         VARCHAR (40) NOT NULL,
  [NewsTemplate]     TINYINT      NOT NULL,
  CONSTRAINT [PK_Students] 
    PRIMARY KEY CLUSTERED ([ID] ASC),
  CONSTRAINT [FK_Students_Classrooms] 
    FOREIGN KEY ([SystemAccount_ID], [Classroom_ID]) 
    REFERENCES [dbo].[Classrooms] ([SystemAccount_ID], [ID]),
  CONSTRAINT [FK_Students_SystemAccounts]         -- this wouldn't be needed if
    FOREIGN KEY ([SystemAccount_ID])              -- Classrooms_ID was NOT NULL
    REFERENCES [dbo].[SystemAccounts] ([ID])
);