我正在设计一个快递数据库。
在一张parcel
表中,我需要一个字段来告诉我有关包裹的当前状态和位置的信息。
如果包裹已到达快递公司的目的地分公司,该字段必须指向有关送货人等的信息。
如果包裹仍在通过快递公司的分支机构,该字段必须指向有关运送包裹的车辆等信息。
我该如何处理这种异质性?
我正在设计一个快递数据库。
在一张parcel
表中,我需要一个字段来告诉我有关包裹的当前状态和位置的信息。
如果包裹已到达快递公司的目的地分公司,该字段必须指向有关送货人等的信息。
如果包裹仍在通过快递公司的分支机构,该字段必须指向有关运送包裹的车辆等信息。
我该如何处理这种异质性?
是否存在无限数量的状态,或者您可以将其分解为离散列表?
如果答案是后者 - 鉴于您问题的“快递公司的分支机构”部分,我认为这是正确的,您可以创建一个查找表交叉引用带有 ID 号的卡车。一个简单的连接 ( http://www.w3schools.com/sql/sql_join.asp ) 应该会返回您正在寻找的信息。
您可以通过从包裹表中引用两个不同的表来做到这一点,一个代表快递分支,另一个代表目的地信息。如果一个不适用于包裹,那么它将为空。如果您不想破坏正常形式,您可以在状态表中获取此信息,然后将其加入这些其他表中,如果没有任何信息冷静下来,您就知道该状态不适用于包裹。
“other_columns”列是可能适用于表的所有其他列的占位符。包裹只有两种处置方式:(t)运输或(d)交付。
create table parcel_dispositions (
parcel_id integer not null,
disposition_timestamp timestamp (0) not null
default current_timestamp,
parcel_disposition char(1) not null
default 't'
check (parcel_disposition in ('t', 'd')),
other_columns char(1) default 'x',
primary key (parcel_id, disposition_timestamp, parcel_disposition)
);
create table parcels_in_transit (
parcel_id integer not null,
disposition_timestamp timestamp not null,
parcel_disposition char(1) not null
default 't'
check (parcel_disposition = 't'),
other_columns char(1) not null default 'x',
primary key (parcel_id, disposition_timestamp, parcel_disposition),
foreign key (parcel_id, disposition_timestamp, parcel_disposition)
references parcel_dispositions (parcel_id, disposition_timestamp, parcel_disposition)
);
create table parcels_delivered (
parcel_id integer not null,
disposition_timestamp timestamp not null,
parcel_disposition char(1) not null
default 'd'
check (parcel_disposition = 'd'),
other_columns char(1) not null default 'x',
primary key (parcel_id, disposition_timestamp, parcel_disposition),
foreign key (parcel_id, disposition_timestamp, parcel_disposition)
references parcel_dispositions (parcel_id, disposition_timestamp, parcel_disposition)
);
insert into parcel_dispositions values
(1, '2013-01-01 09:35', 't', 'x'),
(1, '2013-01-03 17:33', 't', 'y'),
(1, '2013-01-08 08:00', 'd', 'z');
insert into parcels_in_transit values
(1, '2013-01-01 09:35', 't', 'a'),
(1, '2013-01-03 17:33', 't', 'b');
insert into parcels_delivered values
(1, '2013-01-08 08:00', 'd', 'c');
在生产中,您通常会拒绝对基表的访问,并基于此类构建可更新的视图。(运输中的包裹一个视图,交付包裹的另一个视图。)应用程序代码使用视图,而不是基础表。
create view all_parcels_in_transit as
select t1.*
from parcel_dispositions t1
inner join parcels_in_transit t2
on t1.parcel_id = t2.parcel_id
and t1.disposition_timestamp = t2.disposition_timestamp
and t1.parcel_disposition = t2.parcel_disposition;
SQL dbms 还没有强制执行某些合理的约束。例如,在交付后,数据库不应再接受给定包裹的任何处置,但 SQL dbms 还不能强制执行。(不能以声明方式强制执行。不过,您可以使用触发器强制执行。)