Database 保证为空字段是否表示数据库设计不佳?
我正在开发一个批处理应用程序,允许用户提交有关特定车辆信息的请求。用户可以使用VIN或车牌/州组合提交请求。我提出了以下表格结构:Database 保证为空字段是否表示数据库设计不佳?,database,relational-database,database-schema,Database,Relational Database,Database Schema,我正在开发一个批处理应用程序,允许用户提交有关特定车辆信息的请求。用户可以使用VIN或车牌/州组合提交请求。我提出了以下表格结构: 已处理的车辆底座 车辆id(fk)|用户id(fk)|状态|启动时间 车辆 车辆id | VIN |车牌|状态 我的同事认为这是一个糟糕的设计,因为车辆中的每条记录要么有一个空VIN字段,要么有空车牌和状态字段。相反,他们提出了以下建议: 已处理的车辆底座 车辆id(fk)|用户id(fk)|状态|启动时间 车辆 车辆识别码(pk)|字段|值 如果车辆中的条目
已处理的车辆底座
车辆id(fk)|用户id(fk)|状态|启动时间
车辆
车辆id | VIN |车牌|状态
我的同事认为这是一个糟糕的设计,因为车辆中的每条记录要么有一个空VIN字段,要么有空车牌和状态字段。相反,他们提出了以下建议:
已处理的车辆底座
车辆id(fk)|用户id(fk)|状态|启动时间
车辆
车辆识别码(pk)|字段|值
如果车辆中的条目包含一行vin:
1 |“vin”|“123
或一个板/状态的两行:
2 |“plate”|“abc 123”
2 |“州”|“纽约”
我认为第一种解决方案会更容易查询,而不会有任何明显的缺点。应该首选哪种设计?保证空字段真的是糟糕设计的指标吗?一句话:不。这是一种错位优化的情况。由于存储strin,他的模式实际上平均会占用更多空间当然,更复杂的代码和查询会有更差的性能。将其视为识别车辆的多种方法。您的车辆有一个或多个标识。当地警察可能使用LPN识别您的车辆,而停车管理局可能使用许可证徽章或主动/被动转发器,此外,dmv可能依赖关于vrn号码 如果你真的想建立一种灵活的方式将一辆车绑定到多个身份,我会使用一个身份类型表,这样一辆车就可以有一个或多个身份 车辆身份
车辆识别PK
车辆ID FK
识别值
标识类型(类型)
StateID 车辆
车辆ID PK
我更新了答案,删除了一个我认为没有用的表:)你的同事提出的是关于数据库设计中的最终反模式 谷歌搜索比尔·卡温的《反模式》一书和《EAV》 询问您的同事,他建议如何强制数据库中始终成对出现“plate”和“state”值。如果他指向应用程序代码,询问他建议如何强制数据库只能通过他的应用程序更新 您的解决方案比他的好上千倍。但“更好”(从关系纯度的角度来看,它包括避免所有空值)是为每种类型的请求提供自己的表: 车辆查询拜文 用户id(fk)|状态|开始|时间| VIN 汽车牌照 用户id(fk)|状态|开始|时间|车牌|状态
如果要在一段时间内为每个查询保留状态的历史跟踪,则必须在其自己的表中挑出这些内容。空值很好。它们对于单表继承以及系统需要“草稿”实体特别有用 如果您使用像Postgres这样的高质量数据库,那么空值不会导致存储损失 不管怎么说,如果问题是“我们需要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
);
我不确定一个车牌/状态应该如何使用两行。如果
vehicle\u id(pk)
是一个主键,那么你不能有两行相同的车牌号。而且,据我所知,每辆车都必须有VIN(可能是未知的),但没有车牌号。此外,车牌号会随着时间的推移而变化(可能会变化)。