数据库模型规范化 - 数据完整性

Database Model Normalization - Data Integrity

这是我的问题,我有 2 个基本实体。

1-订单和 2-交付类型(基本上是查找 table 1-电子邮件,2-下载,3-USPS 邮件)

假设客户下订单并选择交付类型 3-USPS 邮件。

我的订单 table 存储 id 3 以加入交付类型。基本的东西。

但是当管理员错误地将递送类型从 UPS 邮件更新为 Fedex 邮件时会发生什么。

订单将反映错误的交货类型。 我的问题是,我们是否应该阻止人们在下订单后更新交付类型,或者我的订单应该被非规范化并在那时存储文档类型的快照,这方面的最佳做法是什么?

我看到大多数时候,例如在订单产品场景中,更新产品名称没什么大不了的,但是当新值影响订单时要执行什么程序?

谢谢!

这将完全取决于您在那里实现自动化的业务流程。如果他们不能做,并且没有商业理由去做,那么就应该阻止他们做。如果他们需要这样做,那么系统需要能够处理它。这是您需要从一开始就建模的东西,以防止陷入无法摆脱的困境。

所以,除此之外,没有确定的答案。您的数据需要与订单当前发生的情况相匹配,这是肯定的。

but what happens when an admin by mistake updates the delivery type from UPS mail to Fedex Mail.

不要让这种情况发生。权限是数据库设计的一部分,下面使用 PostgreSQL 进行说明。原则适用于所有 client/server SQL dbms.

create table delivery_types (
  delivery_type_num integer not null primary key,
  delivery_type_name varchar(15) not null unique
);

insert into delivery_types values
(1, 'Email'), (2, 'Download'), (3, 'USPS Mail');

create table orders (
  order_num integer primary key,
  other_columns char(1) not null default 'x',
  delivery_type_num integer not null references delivery_types
    on delete no action on update no action
);

revoke insert, update, delete, truncate on delivery_types from public;
grant select on delivery_types to public;

通过撤销角色 "public" 的权限,只有所有者和数据库超级用户可以更新 table。 "orders" 中的外键引用将阻止所有者和数据库超级用户删除行或更新被其他 table 引用的行的 id numbers

一种略有不同的方法使用自然键。这不是反规范化。 table 和 "delivery_types" 都在 6NF 中。

create table delivery_types (
  delivery_type varchar(15) primary key
);

insert into delivery_types values
('Email'), ('Download'), ('USPS Mail');

create table orders (
  order_num integer primary key,
  other_columns char(1) not null default 'x',
  delivery_type varchar(15) not null references delivery_types
    on delete no action on update no action
);

revoke insert, update, delete, truncate on delivery_types from public;
grant select on delivery_types to public;

insert into orders values 
(1, 'x', 'Email'), (2, 'x', 'Download'), (3, 'x', 'USPS Mail');

权限与以前一样——角色 "public" 的成员可以从 delivery_types select,但他们不能更改内容。但是现在即使是数据库超级用户 也不能删除或更新delivery_types 中的行。外键引用阻止了它。