2015-03-31 2 views
2

У меня есть 3 таблицы - users, teams и team_members. Последнее представляет собой карту многих ко многим от team(id) до user(id) (внешние ключи до teams и users соответственно). Есть ли какая-либо проверка целостности, которую я могу добавить в свою базу данных, которая может утверждать, что, хотя команды без участников могут быть, но пользователи без команд невозможно? Чтобы уточнить, я хочу обеспечить соблюдение на уровне базы данных, что все пользователи должны принадлежать к команде atleast 1 (при этом не требуется, чтобы все команды имели 1 пользователь). Ответ, который работает в MYSQL или Postgres, является приемлемым.Проверка целостности ссылочной целостности в SQL

+0

Что вы используете? MySQL или Postgres? –

+0

Я открыт для обоих. – pathikrit

+0

Просто мысль. Ваше ограничение означает, что когда вы пытаетесь «ВСТАВИТЬ» строку в «пользователей», вы должны также «ВСТАВИТЬ» хотя бы одну строку в «team_members». Таким образом, вся операция не является атомарной, и проверка ограничения должна быть отложена до тех пор, пока обе таблицы не будут изменены. Он пахнет каким-то причудливым триггером. Было бы интересно увидеть решение. –

ответ

3

(Ответ предполагает PostgreSQL;. Сведения о триггерах и блокировке будут меняться, если вы используете другой СУБД, но большинство RDBMSes должно быть в состоянии поддерживать те же основные операции)

Хотя можно добавить внешний ключ от users до teams, для этого требуется дублирование знаний - в основном вы создадите дополнительную связь m: 1 в дополнение к отношениям exisitng m: n. Это нежелательно.

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

  • отложенное триггер ограничение ON INSERT OR UPDATE ... FOR EACH ROW триггер на users, что делает LOCK TABLE users, team_members IN EXCLUSIVE MODE, а затем проверяет, что созданный пользователем, если он не был удален, так как, по меньшей мере одну команду с помощью объединения через team_members. Ваше приложение будет хотеть LOCK TABLE users IN EXCLUSIVE MODE, прежде чем писать ему, а также для предотвращения взаимоблокировок. Обратите внимание, что EXCLUSIVE MODE не предотвращает SELECT.

  • a отложенный триггер ограничения ON UPDATE OR DELETE ... FOR EACH ROW на team_members, который делает то же самое в обратном порядке, убедившись, что если вы удалите членство в команде, то пользователь, который был членом, все еще имеет другие членства в команде. Он также должен блокировать как users, так и team_members.

Конечно, team_members также нуждается FK ограничения на users и teams, но это должно быть просто считать для т: п присоединиться к таблице.

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

Если вам нужен хороший параллелизм, вы, вероятно, набиты.

+0

Если вам не нужны команды team_members, вы могли бы сделать это с помощью столбца массива для замены 'team_members', некоторых триггеров для подделки FK и CHECK, чтобы гарантировать, что массив не пуст? Условия гонки? –

+1

@muistooshort Вы можете, но триггеры FK имеют некоторые специальные трюки, которые вы не можете легко эмулировать с помощью пользовательских триггеров. Расы были бы проблемой, как вы подозревали, если вы не сделали блокировки на уровне стола. В этом случае вы могли бы также провести традиционное реляционное моделирование. –

+0

Ну, это исключает Mysql, поскольку у него нет отложенных ограничений. – pathikrit

Смежные вопросы