2014-10-19 73 views
1

说我有这样的结构:外键引用许多表的一个

体育

reference int identity not null, primary key (ID), 
Duration int, --e.g. football is 90 minutes 
Players int, 
SportID int, 
SportType int --0 for football and 1 for tennis 

网球

Reference int IDENTITY NOT NULL, 
TurfType int, 
-- + more fields related to Tennis 

足球

等我能想到这样做的唯一的办法就是在 Sport表有个
Reference int IDENTITY NOT NULL, 
-- + more fields related to Football 

Sport.SportID引用无论是网球或足球或体操说什么表Sport.SportID引用。

虽然这看起来不正确。这是最好的方法吗?

+0

这是一个可怕的方法。由于你“引用”了几个表中的一个,你基本上**不能**引用任何东西。你应该改变这种关系:'Tennis'应该参考'Sport','Football'应该参考'Sport'--那么你将拥有**真实的**,可执行的参考完整性约束! – 2014-10-19 13:04:55

+1

@marc_s,那就意味着Sport有FootballID,TennisID等等。会有很多的空值。 – w0051977 2014-10-19 13:07:41

+1

是的 - 那又怎样? Null的不会伤害....至少这样,你有**真正的**完整性 - 不仅仅是一个*看起来像*完整,这是没有价值的... – 2014-10-19 13:08:15

回答

0

您是否试图给出一项运动的名称,以便数据库显示详细信息(持续时间,所使用场的类型,球员数量等)?

+1

是的。这是一条评论,而不是一个答案。 – w0051977 2014-10-19 13:05:11

+0

@ w0051977他无法评论他的名誉 – 2014-10-19 13:36:29

+0

@Begueradj,这很公平。除非你有口水,否则不要回答。 – w0051977 2014-10-19 13:38:03

2

具有SportType列是合理的。您可以使用结构接近这个功能,比如:

create table Sports (
    SportsId int identity not null, primary key (ID), 
    Duration int, --e.g. football is 90 minutes 
    Players int, 
    SportType varchar(10), 
    SportId int, 
    check (SportType in ('Football', 'Tennis'), 
    FootballId as (case when SportType = 'Football' then SportId end), 
    TennisId as (case when SportType = 'Tennis' then SportId end), 
    foreign key (FootballId) references Football(FootballId), 
    foreign key (Tennis) references Tennis(Tennis) 
); 

注意,这里使用计算列外键引用,以确保引用完整性。

+0

谢谢+1。说SportID是一个footballID。我将如何做体育和足球之间的内部联合,以返回两个表中的所有字段? – w0051977 2014-10-19 13:11:48

+0

@ w0051977。 。 。您可以使用计算列“FootballId”作为“连接”。 – 2014-10-19 19:49:20

1

在{Sport}和{Tennis/Fotball}之间有"is-a relationship"。在这种情况下,“体育”代表超级班,网球/足球是分班。使用面向对象的编程语言,可以使用继承完成此设计。

Sport.SportID引用无论是网球或足球或体操等

这意味着,这种关系是唯一的。

在T-SQL中,因为没有继承,一个溶液来实现独占是-的关系是使用Type柱和如下的化合物FK(FOREIGN KEY (SportID, Type)):

-- The "superclass" table 
CREATE TABLE dbo.Sport (
    SportID INT IDENTITY(1,1) PRIMARY KEY, 
    Type CHAR(1) NOT NULL CHECK (Type IN ('T', 'F' /*...*/)), 
    UNIQUE(SportID, Type) 
    -- , ... 
); 
GO 
-- The "subclass" tables 
CREATE TABLE dbo.Tennis (
    SportID INT IDENTITY(1,1) PRIMARY KEY, 
    FOREIGN KEY (SportID) REFERENCES dbo.Sport(SportID), 
    Type CHAR (1) NOT NULL CHECK (Type = 'T'), 
    FOREIGN KEY (SportID, Type) REFERENCES dbo.Sport(SportID, Type) 
    -- , ... 
); 
GO 
CREATE TABLE dbo.Fotball (
    SportTypeID INT IDENTITY(1,1) PRIMARY KEY, 
    FOREIGN KEY (SportTypeID) REFERENCES dbo.SportType(SportTypeID), 
    Type CHAR (1) NOT NULL CHECK (Type = 'F'), 
    FOREIGN KEY (SportID, Type) REFERENCES dbo.Sport(SportID, Type) 
    -- , ... 
); 
+0

感谢+1。说SportID是一个footballID。我将如何做体育和足球之间的内部联合,以返回两个表中的所有字段? – w0051977 2014-10-19 13:56:44

+0

@ w0051977:答:简单:'SELECT ... FROM dbo.Sport s INNER JOIN dbo.Fotball f ON s.SportID = f.SportID'。注意:is-a关系应该从子类读到超类。例如:一个footballID是一个sportID。 – 2014-10-19 14:02:20

+0

如果我只提供一个ID并希望从运动表和特定表中获得信息足球,网球等等,我不知道,这项运动来自哪个桌子。 – w0051977 2014-10-19 14:04:27