Избегайте дублирования «пар» значений (два столбца) в таблице SQL - PullRequest
0 голосов
/ 28 января 2019

У меня есть таблица, документирующая отношения между членами домохозяйства, и я хотел бы убедиться, что всегда будет только одна запись с теми же двумя людьми в ней - но теперь нужно рассмотреть два столбца и два значения.Я провел пару часов поиска, и хотя я уверен, что он там, я не нашел его.

У меня есть таблица для людей, чей внешний ключ (Persons.ID) здесь появится в aIDи ставку (два человека).У меня есть другая таблица для ролей (мать, дочь, дядя, брат и т. Д.), Чей внешний ключ (Roles.ID) будет отображаться в aID_role и bID_role).(Я пытаюсь хранить только целые числа в этой таблице, потому что в конечном итоге в ней может быть довольно много записей.)

Relationships
----------------------------------------
aID     aID_role     bID     bID_role
----------------------------------------
 4        1           5        2

Скажем, aID 4 - это Джон, а bID 5 - это Карла.aID_role 1 - это «папа», а bID_role 2 - «дочь».

Как запретить ввод второй записи ниже?

Relationships
----------------------------------------
aID     aID_role     bID     bID_role
----------------------------------------
 4        1           5        2
 5        2           4        1 <-- sort of a duplicate

Обратите внимание, что меня не интересует сравнениестолбцы "_role".Они нематериальны здесь;Я хочу, чтобы Person.ID 4 и 5 не появлялись в нескольких записях в таблице "Отношения".

База данных находится в Azure SQL.

Ответы [ 3 ]

0 голосов
/ 28 января 2019

Вы можете создать вычисляемые столбцы, которые отражают идентификаторы следующим образом:

id1 AS (CASE WHEN aID < bID THEN aid ELSE bid END),
id2 AS (CASE WHEN aID < bID THEN bid ELSE aid END),

Тогда две строки дубликата будут выглядеть следующим образом:

aID  bID  id1  id2
4    5    4    5
5    4    4    5

И выпросто нужно создать УНИКАЛЬНОЕ ограничение:

CONSTRAINT IX_Relationships UNIQUE (id1, id2)
0 голосов
/ 28 января 2019

предложение новой модели:

table persons
id PK
first_name,
second_name


table roles
id PK
role_id
role_name (ex. Father, daugther,)

table relationship
id PK
person    (ex. persons.id = 1, JOHN)
role      (roles.id = 5, FATHER
person_to (persons.id = 3, CARLA,

, короче говоря, "person" - это "role" to "person_to".

Пример из вашего вопроса: вам нужно только добавить 1 записьв таблицу для:

«ДЖОН» - это «ОТЕЦ» к «КАРЛА».

нет необходимости добавлять второй."JOHN"

0 голосов
/ 28 января 2019

Если вы хотите предотвратить вставку «противоположной» строки, вам необходимо реализовать уникальное ограничение для пары столбцов, которым гарантировано определенное свойство (например, первое всегда ниже второго).

Для неориентированных графов простым подходом является проверка ограничения на таблицу, а затем обеспечение вставки данных в соответствии с ограничением.

Однако отношения, как правило, направлены отношения.Например, у меня будет таблица с FromID, ToID и Relationship, где последний будет искать значения, такие как «Отец и дочь» (которые вы можете прочитать с неявным «От» в начале), которыепроясняет, что является FromID, а что является ToID.

Такая структура проясняет, что существует только один правильный путь для хранения этих отношений - но вы все равно не сможете гарантироватьчто, например, FromID всегда ниже, чем ToID и, возможно, пожелает предотвратить случайные вставки, которые являются неправильными (не допускайте, чтобы кто-то был одновременно и матерью, и дочерью другого)

Поэтому мы вводим индексированное представление , который синтезирует пару столбцов с этим отношением, а затем накладывает на него уникальное ограничение.

CREATE VIEW dbo.Relationships_DRI_Unique
WITH SCHEMABINDING
AS
    SELECT
         CASE WHEN FromID < ToID THEN FromID ELSE ToID   END as Col1,
         CASE WHEN FromID < ToID THEN ToID   ELSE FromID END as Col2
    FROM
        dbo.Relationships
GO
CREATE UNIQUE INDEX IX_Relationships_DRI_Unique on dbo.Relationships_DRI_Unique (Col1,Col2)

(DRI = Декларативная ссылочная целостность. Я использую эти буквы в именовании объектов.которые существуют исключительно для обеспечения ограничения. Я не ожидаю, что кто-нибудь когда-либо запросит это представление)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...