SQL一对一关系和结果模式

SQL一对一关系和结果模式,sql,schema,field,table-relationships,Sql,Schema,Field,Table Relationships,我正在创建抵押/贷款数据库-我有一个名为mortgages的表,其中包含以下字段: 抵押贷款id 客户识别码 *费率类型*(可以是:固定或跟踪) …等等 根据rate_type的选择,后面的字段将有所不同。例如,如果选择了固定利率类型的抵押,则用户将只输入该固定利率。如果是跟踪抵押贷款,则需要跟踪利率,例如+0.90%和基本利率(正在跟踪),例如0.50%【给出调整后利率=1.40%】 我的问题是:我如何实现正确的表/字段结构。理想情况下,我不希望所有字段(突出显示): 抵押贷款id 客户

我正在创建抵押/贷款数据库-我有一个名为mortgages的表,其中包含以下字段:

  • 抵押贷款id
  • 客户识别码
  • *费率类型*(可以是:固定或跟踪) …等等
根据rate_type的选择,后面的字段将有所不同。例如,如果选择了固定利率类型的抵押,则用户将只输入该固定利率。如果是跟踪抵押贷款,则需要跟踪利率,例如+0.90%和基本利率(正在跟踪),例如0.50%【给出调整后利率=1.40%】

我的问题是:我如何实现正确的表/字段结构。理想情况下,我不希望所有字段(突出显示):

  • 抵押贷款id
  • 客户识别码
  • 费率类型
  • 固定利率
  • 跟踪率
  • 基本利率

因为这可能会导致混乱。有没有办法把这些分开放在其他桌子上?也许另一个包含费率详细信息的表(一个用于固定,另一个用于跟踪)具有一对一关系?

基于您的问题,我建议您可以创建3个表

1对于基本信息,一个用于存储固定费率详细信息的表和一个用于存储基本费率详细信息的表

TBL港口:

抵押id |客户id |费率类型

tblFixedRates:

id |抵押id |固定利率

tblTrackerRates:


id | mortgageID | track|u rate,base|u rate

将所有三列放在同一个表中是有效的,但根据需要仅使用其中的一列或两列。所有三列都可以为空

另一种选择是,对任一类型的费率类型使用两列,但在处理固定费率时,将其中一列设置为0。由于您要添加两个速率来计算总跟踪速率,因此固定速率加0的值将是固定速率

[dbo].[theTable]
   [mortgage_id],
   [client_id],
   [rate_type],
   [base_rate],
   [rate]       // or whatever generic name is appropriate
所以当[rate_type]是您拥有的轨迹时

[base_rate] = 0.50%
[rate] = 0.90%

total = 1.40%
但是当[rate_type]固定时,您就有了

[base_rate] = 0%
[rate] = 0.70%

total = 0.70%

您拥有的是一个E-R模型,其类型(抵押)提供了一组公共属性,每个属性都是0或1子类型的实例,这些子类型提供了额外的子类型特定属性。请参阅我的答案

如何解决这个问题


正如其他人所建议的,我的建议是为FixedRateMortgages和TrackerRateMortgages提供两个子表,其中MortgageID作为主键,也作为外键返回主Mortgages表


这确保了一对一,但不会强制要求抵押只存在于两个子表中的一个子表中。这是一个数据库无法很好地实施的约束,我们这里讨论的不是引用完整性。您可以在子表上使用触发器来确保只插入其他子表中不存在的抵押贷款,但是触发器非常难看。我可能会坚持在应用程序层(即代码)而不是数据库中强制执行该不变量。

使用SQL
外键
约束可以实现的最佳效果是确保每个抵押贷款类型在每个子类型表中最多出现一次,一对零或一关系(如果愿意)。强制此约束的一种方法是在整个架构中使用
{ID,type}
上的两列复合键,并允许在子表约束中测试
类型。下面是使用两个抵押子类型(大括号表示没有隐含顺序的列表)的草图:

您没有指定SQL产品。在标准SQL-92中,可以使用声明为
delferable INITIALLY DEFERRED
CREATE ASSERTION
约束来保持严格的一对一引用完整性,以封装此“分布式”的每个子类型表逻辑。然后,SQL语句可以在事务中延迟
断言
s,修改引用和引用表,然后重新应用
断言
s(或者通过提交事务自动执行)。遗憾的是,现实生活中没有支持
createassertion
的SQL产品。根据供应商的不同,有一些变通方法,例如触发器、从行级
CHECK
约束调用的SQL函数中的表表达式、从表中撤销写入权限,然后强制用户通过CRUD过程更新表以确保引用完整性等


也就是说,在SQL中,一对零或一关系通常是可以接受的,而且这样做确实可能有好处,例如,使数据库约束更易于编写(从而减少错误),不强制用户使用一组过程的灵活性,等等。

是的,我考虑过这一点,但我如何防止同一个mortgageID在FixedRates和TrackerRates中使用?您的DB将强制每个“利率”与有效的“抵押”相关联。你不会强制一个抵押贷款在每个利率表中没有多个条目。您的业务逻辑可以在适当的表中查看。如果两种类型之间有很多不同之处,那么这种结构是有意义的。如果它真的只有3个字段,那么就让所有列都在1个表中,并让另外两个为空。更正:这确保了一对零或一。更正:这是引用完整性,而不是我们大多数使用的SQL产品中的那种,例如,将其称为分布式外键。考虑一个标准的SQL -92 <代码>创建断言<代码>,声明为<代码>可推迟的最初推迟< /COD> >封装这个“分布式”逻辑。
Mortgages { mortgage_ID , mortgage_type } 
   KEY { mortgage_ID } 
   KEY { mortgage_ID , mortgage_type }
   CONSTRAINT mortgage_type = 'Tracker'
              OR mortgage_type = 'Fixed'

FixedRateMortgages { mortgage_ID , mortgage_type , fixed_rate }
   KEY { mortgage_ID , mortgage_type }
   FOREIGN KEY { mortgage_ID , mortgage_type } REFERENCES Mortgages
   CONSTRAINT mortgage_type = 'Fixed';

FixedRateMortgages { mortgage_ID , mortgage_type , base_rate , track_rate }
   KEY { mortgage_ID , mortgage_type }
   FOREIGN KEY { mortgage_ID , mortgage_type } REFERENCES Mortgages
   CONSTRAINT mortgage_type = 'Tracker';

Clients { client_ID } 
   KEY { client_ID } ;

Agreements { mortgage_ID , mortgage_type , client_ID }
   KEY { mortgage_ID , mortgage_type , client_ID }
   FOREIGN KEY { mortgage_ID , mortgage_type } REFERENCES Mortgages
   FOREIGN KEY { client_ID } REFERENCES Client;