SQL 一对一关系和结果架构

发布于 2024-12-13 11:57:12 字数 600 浏览 1 评论 0原文

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

  • mortgage_id
  • client_id
  • *rate_type* (可能是:fixed 或 tracker) ...等

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

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

  • mortgage_id
  • client_id
  • rates_type
  • fixed_rate
  • track_rate
  • base_rate

因为它可能会导致混乱。有什么办法可以将它们分开到其他表中吗?也许另一个表的rate_details(一个用于固定,另一个用于跟踪)具有一对一的关系?

I am creating a mortgage/loans database - I have a table called mortgages with the fields:

  • mortgage_id
  • client_id
  • *rate_type* (which may be: fixed or tracker)
    ...etc

Depending on the choice for rate_type - the fields that follow will be different. For instance, if a mortgage with a fixed rate_type is selected, then the user will only enter that fixed rate. If it is a tracker mortgage, then a track rate e.g. +0.90% and a base rate(which is being tracked) e.g. 0.50% is needed[giving adjusted rate = 1.40%].

My question is: how can I go about implementing the correct table/field structure for this. Ideally I don't want to have all the the fields (highlighted):

  • mortgage_id
  • client_id
  • rate_type
  • fixed_rate
  • track_rate
  • base_rate

Because it could lead to confusion. Is there any way to separate these into other tables? Perhaps another table with the rate_details (one for fixed and another for tracker) with a one-to-one relationship?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

不弃不离 2024-12-20 11:57:12

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

1 用于基本信息,一个用于存储固定费率详细信息的表,以及一个用于存储有关基本费率详细信息的表。

tblMortgages:

MortgageID |客户 ID |费率类型

tblFixedRates:

id |抵押贷款ID |固定速率

tblTrackerRates:

id |抵押贷款ID |跟踪率、基本率

based on your question, i'd suggest that you can create 3 tables.

1 for the Basic information, a table for storing details on fixed rates, and a table for storing details about base rates.

tblMortgages:

MortgageID | client id | rate type

tblFixedRates:

id | mortgageID | fixed_rate

tblTrackerRates:

id | mortgageID | track_rate, base_rate

蓝眼睛不忧郁 2024-12-20 11:57:12

您拥有的是一个具有类型(抵押)的 ER 模型,该模型提供一组通用属性,每个属性都是 0 或 1 个子类型的实例,这些子类型提供其他特定于子类型的属性。请参阅我的答案

派生概念 - 数据库设计注意事项

我应该吗设计一个 SQL Server 数据库以依赖 UNION 还是避免它?

了解如何解决这个问题。

类型/子类型模型

What you have is an E-R model with a type (a mortgage) that provides a common set of attributes, each of which is an instance of 0 or 1 subtypes, that provide additional subtype-specific attributes. See my answers at

Derived concepts - database design considerations

and

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

for how to solve this.

type/subtype model

昇り龍 2024-12-20 11:57:12

将所有三列放在同一个表中是有效的,但根据需要仅使用其中的 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%

It is valid to have all three columns in the same table but only use 1 or 2 of them as needed. All three columns can be NULLABLE.

Another alternative is use 2 columns for either type of rate type but set the one of the columns to 0 when dealing with fixed rates. Since you are adding two rates to come up with the total tracking rate then the value for the fixed rate plus 0 would be the fixed rate.

[dbo].[theTable]
   [mortgage_id],
   [client_id],
   [rate_type],
   [base_rate],
   [rate]       // or whatever generic name is appropriate

So when the [rate_type] is track you have

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

total = 1.40%

but when the [rate_type] is fixed you have

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

total = 0.70%
榆西 2024-12-20 11:57:12

正如其他人所建议的那样,我的建议是固定利率抵押贷款和跟踪利率抵押贷款有 2 个子表,它们将 MortgageID 作为主键,并作为回到主抵押贷款表的外键。

这确保了一对一的关系,但不会强制抵押贷款只能存在于两个子表之一中。这是数据库不能很好执行的约束,我们在这里讨论的不是参照完整性。您可以在子表上使用触发器来确保只插入其他子表中不存在的抵押贷款,但恕我直言,触发器非常丑陋。我可能会坚持在应用程序层(即代码)而不是数据库中强制执行该不变式。

As others suggested, my advice is 2 sub-tables for FixedRateMortgages and TrackerRateMortgages that have the MortgageID as the Primary Key and also as a Foreign Key back to the main Mortgages table.

This ensures a one-to-one, but it will not enforce that a mortgage should only exist in one of the two sub-tables. This is a constraint that databases don't enforce well, it is not referential integrity we're talking about here. You could use triggers on the sub-tables to ensure that only mortgages that don't exist in the other sub-table are being inserted, but triggers are pretty ugly IMHO. I would probably stick to enforcing that invariant in your application layer (i.e. code) and not the database.

夜访吸血鬼 2024-12-20 11:57:12

使用 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 产品。在标准 SQL-92 中,可以使用声明为 DEFERRABLE INITIALLY DEFERRED 的 CREATE ASSERTION 约束来维护严格的一对一引用完整性,以封装这种“分布式”每个子类型表逻辑。然后,SQL 语句可以在事务中推迟 ASSERTION,修改引用和引用表,然后重新应用 ASSERTION(或通过提交事务自动执行此操作)。遗憾的是,现实生活中没有 SQL 产品支持 CREATE ASSERTION。根据供应商的不同,有一些解决方法,例如触发器、从行级 CHECK 约束调用的 SQL 函数中的表表达式、撤销表的写入权限,然后强制用户通过 CRUD 过程更新表,以确保也就是说

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

The best you can achieve using SQL FOREIGN KEY constraints is to ensure that each mortgage type appears at most once in each subtype table, a one-to-zero-or-one relationship, if you will. One way to enforce this constraint is to use a two-column composite key on { ID , type } to be used throughout the schema and allowing the type to be tested in subtable constraints. Here's a rough sketch using two mortgage subtypes (curly braces indicate a list with no implied order):

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;

You did not specify a SQL product. Strict one-to-one referential integrity may be maintained in Standard SQL-92 using CREATE ASSERTION constraints declared as DEFERRABLE INITIALLY DEFERRED to encapsulate this 'distributed' one per subtype table logic. A SQL statment could then, in a tranasction, defer the ASSERTIONs, modify referenced and referencing tables then reapply the ASSERTIONs (or do this automatically by committing the transaction). Sadly, there are no real life SQL products that support CREATE ASSERTION. There are workarounds depending on vendor e.g. triggers, a table expression in a SQL function called from a row-level CHECK constraint, revoking write privileges from the tables then forcing users to update the tables via CRUD procedures that ensure referential integrity, etc.

That said, it is usually acceptable in SQL to have one-to-zero-or-one relationships and indeed there may be advantages to doing so e.g. to make database constraints easier to write (and therefore fewer bugs), flexibility of not forcing users to use one set of procedures, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文