Ограничения уникальности в MS Access - PullRequest
2 голосов
/ 09 апреля 2009

В базе данных, которую мне нужно спроектировать для MS Access, у меня есть таблица «Измерения», в которой хранятся определенные параметры измерения (Измеренные значения, Отклонение стандартного отклонения и т. Д.) - каждая строка имеет целочисленный идентификатор как основной ключ.

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

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

Ответы [ 5 ]

3 голосов
/ 09 апреля 2009

Такие ограничения действительно могут быть реализованы в ACE / JET с использованием ограничений CHECK.

Человек, который сказал, что обычно использует триггеры для такого рода вещей, не знает о разнице между CHECK ограничениями в ACE / Jet и SQL Server соответственно: в SQL Server они не могут включать подзапросы, то есть не могут ссылаться на значения в других строках той же таблицы или в других таблицах, тогда как в ACE / Jet это возможно.

В идеальном (но еще не существующем AFAIK) продукте SQL-92 описанная уникальность будет реализована с использованием ASSETION, находящимся на уровне схемы. Поскольку ограничения CHECK относятся к уровню таблицы и проверяются только в том случае, если для таблицы, для которой они определены, задано UPDATE d или INSERT ed, вам нужно будет установить соответствующие ограничения CHECK для всей ссылочной таблицы (то же самое будет к триггерам SQL Server). Вот быстрый пример:

CREATE TABLE Parent 
(
   parent_ID INTEGER NOT NULL IDENTITY UNIQUE, 
   data_col INTEGER NOT NULL
)
;
CREATE TABLE Child1
(
   parent_ID INTEGER NOT NULL
      REFERENCES parent (parent_ID), 
   data_col INTEGER NOT NULL
)
;
CREATE TABLE Child2
(
   parent_ID INTEGER NOT NULL
      REFERENCES parent (parent_ID), 
   data_col INTEGER NOT NULL
)
;
ALTER TABLE Child1 ADD
   CONSTRAINT child1__no_dups_in_child2
   CHECK (NOT EXISTS (
                      SELECT * 
                        FROM Child1 AS C1
                             INNER JOIN Child2 AS C2
                                ON C1.parent_ID = C2.parent_ID
                     ))
;
ALTER TABLE Child2 ADD
   CONSTRAINT child2__no_dups_in_child1
   CHECK (NOT EXISTS (
                      SELECT * 
                        FROM Child1 AS C1
                             INNER JOIN Child2 AS C2
                                ON C1.parent_ID = C2.parent_ID
                     ))
;

Однако мне интересно, есть ли у вас подклассы (т. Е. Можно вводить каждую сущность, представленную идентификатором), и в этом случае вы сможете использовать ограничения FOREIGN KEY s и CHECK уровня строки (или валидацию) Правила, если вам удобнее использовать интерфейс MS Access, чем SQL DLL, что требуется для ограничений CHECK). Логика будет легче реализовать, чем ограничения на уровне таблицы CHECK, просто следите за циклами в CASCADE ссылочных действиях. Вот еще один простой пример:

CREATE TABLE Parent 
(
   parent_ID INTEGER NOT NULL IDENTITY, 
   child_type VARCHAR(4) NOT NULL, 
   CONSTRAINT child_type__values 
      CHECK (child_type IN ('Boy', 'Girl')), 
   UNIQUE (child_type, parent_ID)
)
;
CREATE TABLE Girls
(
   parent_ID INTEGER NOT NULL, 
   child_type VARCHAR(4) DEFAULT 'girl' NOT NULL, 
   CONSTRAINT girl_child_type__must_be_girl
      CHECK (child_type = 'girl'),
   FOREIGN KEY (child_type, parent_ID)
      REFERENCES Parent (child_type, parent_ID), 
   data_col INTEGER NOT NULL
)
;
CREATE TABLE Boys
(
   parent_ID INTEGER NOT NULL, 
   child_type VARCHAR(4) DEFAULT 'boy' NOT NULL, 
   CONSTRAINT boy_child_type__must_be_boy
      CHECK (child_type = 'boy'),
   FOREIGN KEY (child_type, parent_ID)
      REFERENCES Parent (child_type, parent_ID), 
   data_col INTEGER NOT NULL
)
;
3 голосов
/ 09 апреля 2009

Ядро Microsoft ACE / Jet не поддерживает триггеры, поэтому вы обычно реализуете этот тип функций.

РЕДАКТИРОВАТЬ: Как указано @onedaywhen, JET 4.0 и далее поддерживает проверочные ограничения, но не просто реализовать ограничение типа xor для двух столбцов.

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

0 голосов
/ 10 апреля 2009

Я сам опасаюсь триггеров и проверяю ограничения, в основном потому, что я разработал большинство своих приложений без них (Access / Jet и MySQL / MyISAM). Я согласен с BobClegg, что это звучит как ситуация с супертипом / подтипом. В этом случае вы бы использовали таблицу соединений с уникальным индексом для внешнего ключа и столбцом, указывающим тип измерения. Уникальный индекс на FK предотвратит добавление второго типа. Это также означает, что у вас не будет пустых полей в основной записи. Конечно, одно пустое числовое поле не является проблемой хранения, но два исключительных поля всегда кажутся мне ошибкой проектирования.

0 голосов
/ 09 апреля 2009

Учитывая, что вы проектируете эту базу данных. Вы уверены, что ваши структуры таблиц соответствуют стандартным правилам нормализации.

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

0 голосов
/ 09 апреля 2009

Митч прав насчет того, что возможно в Access. Однако, если у вас где-то есть BL, это вписывается в то, что является законным как бизнес-правило. Это то, что я, скорее всего, сделаю.

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