SQL一对一关系和结果模式

时间:2011-11-02 20:41:39

标签: sql schema field table-relationships

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

  • mortgage_id
  • 的client_id
  • * rate_type *(可能是:固定或跟踪) ...等

根据rate_type的选择 - 后面的字段会有所不同。例如,如果选择具有固定rate_type的抵押,则用户将仅输入该固定利率。如果是跟踪器抵押,那么跟踪率例如+ 0.90%和基本速率(正在跟踪),例如需要0.50%[给出调整后的比率= 1.40%]。

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

  • mortgage_id
  • 的client_id
  • RATE_TYPE
  • fixed_rate
  • track_rate
  • base_rate

因为它可能导致混乱。有没有办法将这些分成其他表格?也许另一个带有rate_details的表(一个用于固定,另一个用于跟踪器)与一对一的关系?

5 个答案:

答案 0 :(得分:1)

根据你的问题,我建议你可以创建3个表。

1表示基本信息,表格用于存储固定费率的详细信息,表格用于存储基本费率的详细信息。

tblMortgages:

MortgageID |客户端ID |费率类型

tblFixedRates:

id | mortgageID | fixed_rate

tblTrackerRates:

id | mortgageID | track_rate,base_rate

答案 1 :(得分:0)

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

另一种替代方法是对任一类型的费率类型使用2列,但在处理固定费率时将其中一列设置为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%

答案 2 :(得分:0)

你所拥有的是具有类型(抵押)的ER模型,它提供了一组共同​​的属性,每个属性都是0或1个子类型的实例,提供额外的子类型特定属性。

见我的答案

Derived concepts - database design considerations

Should I Design a SQL Server database to rely on UNION or avoid it?

如何解决这个问题。

type/subtype model

答案 3 :(得分:0)

正如其他人所建议的那样,我的建议是2个子表,用于FixedRateMortgages和TrackerRateMortgages,它们将MortgageID作为主键,并作为外键返回主Mortgages表。

这确保了一对一,但不会强制抵押只应存在于两个子表中的一个中。这是数据库不能很好地执行的约束,我们在这里谈论的不是引用完整性。你可以在子表上使用触发器来确保只插入不存在于另一个子表中的抵押,但触发器是相当丑陋的恕我直言。我可能会坚持在您的应用程序层(即代码)而不是数据库中强制执行该不变量。

答案 4 :(得分:0)

使用SQL FOREIGN KEY约束可以达到的最佳效果是确保每个抵押类型在每个子类型表中最多出现一次,一对一或零关系如果你愿意的话。实施此约束的一种方法是在{ ID , type }上使用两列组合键在整个模式中使用,并允许在子表约束中测试type。这是使用两个抵押子类型的粗略草图(花括号表示没有隐含顺序的列表):

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;

您没有指定SQL产品。可以使用声明为CREATE ASSERTION的{​​{1}}约束在标准SQL-92中维护严格的一对一参照完整性,以便为每个子类型表逻辑封装这个“分布式”一个。然后,SQL语句可以在跟踪中推迟DEFERRABLE INITIALLY DEFERRED,修改引用和引用表,然后重新应用ASSERTION(或通过提交事务自动执行此操作)。遗憾的是,没有支持ASSERTION的真实SQL产品。有些解决方法取决于供应商,例如触发器,从行级CREATE ASSERTION约束调用的SQL函数中的表表达式,从表中撤消写权限,然后强制用户通过确保引用完整性的CRUD过程更新表等。

也就是说,在SQL中通常可以接受一对一或一对一的关系,实际上这样做可能是有利的,例如使数据库约束更容易编写(因此更少的错误),不强迫用户使用一组程序的灵活性等。