SQL 一对一关系和结果架构
我正在创建一个抵押/贷款数据库 - 我有一个名为抵押的表,其字段为:
- 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
根据你的问题,我建议你可以创建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
您拥有的是一个具有类型(抵押)的 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.
将所有三列放在同一个表中是有效的,但根据需要仅使用其中的 1 或 2 列。所有三列都可以为 NULLABLE。
另一种替代方法是对任一类型的费率类型使用 2 列,但在处理固定费率时将其中一列设置为 0。由于您要添加两个费率来得出总跟踪费率,因此固定费率加上 0 的值就是固定费率。
因此,当 [rate_type] 被跟踪时,你会得到
,但当 [rate_type] 被固定时,你会得到
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.
So when the [rate_type] is track you have
but when the [rate_type] is fixed you have
正如其他人所建议的那样,我的建议是固定利率抵押贷款和跟踪利率抵押贷款有 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.
使用 SQL
FOREIGN KEY
约束可以实现的最佳效果是确保每个抵押类型在每个子类型表中至多出现一次,即一对零或一关系,如果你愿意的话。强制实施此约束的一种方法是在{ ID , type }
上使用两列复合键,以便在整个架构中使用,并允许在子表中测试type
限制。下面是使用两种抵押子类型的粗略草图(大括号表示没有隐含顺序的列表):您没有指定 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 thetype
to be tested in subtable constraints. Here's a rough sketch using two mortgage subtypes (curly braces indicate a list with no implied order):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 asDEFERRABLE INITIALLY DEFERRED
to encapsulate this 'distributed' one per subtype table logic. A SQL statment could then, in a tranasction, defer theASSERTION
s, modify referenced and referencing tables then reapply theASSERTION
s (or do this automatically by committing the transaction). Sadly, there are no real life SQL products that supportCREATE ASSERTION
. There are workarounds depending on vendor e.g. triggers, a table expression in a SQL function called from a row-levelCHECK
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.