微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql-server – 如何与特权孩子建立一对多的关系?

我希望有一对多的关系,其中对于每个父母,一个或零个孩子被标记为“最喜欢的”.但是,并非每个父母都会有一个孩子. (将父母视为本网站上的问题,将儿童视为答案,将最喜欢的视为已接受的答案.)例如,
TableA
    Id            INT PRIMARY KEY

TableB
    Id            INT PRIMARY KEY
    Parent        INT NOT NULL FOREIGN KEY REFERENCES TableA.Id

我看到它的方式,我可以将以下列添加到TableA:

FavoriteChild INT NULL FOREIGN KEY REFERENCES TableB.Id

或表B中的以下列:

IsFavorite    BIT NOT NULL

第一种方法的问题是它引入了一个可以为空的外键,据我所知,它不是标准化形式.第二种方法的问题是需要做更多的工作以确保最多只有一个孩子是最喜欢的.

我应该使用什么样的标准来确定使用哪种方法?或者,我还没有考虑其他方法吗?

我正在使用sql Server 2012.

解决方法

另一种方式(在FOREIGN KEY关系中没有Null和没有循环)是有第三个表来存储“最喜欢的孩子”.在大多数DBMS中,您需要在TableB上使用额外的UNIQUE约束.

@Aaron更快地发现上面的命名约定相当麻烦并且可能导致错误.如果您的表中没有Id列,并且列(已连接的)在出现的许多表中具有相同的名称,那么通常会更好(并且会让您保持理智).所以,这是一个重命名

Parent
    ParentID        INT NOT NULL PRIMARY KEY

Child
    ChildID         INT NOT NULL PRIMARY KEY
    ParentID        INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
    UNIQUE (ParentID,ChildID)

FavoriteChild
    ParentID        INT NOT NULL PRIMARY KEY
    ChildID         INT NOT NULL 
    FOREIGN KEY (ParentID,ChildID) 
        REFERENCES Child (ParentID,ChildID)

sql-Server(您正在使用)中,您还可以选择您提到的IsFavorite位列.每位父母最喜欢的孩子可以通过过滤的唯一索引来完成:

Parent
    ParentID        INT NOT NULL PRIMARY KEY

Child
    ChildID         INT NOT NULL PRIMARY KEY
    ParentID        INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
    IsFavorite      BIT NOT NULL

CREATE UNIQUE INDEX is_FavoriteChild
  ON Child (ParentID)
  WHERE IsFavorite = 1 ;

并且不建议使用选项1的主要原因是,外键引用中的循循环径模式存在一些问题,至少在sql-Server中不是这样.

阅读一篇相当古老的文章SQL By Design: The Circular Reference

当从两个表中插入或删除行时,您将遇到“鸡与蛋”问题.我应该首先插入哪个表 – 不违反任何约束?

为了解决这个问题,您必须定义至少一个可为空的列. (好吧,从技术上讲你没必要,你可以将所有列都设置为NOT NULL,但只能在DBMS中,比如Postgres和Oracle,已经实现了可延迟的约束.请参阅@Erwin在类似问题中的答案:Complex foreign key constraint in SQLAlchemy如何实现这一点在Postgres完成).不过,这种设置感觉就像在冰上滑冰一样.

在SO(但是对于MysqL)In SQL,is it OK for two tables to refer to each other?检查一个几乎相同的问题,我的答案几乎相同. MysqL虽然没有部分索引,但唯一可行的选择是可以为空的FK和额外的表解决方案.

原文地址:https://www.jb51.cc/mssql/80572.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐