Ограничение уникальности для других столбцов в таблице внешнего ключа - PullRequest
0 голосов
/ 26 июня 2018

У меня есть некоторые Вещи с 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 вместе со столбцами thing_id и language в ThingNames, на которые ссылается canonical_name_id . Включение всех столбцов в качестве внешних ключей в CanonicalNames, конечно, избыточно и подвержено ошибкам, так есть ли способ наложить ограничения уникальности на таблицы? Или есть лучшее решение, которого я не вижу?

1 Ответ

0 голосов
/ 27 июня 2018

Я не уверен насчет пары вещей в вашем дизайне. Объявление 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 не является избыточным, и оно включает ограничение 0-1, которое вам не хватает.

Этот дизайн позволяет нескольким вещам иметь одинаковые имена на разных языках, но также позволяет разным вещам иметь одинаковые имена на разных языках. Например, «kjole» означает «платье» как на норвежском, так и на датском языке, но «платье» на норвежском языке означает «костюм» на английском языке. Дайте мне знать, если это будет запрещено, и я обновлю дизайн.

Таблица релевантности может (или, возможно, должна) быть опущена, если есть правило, гласящее, что Вещество относится к полю, если и только если у него есть хотя бы одно каноническое имя для этого поля. Тогда, конечно, CanonicalName будет ссылаться на Field вместо Relevance.

...