【问题标题】:Need Help Creating Primary Key/Foreign Key Relationships between Multiple Tables需要帮助在多个表之间创建主键/外键关系
【发布时间】:2015-09-15 20:59:03
【问题描述】:

背景:

(我使用的是 Microsoft SQL Server 2014)

我的公司收到包含许多帐户 (tblAccount) 的数据文件 (tblFile)。对于每个数据文件,我们可能会执行多个“定价”(tblPricing),这些“定价”可能包含文件中的所有帐户,也可能只包含其中的一部分,但“定价”不能包含任何不包含在定价所依据的文件中。所以,总结一下:

  1. 我们得到一个文件
  2. 此文件可以包含多个帐户
  3. 我们从这个单一文件中创建了许多定价
  4. 每个定价都可以包含它所链接到的文件中的全部或部分帐户,但不能包含不在该文件中的帐户

这是今天存在的(方式)简化的数据库图:

问题:

到目前为止的工作情况:

  • tblFiletblPricing之间的1:Many关系
  • tblFiletblAccount 之间的 Many:Many 关系(一个帐户可以存在于多个文件中)
  • tblPricingtblAccount 之间的 Many:Many 关系(因为可以执行多个定价,所以一个帐户可以存在多个定价)

我们的问题来自于试图在文件拥有的帐户子集和定价拥有的帐户子集之间强制执行完整性。使用上述结构,tblPricingAccounts 可以包含 tblFileAccounts 中未包含的帐户,这违反了我们对每个定价仅包含其所基于的文件中的帐户的要求。

我已经尝试更改外键关系,我打破了tblPricingAccountstblAccount 之间的链接,从tblPricingAccounts 中删除了“acct_id”,而是将tblPricingAccounts 链接到tblFileAccounts(是的,我知道我需要tblFileAccounts 中的主键,我有一个)。但是,然后我可以将任何我想要的“pricing_id”插入tblPricingAccounts。现在我可以将帐户链接到与最初包含这些帐户的文件无关的定价。

需要

归根结底,我并不关心我的数据库的结构或关系是什么样的。我只需要满足以下条件,我似乎无法完全理解它:

  1. 一个文件包含许多帐户。
  2. 一个文件包含许多定价。
  3. 定价包含多个帐户,但这些帐户必须包含在定价所链接到的文件中。

感谢任何帮助,我愿意接受所有可以在 SQL Server 中执行的建议。最终,我正在围绕这个数据库构建一个 Web 应用程序,并且我正在使用 Entity Framework 6 来让生活更轻松(主要是......)。我显然可以通过我的代码强制执行上述 3 个需求,但我真的希望数据库成为强制执行这种完整性的最后一道防线。

【问题讨论】:

  • 您是否考虑过使用tblPricingAccounts 上的触发器来查找acct_idtblFileAccounts 并匹配tblPricing 中的file_id
  • 嗯,不。当然,我正在设计我的 Web 应用程序,它将使用 asp.net 实体框架使用这个数据库,它不会识别触发器,但值得研究至少在数据库级别保持完整性。当我阅读更多关于触发器的内容时​​会更新......

标签: sql-server database entity-framework tsql


【解决方案1】:

这是一种外键约束不打算处理的情况。 FK 约束测试表之间是否存在值;它们不强制执行特定的基数要求。

简单基数是问题中提到的“一对多”、“多对多”关系。不过,您更复杂的需求本质上仍然与基数有关:要求某些行子集以特定方式与某些其他行子集相关。如果您愿意,可以使用“窗口基数”。 (据我所知是我自己的造币。)

正如 cmets 对该问题所建议的,在数据​​库中完全执行此操作的一种方法是通过 触发器。在这种情况下,精心设计的触发器可能会测试要插入的新行是否有效,如果不是,则在不插入的情况下出错。对于批量插入,您可能希望插入有效行并丢弃其余行,或者如果 1+ 行无效,则将所有内容返回。您还可以制作逻辑来处理可能破坏完整性要求的更新或删除。

请注意,触发器会对性能产生负面影响,尤其是在频繁更改表的情况下。

其他方法是按照建议在应用程序逻辑中处理此问题,和/或无论如何都允许数据进入表,但定期验证现有数据。例如,每晚的进程可以识别不符合此要求的数据并将其传递给人工进行纠正。

【讨论】:

  • 我认为这很有意义。我要么期待在我面前有一些简单的答案,要么基本上是你提供的这个答案。我再次使用实体框架对客户端应用程序进行编程,因此我肯定能够以这种方式保持“窗口基数”。我也只是希望将“窗口基数”添加到数据库本身中,作为最后一道防线。触发器应该可以解决问题,考虑到数据库事务的范围,我认为它们不会对性能产生太大影响。感谢您深思熟虑的答案!
【解决方案2】:

听起来tblFileAccounts 可能是多余的。尝试完全删除它并通过 tblPricingAccounts 和 tblPricing 中捕获的关系推断哪些帐户存在于哪些文件中。

如果这满足您的需要,并且没有正确属于 tblFileAccounts 对象(表)的属性(列),那么我认为您的问题已经解决。

【讨论】:

  • 很遗憾,它不能满足我们的需求,因为可能永远不存在定价,我们仍然需要确定哪些帐户属于哪个文件。
  • 一个文件的两个定价能否都包含同一个帐户(该文件中的一个帐户)?
  • 是的。我们的业务理念是接收包含帐户的文件。然后,我们对这些文件进行定价,寻找目标,例如 IRR、最高价格等。因此我们可以对单个文件执行 5 次定价,并且 5 次定价中的每一个都可能具有来自该文件的唯一帐户子集。那么......我们可能会获得一个新文件作为“更新”,其中可能有第一个文件没有的其他帐户。然后我们将重复定价练习。
  • 我的新答案有点取代了这个,现在我想多了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-03
相关资源
最近更新 更多