Комментарии до того, как вопрос был превращен в «бонусный» вопрос
То, что вы хотели бы сделать, это выразить, что объединение Elements и Elements_Xref имеет уникальное ограничение на Class и Real ID. Если у вас есть СУБД, которая поддерживает ограничения ASSERTION для SQL-92, вы можете сделать это.
AFAIK, ни одна СУБД не поддерживает их, поэтому вы застряли с использованием триггеров.
Кажется странным, что дизайн не ограничивает Real ID быть уникальным среди классов; Из обсуждения кажется, что данный Real ID может быть частью нескольких разных классов. Если бы действительный идентификатор был «уникальным, если не нулевым», то вы могли бы легче обеспечить уникальность, если бы СУБД поддерживала концепцию «уникального, если не нулевого» (большинство этого не делает; я верю, что есть такая, но она забыта который это).
Комментарии перед внесенными изменениями 2010-02-08
Вопрос исключает «заклинивание» Real_ID в верхней таблице (элементы); он не исключает включение класса в нижнюю таблицу (Elements_Xref), который затем позволяет вам создать уникальный индекс для Class и Real_ID в Elements_Xref, достигая (я полагаю) требуемого результата.
Из данных примера неясно, является ли синтетический идентификатор в таблице элементов уникальным или может ли он повторяться с разными классами (или, действительно, может ли синтетический идентификатор повторяться в одном классе). Учитывая, что столбец идентификатора (как представляется, является уникальным), а также столбец синтетического идентификатора кажется разумным предположить, что иногда синтетический идентификатор повторяется - в противном случае в таблице есть два уникальных столбца без веской причины. По большей части это не имеет значения - но это влияет на ограничение уникальности, если класс копируется в таблицу Elements_Xref. Еще одна возможность; возможно, класс вообще не нужен в таблице элементов; он должен жить только в таблице Elements_Xref. У нас недостаточно информации, чтобы сказать, возможно ли это.
Комментарии для внесенных изменений 2010-02-08
Теперь, когда таблица Элементов имеет Синтетический ID в качестве первичного ключа, все несколько проще. Есть комментарий, что информация «Класс» на самом деле является «месяцем», но я постараюсь не обращать на это внимания.
В таблице Elements_Xref у нас есть столбец уникального идентификатора, а затем синтетический идентификатор (который не помечен как внешний ключ для элементов, но предположительно должен фактически быть один) и реальный идентификатор. Из данных примера видно, что более одного синтетического идентификатора могут сопоставляться с данным реальным идентификатором. Непонятно, почему в таблице Elements_Xref есть и столбец ID, и столбец синтетического идентификатора.
Мы не знаем, может ли один синтетический идентификатор сопоставляться только с одним действительным идентификатором или он может сопоставляться с несколькими значениями действительного идентификатора.
Поскольку синтетический идентификатор является первичным ключом элементов, мы знаем, что один синтетический идентификатор соответствует одному классу.
Мы не знаем, меняется ли сопоставление Synthetic ID и Real ID с течением времени (это может быть связано с тем, что класс связан с датой) и нужно ли помнить старое состояние.
Можно предположить, что таблицы сведены к минимуму и что в каждой таблице есть другие столбцы, содержимое которых не имеет прямого отношения к вопросу.
Проблема состоит в том, что реальный идентификатор является внешним ключом для других данных и может иметь значение NULL.
Я не вижу совершенно не избыточного дизайна, который работает.
Я думаю, что таблица Elements_Xref должна содержать:
- Синтетический ID
- Класс
- Настоящий ID
с (Синтетический ID, Класс) в качестве элемента внешнего ссылки, ссылающегося на Элементы, и с ограничением NOT NULL на Реальный ID, и с уникальным ограничением на (Класс, Реальный ID).
Таблица Elements_Xref содержит только те строки, для которых известен Real ID, и корректно обеспечивает требуемое ограничение уникальности.
Странный бит в том, что данные (Synthetic ID, Class) в Elements_Xref должны совпадать с теми же столбцами в Elements, даже если Synthetic ID является первичным ключом Elements.
В IBM Informix Dynamic Server вы можете добиться этого:
CREATE TABLE elements
(
class CHAR(1) NOT NULL,
synthetic_id SERIAL NOT NULL PRIMARY KEY,
UNIQUE(class, synthetic_id)
);
CREATE TABLE elements_xref
(
class CHAR(1) NOT NULL,
synthetic_id INTEGER NOT NULL REFERENCES elements(synthetic_id),
FOREIGN KEY (class, synthetic_id) REFERENCES elements(class, synthetic_id),
real_id CHAR(5) NOT NULL,
PRIMARY KEY (class, real_id)
);