是否保证空字段表示数据库设计不好



我正在开发一个批处理应用程序,该应用程序允许用户提交有关特定车辆的信息请求。用户可以使用VIN或车牌/州组合提交申请。我提出了以下表格结构:


待处理的车辆

vehicle_id(fk)|user_id(fk)|status|start_time

车辆

vehicle_id|VIN|plate|state


我的同事认为这是一个糟糕的设计,因为Vehicles中的每个记录要么有一个空VIN字段,要么有空车牌和状态字段。相反,他们提出了以下建议:
待处理的车辆

vehicle_id(fk)|user_id(fk)|status|start_time

车辆

vehicle_id(pk)|field|value

Vehicles中的条目将由一行vin组成:

1|"vin"|"123

或两行用于一个板/状态:

2|"plate"|"abc 123" 2|"state"|"NY"


我认为第一个解决方案会更容易查询,不会有任何明显的缺点。应该优先选择哪种设计?保证的空字段真的是糟糕设计的指标吗?

您的同事提出的是数据库设计中的终极反模式。

谷歌搜索Bill Karwin的"反模式"书籍和"EAV"。

询问您的同事,他建议如何强制"plate"one_answers"state"值始终成对出现在他的数据库中。如果他指向应用程序代码,请询问他建议如何强制数据库只通过他的应用程序进行更新。

你的解决方案比他的好一千倍。更"好"的是(从避免所有null的关系纯粹性的角度来看)为每种类型的请求提供自己的表:

车辆查询(按VIN )

user_id(fk)|状态|开始时间| VIN

车辆查询(按车牌)

user_id(fk)| status | start_time | plate | state

如果要对每个查询的状态进行历史跟踪,则必须在其自己的表中单独列出这些状态。

总之:不。这是一个错位优化的例子。由于存储字符串,他的模式实际上平均会占用更多的空间;当然,更复杂的代码和查询的性能会更差。

将其视为识别车辆的多种方法。您的车辆具有一个或多个身份。当地警方可能会使用LPN识别您的车辆,而停车管理局可能会使用许可证徽章或主动/被动转发器,此外,dmv可能依赖于vrn编号。

如果你真的想建立一种灵活的方式将车辆绑定到多个身份,我会使用身份类型表,这样车辆就可以有一个或多个身份。

车辆识别
车辆识别PK
车辆ID FK
标识值
IdentityType(类型)
StateID??

车辆
VehicleID PK

我更新了答案,删除了一个我认为没有用的表:)

空值是可以的。它们对于单表继承特别有用,并且如果您的系统需要"Draft"实体。

如果您使用像Postgres这样的高质量数据库,则不会对null进行存储惩罚。

无论如何,如果问题是"我们需要A或B,而A和B非常相似",那么答案几乎总是表继承。如果要快速移动,请使用"单表继承"。如果NULL让您感到难过,那么请使用类表继承。

--STI:
create table vehicle_identifiers (
  id int primary key,
  type text not null check (type in ( 'VIN', 'STATE_N_PLATE' ) )
  vin null,
  state char(2) null,
  plate text null,
  check ( ( type='VIN' and vin is not null ) or ( type='STATE_N_PLATE' and state is not null and plate is not null ) )
);
--CTI:
create table vehicle_identifiers (
  id int primary key
);
create table vehicle_identifiers_vin (
  id int primary key references vehicle_identifiers(id),
  vin text not null
);
create table vehicle_identifiers_state_n_plate (
  id int primary key references vehicle_identifiers(id),
  state text not null,
  plate text not null
);

最新更新