【发布时间】:2011-08-23 04:23:07
【问题描述】:
我有一个表格设计问题,我需要一个巧妙的解决方案。
假设我有两个表,有关系:
Contract 1---N Payment
现在,假设我有需要进入这些表的遗留数据。但问题是,许多遗留的支付条目是跨多个合约聚合的
所以我们实际上可以将其视为:
新:
SomethingAboveContract 1---N Contract 1---N Payment
旧版:
SomethingAboveContract 1---N Payment
现在,我可以通过在 Contract 和 Payment 之间创建 M-N 关系来解决这个问题。
Contract 1---N ContractPayment N---1 Payment
(我可以识别与聚合付款相关的所有合同)
这对于遗留数据来说很好,但我确实希望在未来强制执行合同和付款之间的 1-N 关系。所以,用我很不方便的涂鸦来说明,我想这样做:
即如果付款是聚合的,ContractID 将为 NULL,否则不应为 null。换句话说,我需要找到一种方法来在 Payment 表上强制执行以下或有事项:
- 如果 PaymentID 出现在 ContractPayment 中,则 ContractID 可为空
- 如果 PaymentID 未出现在 ContractPayment 中,则 ContractID 不能为空
不过我不知道该怎么做。
即使这是可能的,它看起来确实有点难看(遗留数据转换总是如此)。因此,如果有人有更优雅的解决方案,那就太好了。否则,任何可行的方法!
谢谢
卡尔
【问题讨论】:
-
由于您不能编写影响多个表的 DML 语句,因此这里存在先有鸡还是先有蛋的问题 - 在 @ 中存在一行之前,您无法插入
ContractPayment987654328@,但您无法在 Payment 中插入所需的行,因为它有一个空ContractID,并且在ContractPayment中没有行 -
@Damien_The_Unbeliever:我猜你在“DML”的定义中很方便地省略了
SELECT:) -
@onedaywhen - 因为
SELECT(没有INTO)不操纵数据,不,我不包括SELECT在D M L. 即使我们确实包含了它,您是否知道有任何方法可以让SELECT语句影响任何表(更不用说多个表了) -
我不知道有什么方法可以指定条件可空性,除了可能在触发器中强制执行这种关系,我不建议这样做。 (
触发器中的业务逻辑,也称为“如何射中自己的脚,让你的同事讨厌你!”)。鉴于您有合同和付款之间的连接表,我不明白合同和付款之间直接联系的价值。连接表、Contract 和 Payment 之间的外键与直接链接的作用相同,只是它们 A) 间接且 B) 更灵活。 YMMV。 -
@Damien_The_Unbeliever:我不认为 DML 是正式定义的,例如不是 SQL 标准的一部分。尽管您无疑会发现许多诸如您自己的排除
SELECT(没有INTO),但我认为大多数都包含它,例如Wikipedia's。没什么大不了的,当然:)
标签: sql sql-server-2008 many-to-many database-design