数据库:如何区分“一个或多个”和“零或多个”关系?

时间:2011-04-04 12:49:56

标签: sql database tsql database-design

设计工具可以区分“一个TO 零或多个“一个TO 一个或多个关系。我可以想象如何实现“一个零或多个”关系:


CHILD_TABLE

(pk)chid_id
(fk)parent_id (必填)


PARENT_TABLE

(pk)parent_id


如何实施“一对一或多”关系?怎么说父母需要至少一个孩子?或者“一个或多个”通常实现为“零或多个”?

6 个答案:

答案 0 :(得分:8)

很明显,强制执行约束(例如您指定的约束)将要求客户端有时会发出(并且DBMS引擎接受)某些可能被标记为“同时更新”的内容,即多个不同的表正在在任何约束检查之前更新。

SQL 语言(我的意思是,标准)通过CREATE ASSERTION为它提供支持。唉,现有的引擎都不支持这种说法。

使用当前现有的SQL引擎可以实现的唯一方法是推迟约束检查,直到所有更新完成后(当然,如果您的引擎支持此操作)。如果您的数据库是“共享的”并且也可以由其他程序更新,那么在应用程序代码或业务逻辑中实施这些约束最终将完全没有约束条件。

确实存在支持强制执行约束的系统,但它们不是SQL系统。

aioobe的解决方案非常原创,但请记住,您只能通过将“many”(/ child)一侧的所有列复制到“one”(/ parent)一侧来实现此目的(因为否则您仍然拥有两个表之间的问题相同,除了“或更多”部分已经消失,但这不是问题所在。)如果你这样做,那么在以下情况下你将面临很大的困难:

  • 针对“很多”方面编写查询(您必须确保位于“一”侧的另一行将始终与多方进行UNIONed),
  • 在“很多”方面强制执行密钥(您必须注意到,许多方面的密钥与位于“一”方的另一条密钥的值不相同,
  • 当引用表本身就是您的“一个或多个”时强制引用完整性(您应该看到它对于存在于“one”侧的另一行的引用也是有效的)

所以aioobe的解决方案虽然原创,但可能会产生比解决方案更多的新问题。

答案 1 :(得分:6)

通过业务逻辑或至少使用事务来实现1对1或更多关系。您不能同时插入两个表;你一次插入一张桌子。因此,您需要在插入子项之前插入父项,并且数据库没有内置的方法来强制执行所需的逻辑。

如果将两个INSERT语句包装在事务中,则可以保证子插入失败,将回滚父插入。但是,如果没有孩子,则确保不插入父项,这取决于业务逻辑。

答案 2 :(得分:3)

在SQL Server中,外键关系始终是“一”到“零或更多”。 “一个”到“一个或多个”关系也会使得插入初始数据非常困难。 (您必须先禁用外键才能在父表中插入记录)

答案 3 :(得分:2)

我所知道的最好的方法是通过存储过程执行所有插入操作,该存储过程具有事务,并在子节点失败时回滚父插入。

我看到的另一种方式(但实际上有点像黑客攻击)是让子级中的所有字段除了自动生成的Id和FK可以为空之外,然后插入只有来自父表的触发器的id的记录。然后,对子表进行更新,以添加其他字段的详细信息。如果它们应该可以为空或者在子表的数据输入时可能没有任何数据,则可以接受,但如果字段不应为空,则可以创建数据迭代问题。

答案 4 :(得分:1)

您可以将其实现为“一对一”加上“一对多或更多”

答案 5 :(得分:0)

SQL语言通常对参照完整性和完整性约束的支持非常有限。标准SQL(以及大多数(如果不是所有流行的SQL DBMS)都不支持一对一或多个约束。 SQL FOREIGN KEY约束在关系的引用端始终是可选的。数据建模工具和语言通常支持这样的约束(ORM,ERD),但DBMS很少允许您实现它们。