是否可以通过规范化跨多个表且不使用空列来实现唯一外键?

Is unique foreign keys across multiple tables via normalization and without null columns possible?

这是一个关系数据库设计问题,不特定于任何 RDBMS。一个简化的案例:

我有两辆 table 汽车和卡车。他们都有一列,比如 RegistrationNumber,它在两个 table 中必须是唯一的。 这可能会通过一些 insert/update 触发器来强制执行,但如果可能的话,我正在寻找更 "clean" 的解决方案。

实现此目的的一种方法是添加第三个 table,Vehicles,它包含 RegistrationNumber 列,然后向 Vehicles 添加另外两个列 CarID 和 TruckID。但是对于 Vehicles 中的每一行,CarID 或 TruckID 列之一将始终为 NULL,因为 RegistrationNumber 适用于 Car 或 Truck,而另一列则为 NULL 值。

是否可以在多个 table 之间强制执行唯一的 RegistrationNumber 值,而不引入 NULL 列或依赖触发器?

您可以添加第三个 table 包含单列 RegistratioNumber 的车辆,您对其应用唯一约束,然后在现有 tables - 汽车和卡车 - 使用 RegistrationNumber 作为外部Vehicles table 上的键。这样就不需要额外的id,避免了null问题,保证了注册号的唯一性。

更新 - 此解决方案不会阻止汽车和卡车共享相同的注册号。要强制执行此约束,您需要在普通 SQL 之外添加触发器或逻辑。否则你可能想看看 Gordon 的涉及复合外键的解决方案。

这有点复杂。拥有第三个 table、Vehicles 绝对是解决方案的一部分。第二部分是保证车辆要么是汽车要么是卡车,但不能两者都是。

一种方法是"list-all-the-possibilities"方法。这就是你用两列提出的建议。此外,这应该有一个约束来验证只有一个id被填充。类似的方法是让CarIdTruckId实际上是VehicleId。这减少了浮动的不同 ID 的数量。

另一种方法使用组合键。思路是:

create table Vehicles (
    Vehicle int primary key,
    Registration varchar(255),
    Type varchar(255),
    constraint chk_type check (type in ('car', 'truck')),
    constraint unq_type_Vehicle unique (type, vehicle), -- this is redundant, but necessary
    . . .
);

create table car (
    VehicleId int,
    Type varchar(255), -- always 'car' in this table
    constraint fk_car_vehicle foreign key (VehicleId) references Vehicles(VehicleId),
    constraint fk_car_vehicle_type foreign key (Type, VehicleId) references Vehicles(Type, VehicleId)
);

查看以下标签:

您已经在问题中概述了 class table 继承。该标签只会添加一些详细信息,并向您展示一些其他问题,这些问题的答案可能会有所帮助。

共享主键是一种强制执行 IS-A 关系(例如车辆和卡车之间的关系)的一对一性质的简便方法。它还允许其他 table 中的外键引用车辆以及卡车或汽车,视情况而定。