Как обеспечить уникальность для нескольких таблиц - PullRequest
5 голосов
/ 19 февраля 2010

У меня есть следующие таблицы на сервере MySQL:

Companies:
- UID (unique)
- NAME
- other relevant data

Offices:
- UID (unique)
- CompanyID
- ExternalID
- other data

Employees:
- UID (unique)
- OfficeID
- ExternalID
- other data

В каждом из них UID является уникальным идентификатором, созданным базой данных.

Существуют внешние ключи для обеспечения связи между Сотрудником -> Офис -> Компания по UID.

Поля ExternalID в Офисах и Сотрудниках - это идентификатор, предоставленный моему приложению Компанией (фактически, моим клиентом). Клиенты не имеют (и не заботятся) о моих собственных идентификаторах, и все данные, которые мое приложение получает от них, идентифицируются исключительно на основании их идентификаторов (т. Е. ExternalID в моих таблицах).

т.е. запрос от клиента на псевдо-языке похож на «Я Компания X, обнови данные для моего сотрудника Y».

Мне нужно обеспечить уникальность комбинации CompanyID и Employees.ExternalID, поэтому в моей базе данных не будет дубликата ExternalID для сотрудников одной компании.

Я думал о 3 возможных решениях:

  1. Измените схему для сотрудников, включив в нее CompanyID, и создайте уникальное ограничение для двух полей.

  2. Включите триггер, который при обновлении / вставке в Employees проверяет уникальность.

  3. Провести проверку на уровне приложения (т.е. мой сервис получения).

Моя альтернатива-dbadmin-in-me утверждает, что (3) является худшим решением, поскольку оно не защищает базу данных от несогласованности в случае ошибки приложения или чего-то еще, и, скорее всего, будет самым медленным.

Триггерным решением может быть то, что я хочу, но оно может усложниться, особенно если необходимо выполнить несколько вставок / обновлений в одном выражении, и я не уверен насчет производительности по сравнению с (1).

И (1) выглядит самым быстрым и простым подходом, но это противоречит моему пониманию реляционной модели.

Мнение экспертов SO DB о плюсах и минусах каждого из подходов, особенно если есть возможность добавить дополнительный уровень косвенности - например, Компания -> Офис -> Отдел -> Сотрудник, и те же потребности в уникальности быть сохраненным (Компания / Сотрудник).

Ответы [ 3 ]

3 голосов
/ 19 февраля 2010

Вы правы - # 1 - лучший вариант.
Конечно, я бы поставил под сомнение это на первый взгляд (из-за ярлыков), но знание бизнес-правила, гарантирующего, что сотрудник связан только с одной компанией - это имеет смысл.

Кроме того, у меня есть внешний ключ, связывающий идентификатор компании в таблице сотрудников с идентификатором компании в офисе. В противном случае вы разрешаете сотруднику быть связанным с компанией без офиса. Если это не приемлемо ...

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

1 голос
/ 19 февраля 2010

Каждая из таблиц, предоставленных вашей компанией, должна включать CompanyID в «УНИКАЛЬНЫЙ КЛЮЧ» поверх идентификаторов, предоставленных компанией.

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

CREATE TABLE company (
        uid INT NOT NULL PRIMARY KEY,
        name TEXT
        );

CREATE TABLE office (
        uid INT NOT NULL PRIMARY KEY,
        companyID INT NOT NULL,
        externalID INT NOT NULL,
        UNIQIE KEY (companyID, externalID),
        FOREIGN KEY (companyID) REFERENCES company (uid)
        );

CREATE TABLE employee (
        uid INT NOT NULL PRIMARY KEY,
        companyID INT NOT NULL,
        officeID INT NOT NULL,
        externalID INT NOT NULL,
        UNIQIE KEY (companyID, externalID),
        FOREIGN KEY (companyID) REFERENCES company(uid)
        FOREIGN KEY (companyID, officeID) REFERENCES office (companyID, externalID)
        );

и т. Д.

0 голосов
/ 19 февраля 2010

Установите для auto_increment_increment номер вашей таблицы. SET auto_increment_increment = 3; (вы можете установить это в my.cnf)

Затем вручную установите начальное значение auto_increment каждой таблицы на разные значения первый стол до 1, второй стол до 2, третий стол до 3

Таблица 1 будет иметь такие значения, как 1,4,7,10,13 и т. Д.

Таблица 2 будет иметь значения, такие как 2,5,8,11,14 и т. Д.

Таблица 3 будет иметь значения как 3,6,9,12,15 и т. Д.

Конечно, это всего лишь ОДИН вариант, лично я бы просто сделал это комбо-значением. Может быть так же просто, как TableID, AutoincrementID, где TableID является постоянным во всех строках.

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