0

我正在设计一个快递数据库。

在一张parcel表中,我需要一个字段来告诉我有关包裹的当前状态和位置的信息。

如果包裹已到达快递公司的目的地分公司,该字段必须指向有关送货人等的信息。

如果包裹仍在通过快递公司的分支机构,该字段必须指向有关运送包裹的车辆等信息。

我该如何处理这种异质性?

4

3 回答 3

1

是否存在无限数量的状态,或者您可以将其分解为离散列表?

如果答案是后者 - 鉴于您问题的“快递公司的分支机构”部分,我认为这是正确的,您可以创建一个查找表交叉引用带有 ID 号的卡车。一个简单的连接 ( http://www.w3schools.com/sql/sql_join.asp ) 应该会返回您正在寻找的信息。

于 2013-08-04T16:10:39.783 回答
0

您可以通过从包裹表中引用两个不同的表来做到这一点,一个代表快递分支,另一个代表目的地信息。如果一个不适用于包裹,那么它将为空。如果您不想破坏正常形式,您可以在状态表中获取此信息,然后将其加入这些其他表中,如果没有任何信息冷静下来,您就知道该状态不适用于包裹。

于 2013-08-04T17:35:11.703 回答
0

“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 还不能强制执行。(不能以声明方式强制执行。不过,您可以使用触发器强制执行。)

于 2013-08-04T20:52:13.583 回答