php - 我应该如何建立表之间的关系?

标签 php mysql invoice relational integrity

我正在我的 Web 应用程序中构建一个发票组件。 在“我的架构”中,我们设置了某些客户可能想要开具发票的级别。

Projects -> Sites -> Jobs -> Phases -> Teams

其中每一个都是数据库中的表,并且与其父表有关系。

我计划构建一个项目表,该表将保存有关我们如何为每个级别所完成的工作开具发票的通用信息,即名称、默认价格、计量单位等.

然后,用户将创建一个发票模型,他们可以将项目列表与该模型相关联,以便这些项目可以重复使用。

这就是我的问题发挥作用的地方。当需要开具发票时,我需要将发票模型与上述级别之一相关联。我不想为每个级别创建一个与发票模型的链接表。我想以某种方式保持表之间的关系完整性。而且,如果将来我可以对其他东西进行计费,我不想进行巨大的数据库更改和/或代码更改来考虑这个新的“可计费级别”。

有没有办法让我保持关系完整性,而无需创建新表将发票模型链接到级别?

最佳答案

可以实现多态关系,解决附加“n”个不同实体类型的问题。

据我所知,多态关系的缺点是,在不损失引用完整性的情况下实现它是不可能的。

对此的一个很好的阅读是 https://hashrocket.com/blog/posts/modeling-polymorphic-associations-in-a-relational-database 。流行且最简单的实现之一是多态连接,引用自下面的文章:

Polymorphic Joins

A simple approach to connect an acl to a resource is to use two columns on the acl table: resource_type and resource_id. This approach was popularized by Ruby on Rails. The acl table could be defined as follows:

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)
);

The query for retrieving an acl for document id:42 would be like the following:

select *
from acl
where resource_type='document'
  and resource_id=42;

A serious problem with this approach is the database is very limited in the data integrity it can enforce due to the lack of foreign key constraints. It can ensure a resource has no more that one acl, but that is all. A resource can be missing an acl and an acl can point to a missing resource.

<小时/>

Exclusive Belongs To 方法是提高引用完整性的好方法,但需要为每个可能的实体类型创建一个新列。引自文章:

Exclusive Belongs To (AKA Exclusive Arc) In this model, the acl has foreign keys to all tables to which it can belong.

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;

Take note of the check constraint. This ensures that an acl belongs to exactly one resource of any type. With this design an acl cannot be orphaned, but there is no way to enforce that a resource has an acl. Also important are the partial unique indexes. Limiting the unique indexes to only not null values dramatically saves space as well as reducing write operations on insert.

关于php - 我应该如何建立表之间的关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51388194/

相关文章:

php - 通过 magento 安装为我的子域安装的通配符 ssl 无法正常工作

php - 获取 ID 连接到逗号分隔列表的所有匹配记录

MySQL > 表不存在。但它确实(或应该)

mysql - MySQL 中发票前缀的最佳实践?

Javascript - 将计算值输入发票的文本区域

php - html5 下载和 php 下载不适用于移动设备

PHP 验证 HTTP 消息

php - MySql 5.7 : General error: 1366 Incorrect integer value: '' for TinyInt(1) field

php - mySQL 查询不适用于 PHP,但适用于 PHPMyAdmin

stripe-payments - 结账成功后如何生成 strip 发票