外键 table 中其他列的唯一性约束

Uniqueness constraint on other columns in table of foreign key

我有一些 Things 有 0-* 任意数量的 languages:

CREATE TABLE Things(
    thing_id INT PRIMARY_KEY,
    thing_proprty INT);

CREATE TABLE ThingNames(
    thing_name_id INT PRIMARY_KEY,
    thing_id INT,
    language CHAR[2],
    name VARCHAR[64] UNIQUE,
    FOREIGN KEY (thing_id) REFERENCES Things(thing_id));

这些东西与许多 Fields 相关,并且在每个字段中,每种语言有 0-1 个 CanonicalNames。直接的方法是

CREATE TABLE Fields(
    field_id INT PRIMARY_KEY,
    name VARCHAR[64])

CREATE TABLE CanonicalNames(
    thing_id INT
    field_id INT
    canonical_name_id INT
    FOREIGN KEY (thing_id) REFERENCES Things(thing_id),
    FOREIGN KEY (field_id) REFERENCES Fields(field_id),
    FOREIGN KEY (canonical_name_id) REFERENCES ThingNames(thing_name_id));

但这错过了 0-1 约束,这将是 field_id 以及 thing_id[ 的唯一性约束=28=] 和 language 列,由 canonical_name_id 引用。将所有列作为外键包含在 CanonicalNames 中当然是多余的并且容易出错,那么有没有办法跨表施加唯一性约束?还是这里有我没有看到的更好的解决方案?

我不确定您设计中的一些内容。将 ThingNames.name 声明为键意味着同一事物不能在两种不同的语言中具有相同的名称,但这似乎可能发生在相关语言(例如挪威语和丹麦语)中,或者当技术术语未翻译时。

而且相关性的概念并未在您的架构中明确表示。只有至少有一个规范名称(对于某种语言)的事物才与字段相关吗?

但是,根据一些假设,我建议使用此模型(基于 Dataphor 的伪代码,省略数据类型):

create table Thing {
  ThingId,
  ThingProperty,
  key { ThingID }
};

create table Field {
  FieldId,
  FieldName,
  key { FieldId },
  key { FieldName } // Assumption - or can several Fields have the same name?
};

create table Relevance { // Standard many-to-many association table
  ThingId,
  FieldId,
  key { ThingId, FieldId },
  reference Relevance_Thing { ThingId } references Thing { ThingId },
  reference Relevance_Field { FieldId } references Field { FieldId }
};

create table ThingName {
  ThingName,
  Language,
  ThingId,
  key { ThingName, Language }, // Assuming the same thing may have the same name in different languages
  reference ThingName_Thing { ThingId } references Thing { ThingId }
};

create table CanonicalName {
  ThingId,
  FieldId,
  Language,
  CanonicalName,
  key { ThingId, FieldId, Language },
  reference CanonicalName_Relevance { ThingId, FieldId } references Relevance { ThingId, FieldId },
  reference CanonicalName_ThingName { ThingId, Language, CanonicalName } references ThingName { ThingId, Language, ThingName }
};

CanonicalName 不在 BCNF 中,因为 FD { Canonicalname, Language } -> { ThingId },但冗余由引用 CanonicalName_ThingName 控制。 (您可以称它为外键,但它实际上是外键。)这不是错误,而是您如何确保规范名称是事物名称之一。 (我假设这是一条规则。)在这个设计中,在 CanonicalName 中有一个 Language 列并不是多余的,它可以实现你所缺少的 0-1 约束。

这种设计允许多个Thing在不同的语言中有相同的名字,也允许不同的Thing在不同的语言中有相同的名字。例如,"kjole" 在挪威语和丹麦语中都表示 "dress",但在挪威语中 "dress" 在英语中表示 "suit"。让我知道这是否应该被禁止,我会更新设计。

相关性 table 可以(或可能应该)被省略,如果有一条规则说一个事物与一个字段相关,当且仅当它至少有一个该字段的规范名称。当然,CanonicalName 必须引用 Field 而不是 Relevance。