SQL 只允许其他列匹配的外键

问题描述

我有两张桌子,

CREATE TABLE ActivityCodes (
    ActivityCodeID INT NOT NULL PRIMARY KEY,LocationID INT NOT NULL
);

CREATE TABLE LocationSettings (
    LocationID INT NOT NULL PRIMARY KEY,DefaultFooActivityCodeID INT,FOREIGN KEY (DefaultFooActivityCodeID) REFERENCES ActivityCodes(ActivityCodeID)
);

与所示的外键关系。活动代码仅对给定的 LocationID 有效,DefaultFooActivityCodeID 表中的 LocationSettings 应为 ActivityCodeID,其中 ActivityCodes.LocationID == LocationSettings.LocationID。如何在 sql 中强制执行?可以用约束或外键来完成吗?有可能吗?


编辑:只是添加一些说明,这些表中的有效数据应该是这样的:

ActivityCodes

ActivityCodeID 位置 ID
1 123
2 123
3 456
4 456

LocationSettings

位置 ID DefaultFooActivityCodeID
123 1
456 4

一个地点可以有多个活动代码。位置的认活动代码必须是该位置的活动代码。 @Charlieface 我尝试使用 answer you linked 中建议的复合外键,但是我收到一个错误,说 LocationID 上的 ActivityCodes 既不是唯一键也不是主键(我使用的是 MS sql Server ).

解决方法

您提供的 DDL 并不代表您所描述的内容。 DDL 描述了这一点: ActivityCodes 独立于 LocationSettingsLocationSettings 而是依赖于 ActivityCodes(一个 ActivityCodes 有多个 LocationSettings

外键的定义很好,比如 FOREIGN KEY (DefaultFooActivityCodeID) REFERENCES ActivityCodes(ActivityCodeID)。如果您在没有先插入 ActivityCode 的情况下尝试插入 LocationSettings,则会因违反约束而失败。

,

外键引用不必是主键。这允许您对同一个表有两个外键引用,即使它们是多余的:

CREATE TABLE ActivityCodes (
    ActivityCodeID INT NOT NULL PRIMARY KEY,LocationID INT NOT NULL,UNIQUE (LocationID,ActivityCodeID)
);

CREATE TABLE LocationSettings (
    LocationID INT NOT NULL PRIMARY KEY,DefaultFooActivityCodeID INT,FOREIGN KEY (DefaultFooActivityCodeID) REFERENCES ActivityCodes(ActivityCodeID),FOREIGN KEY (LocationID,DefaultFooActivityCodeID) REFERENCES ActivityCodes(LocationID,ActivityCodeID)
);

虽然这表达了你想要的,但你会发现这在实践中维护起来有点棘手。设置默认值需要以下步骤:

  1. 插入具有 NULL 默认值的位置。
  2. 使用默认活动在 ActivityCodes 中插入一行。
  3. 更新 LocationSettings 中的默认值。