标识列与复合主键分开

时间:2013-01-27 17:16:42

标签: sql sql-server database database-design

我有一张代表足球比赛的桌子:

  • 日期
  • 对手

我觉得{Date,Opponent}是主键,因为在这个表中每个日期永远不会有多个对手。问题是当我在其他表中创建外键约束时,我必须在其他表中包含Date和Opponent列:

足球比赛统计表:

  • 日期
  • 对手
  • 赛事(进球,黄牌等)

理想情况下,我希望:

足球比赛表:

  • ID
  • 日期
  • 对手

足球比赛统计表:

  • SoccerMatchID
  • 赛事(进球,黄牌等)

其中SoccerMatch.ID是唯一ID(但不是主键),{Date,Opponent}仍然是主键。

问题是SQL Server似乎不允许我将ID定义为唯一标识,而{Date,Component}是主键。当我转到ID的属性时,信号唯一标识的部分将显示为“否”。

(我假设每个人都同意我应该尝试实现上述目标,因为这是一个更好的设计?)

1 个答案:

答案 0 :(得分:1)

我认为大多数人都没有使用图形设计器来做这件事,因为图形设计师正在阻止它,而不是SQL Server。尝试在查询窗口中运行DDL:

ALTER TABLE dbo.YourTable ADD ID INT IDENTITY(1,1);
GO
CREATE UNIQUE INDEX yt_id ON dbo.YourTable(ID);
GO

现在您可以在其他表中引用此列没问题:

CREATE TABLE dbo.SomeOtherTable
(
  MatchID INT FOREIGN KEY REFERENCES dbo.YourTable(ID)
);

那就是说,我发现列名ID完全没用。如果它是MatchID,为什么不在架构中出现的任何地方调用它MatchID?是的,它在PK表中是多余的,但整个模型中的IMHO一致性更为重要。

就此而言,为什么你的表名为SoccerMatch?你有其他种类的比赛吗?我认为Matches的唯一ID = MatchID。这样,如果您以后有不同类型的匹配,则无需为每项运动创建新表 - 只需添加某种类型的type列即可。如果你只有足球,那么SoccerMatch是多余的,不是吗?

另外,我建议关键和唯一索引是相反的方式。如果您不打算使用多列密钥进行外部参考,那么至少在我看来,将PK作为您在其他表中引用引用的内容更为直观。所以我会说:

CREATE TABLE dbo.Matches
(
  MatchID INT IDENTITY(1,1),
  EventDate DATE, -- Date is also a terrible name and it's reserved
  Opponent <? data type ?> / FK reference?
);

ALTER TABLE dbo.Matches ADD CONSTRAINT PK_Matches
  PRIMARY KEY (MatchID);

ALTER TABLE dbo.Matches ADD CONSTRAINT UQ_Date_Opponent
  UNIQUE (EventDate, Opponent);