我正在将发票组件构建到我的Web应用程序中。 在“我的模式”中,某些客户可能希望开具发票。
Projects -> Sites -> Jobs -> Phases -> Teams
每个都是数据库中的表,并且与其父表有关系。
我计划建立一个 Items 表,该表将保存有关我们将如何为每个级别的工作开具发票的通用信息,即名称,默认价格,计量单位等。
然后,用户将创建一个开发票模型,他们可以将项目的列表与之关联,以便可以重复使用。
这是我的问题发挥作用的地方。当需要发票时,我需要将发票模型与上述级别之一相关联。我不想为每个级别的发票模型创建链接表。我想以某种方式保持表之间的关系完整性。而且,如果将来有其他事情我可以反对,我不想为了适应这种新的“可计费级别”而进行巨大的数据库更改和/或代码更改。
有没有一种方法可以保持关系完整性,而无需创建将发票模型链接到级别的新表?
答案 0 :(得分:1)
可以实现多态关系,从而解决附加“ n”个不同实体类型的问题。
据我所知,多态关系的不利之处是在不丢失参照完整性的情况下是不可能实现的。
对此https://hashrocket.com/blog/posts/modeling-polymorphic-associations-in-a-relational-database的一个很好的阅读。流行且最简单的实现之一是多态联接,该引自以下文章:
多形联接
将ACL连接到资源的一种简单方法是使用两个 ACL表上的列:resource_type和resource_id。这种方法 由Ruby on Rails普及。 acl表可以定义为 如下:
create table acl(
id serial primary key,
resource_type varchar not null,
resource_id integer not null,
-- other fields omitted
unique(resource_id, resource_type)
);
用于检索文档ID:42的ACL的查询就像 以下:
select *
from acl
where resource_type='document'
and resource_id=42;
这种方法的一个严重问题是数据库非常有限 由于缺少外键,它可以强制执行数据完整性 约束。它可以确保资源的acl不超过一个,但是 就这些。资源可能缺少ACL,ACL可能指向 缺少资源。
Exclusive Belongs To方法是增加引用完整性的一种好方法,但是对于每种可能的实体类型都需要一个新列。引用文章:
排他性属于(又名“排他性弧线”)(AKA Exclusive Arc)。在此模型中,acl具有指向它可以属于的所有表的外键。
create table acl(
id serial primary key,
document_id integer references document,
image_id integer references image,
file_id integer references file,
report_id integer references report,
-- other fields omitted
check(
(
(document_id is not null)::integer +
(image_id is not null)::integer +
(file_id is not null)::integer +
(report_id is not null)::integer
) = 1
)
);
create unique index on acl (document_id) where document_id is not null;
create unique index on acl (image_id) where image_id is not null;
create unique index on acl (file_id) where file_id is not null;
create unique index on acl (report_id) where report_id is not null;
记录检查约束。这确保acl属于 恰好是任何一种资源。使用此设计,acl不能 孤立,但无法强制资源具有ACL。 部分唯一索引也很重要。限制独特 仅索引为非空值的索引可显着节省空间以及 减少对插入的写操作。
答案 1 :(得分:0)
为清楚地回答您的问题,您必须保持至少两个表的关系才能保持关系的完整性,一个表用于存储模型和物料之间的关系ID,另一个表用于存储要创建的物料的所有数据,在这种情况下,您将只剩下另外两个表,但是现在可以解决将来的痛苦。