我有一些事物,它们具有0- *个名称,且具有任意数量的语言:
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));
事物与许多字段相关,在每个字段中每种语言都有0-1个 CanonicalName 。直接的方法是
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 的唯一性约束,以及ThingNames的 thing_id 和 language 列由 canonical_name_id 引用。在CanonicalNames中包括所有列作为外键当然是多余的并且容易出错,因此是否有办法在表之间施加唯一性约束?还是这里有我没有看到的更好的解决方案?
答案 0 :(得分:0)
我不确定您的设计中有几件事。将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 }
};
由于FD { Canonicalname, Language } -> { ThingId }
,CanonicalName不在BCNF中,但是冗余由引用CanonicalName_ThingName控制。 (您可以将其称为外键,但实际上它是外键。)这不是bug,而是通过这种方式确保规范名称是事物名称之一。 (我假设这是一个规则。)在这种设计中,在CanonicalName中具有Language列不是多余的,它可以启用您缺少的0-1约束。
此设计允许多个事物在不同语言中具有相同的名称,但也允许不同事物在不同语言中具有相同的名称。例如,“ kjole”在挪威语和丹麦语中均表示“着装”,而在挪威语中的“着装”在英语中则表示“西服”。让我知道是否应禁止这样做,我将更新设计。
如果有规则说事物与某个领域相关,并且且仅当该事物具有该领域的至少一个规范名称时,相关表可以(或应该省略)。当然,CanonicalName必须引用Field而不是Relevance。