Является ли использование нескольких уникальных ограничений на одной таблице плохим дизайном?

8

Я посмотрел на INSERT INTO .. ON CONFLICT (..) DO UPDATE ..синтаксис PostgreSQL и понял, что вы не можете сделать несколько уникальных проверок ограничений с ним. Я имею в виду, что вы либо ссылаетесь на составной уникальный индекс по именам столбцов ON CONFLICT (Name, Symbol)(если уникальный индекс определен для этих двух столбцов), либо используете первичный ключ. Если вы определяете два отдельных уникальных индекса для столбцов, вы можете проверить только один.

CREATE TABLE student
    (Id int primary key, Name varchar(50), Symbol varchar(50),
      CONSTRAINT col1_unique UNIQUE (Name),
      CONSTRAINT col2_unique UNIQUE (Symbol)
    ); 

INSERT INTO student
    (Id, Name, Symbol)
VALUES
    (1, 'John', 'J'),
    (2, 'David', 'D'),
    (3, 'Will', 'W');

INSERT INTO student
    (Id, Name, Symbol)
VALUES
    (4, 'Jeremy', 'J')
   on conflict(Name) DO UPDATE
   set Name = 'Jeremy';

Может выдать ошибку, говоря, Jявляется дубликатом. Однако этот пример просто плохой дизайн, потому что Символ должен быть в другой таблице и быть связан с таблицей ученика через отношение один ко многим. Вот почему мне интересно, может быть, PostgreSQL on conflictбыл спроектирован таким образом, потому что вы ВСЕГДА можете реструктурировать таблицы таким образом, чтобы в них был только один уникальный индекс. Это правда или есть другая причина?

Пример скрипки: http://www.sqlfiddle.com/#!17/9c0ce

appl3r
источник
вы ВСЕГДА можете реструктурировать таблицы таким образом, чтобы был только один уникальный индекс. Существуют EntityA и EntityB. Есть 2 экземпляра каждого. Любой экземпляр EntityA может объединяться с любым экземпляром EntityB, поэтому существует 2 возможных комбинации, в которых используются все экземпляры. Одна из этих комбинаций реализована, и вы должны ее сохранить. Теперь попробуйте создать схему, в которой не существует таблицы с двумя уникальными типами со всеми ограничениями, которая предотвращает использование недопустимых данных.
Акина
@ Акина, я упустил твою точку зрения. Если две сущности связаны через отношение «многие ко многим», вы создаете таблицу ссылок, в которой хранятся их внешние ключи, поэтому таблицы с двумя уникальными индексами не существует.
appl3r
Один экземпляр может быть использован только один раз, поэтому вы должны иметь 2 уникальных индекса в связанной таблице (каждой сущностью отдельно), чтобы предотвратить использование уже использованного экземпляра.
Акина
Хотя это правда, это довольно сложно: посмотрите образец в ответе Майкла Грина. Разделение такой простой таблицы на 4 таблицы - определенно головная боль, хотя, поскольку это простой словарь, вам не нужно использовать опцию «ON CONFLICT».
Уолфрат

Ответы:

8

Всегда есть Шестой, или Ключ Домена, Нормальная Форма. Здесь каждый неключевой столбец становится собственной таблицей. Таким образом, таблица 3NF T (Key, Col1, Col2, ..) становится T1 (Key, Col1), T2 (Key, Col2) и т. Д. Те новые таблицы, которым требуется уникальность, могут быть объявлены.

Однако я думаю, что иметь несколько уникальных ограничений на таблицу - это нормально. Взять хотя бы таблицу стран. Это будет, скажем, ID, название, код ISO, столица и некоторые другие. Каждый из этих первых четырех будет уникальным. Более того, если мы хотим, чтобы наша система опиралась на уникальность каждого, я считаю, что мы должны определить уникальные ограничения для каждого из них. Это обеспечивает правду о данных, на которые могут положиться все потребители.

Майкл Грин
источник
Вы думаете, что дизайн postgresql - это только результат близорукости? Oracle, SQL Server, DB2 и другие предоставляют способ учесть все уникальные ключи в такой ситуации (используя MERGEинструкцию). Pg ON CONFLICT DO UPDATE был добавлен только в 9.5 и намного более ограничен.
appl3r
1
@ appl3r это только детали реализации. Вы можете обойтись ON CONFLICT DO NOTHINGбез упоминания уникальных ограничений, и он будет учитывать все из них (и ничего не делать). Когда вы хотите сделать ON CONFLICT DO UPDATE, вы должны объявить столбец или ограничение и только один. Ограничение может быть снято в будущих версиях.
ypercubeᵀᴹ
Я немного смущен вашим первым абзацем. Допустим, мы разбили таблицу студента (Id, Name, Symbol) на S1 (Id, Name) и S2 (Id, Symbol), чтобы попытаться превратить ее в DK / NF. Каковы будут ограничения домена и домена на S2, и как они будут гарантировать, что у каждого учащегося есть как один уникальный идентификатор, так и один уникальный символ?
Илмари Каронен
1
Вопрос был (вроде): «Если с несколькими индексами UNIQUE все в порядке, почему PostgreSQL требует, чтобы был указан индекс арбитра, ON CONFLICT ... DO UPDATEи, к сожалению, этот ответ не решает эту проблему.
AndreKR
@AndreKR адресовано (выделено жирным шрифтом): «было ли (эта функция Postgres) спроектирована таким образом, потому что вы ВСЕГДА можете реструктурировать таблицы таким образом, чтобы в них был только один уникальный индекс?» Вы, конечно, можете добавить еще один ответ, обращаясь к
теме, которую