Проблема согласованности схемы базы данных - PullRequest
2 голосов
/ 01 мая 2011

Часть моей схемы базы данных включает объекты:

Jobs
Agencies
Agents
and relation JobAgent
  • Каждое задание имеет одно агентство, которому оно принадлежит
  • Каждый агент принадлежит одному агентству
  • В каждом задании есть 0-н агентов

База данных будет SQL Server 2008

Вот моя схема:

enter image description here

Моя проблема в том, что Jobs.agencyid всегда должен быть равен Agents.agencyid, если он связан через JobAgent. Если Jobs.agencyid будет обновлён до нового агентства, агенты будут принадлежать другому агентству, чем задание.

Как лучше всего перестроить мою схему, чтобы не полагаться на триггеры или код приложения для обеспечения такой согласованности?

Ответы [ 4 ]

1 голос
/ 01 мая 2011

Проблема в том, что если работа перемещается из одного агентства в другое (как вы говорите, если Jobs.agencyid должен был быть обновлен ...), то соответствующие записи в JobAgent теряют смысл: эти агенты не могут быть прикрепленным к работе, которой больше нет в их агентстве, поэтому записи JobAgent, связывающие их с заданиями, должны быть удалены ...

Один из способов обеспечить это - добавить поле JobAgent.agencyid и сделать его внешним ключом для Jobs.agencyid , с ON UPDATE RESTRICT для принудительного (ручного) удаления соответствующих записей JobAgent до изменения Jobs.agencyid.


Редактировать : другая проблема, которую я на самом деле не рассматривал, заключается в том, что когда вы впервые связываете задание с агентом (т.е. создаете новую запись JobAgent), вы должны убедиться, что они оба принадлежат то же самое агентство ... для этого, я думаю, решение OMG работает лучше всего - я рад отложить лучший ответ.

OMG также поднимает вопрос о том, как обрабатывать обновления: вы можете либо

  1. Измените поле Jobs.agencyid и удалите (вручную) все связанные записи JobAgent: в этом случае старые агенты больше не работают над этим заданием, и вы можете назначить кого-то из нового агентства для работы над ним.

  2. Измените поле Jobs.agencyid и также измените все связанные записи JobAgent (т. Е. Все эти агенты перемещаются с заданием в новое агентство) - но это очень грязно потому что эти агенты также будут связаны с другими заданиями, которые все еще находятся в исходном агентстве.

  3. Как предлагает OMG, создайте новую запись Jobs и пометьте старую как несуществующую (для последующего удаления).

  4. Как указано выше, но сохраняйте запись о несуществующей работе, чтобы сохранить историческую информацию.

Выбор 3 или 4 зависит в некоторой степени от того, для чего предназначена ваша система: хотите ли вы просто поддерживать текущее состояние "кто имеет какие работы"? или вам нужно вести какую-то историю, например, если к работе приложены учетные записи ... эта информация должна оставаться связанной с исходным агентством (но это все выходит за рамки вашего исходного вопроса).

1 голос
/ 01 мая 2011

АГЕНТСТВА

  • agency_id (pk)

JOBS

  • job_id (pk)
  • agency_id (fk toAGENCIES.agency_id)

АГЕНТЫ

  • agent_id (pk)
  • agency_id (от FK до AGENCIES.agency_id)

JOBAGENT

  • job_id
    • fk to JOBS.job_id
  • agent_id
    • fk для AGENTS.agent_id
  • agency_id
    • fk до JOB.agency_id
    • fk до AGENTS.agency_id

Вы можете определить большечем одно ограничение внешнего ключа для столбца - это просто означает, что значение в JOBAGENT должно удовлетворять ОБА ограничениям внешнего ключа, которые должны быть разрешены.Но вам будет весело, если вы когда-нибудь захотите обновить задания для другого агентства ...;) SQL Server поддерживает составные внешние ключи: http://msdn.microsoft.com/en-us/library/ms175464.aspx

Обновление в отношении обновления

У вас есть дваварианты -

  • Выполнять вручную, поскольку ON UPDATE CASCADE и т. д. не будут обрабатывать обновления агентства и агента без использования триггеров
  • Наличие столбца состояния в JOB, поэтому вы можете отменить заданиечтобы воссоздать работу с новыми записями поддержки (агент, агент по трудоустройству и т. д.).Дальнейшая очистка может быть автоматизирована, в зависимости от статуса работы, если вы хотите
0 голосов
/ 01 мая 2011

Следующая схема отвечает на ваш вопрос?

    Jobs      Agents     Agencies
      ^          ^          ^
      |          |          |
       \         |         /
        \        |        /
           AgentiatedJob

Как правило, у меня есть первичный ключ с одним полем для каждой таблицы, потому что проще сопоставить реестр в таблице и ссылаться на него в таблицах ниже. Таким образом, следуя этому подходу, AgientiatedJob будет иметь по крайней мере поля:

  • AgentiatedJobId
  • JobId
  • AgentId
  • AgencyId
0 голосов
/ 01 мая 2011

Вы можете использовать ON UPDATE CASCADE с внешними ключами.См. Страница Википедии .Или, может быть, если agencyid - это то, что вы ожидаете изменить, вы можете иметь уникальное ограничение для него и использовать какое-то другое бессмысленное поле для идентификатора агентства (скажем, столбец автоинкремента).

...