Требуется уровень разработки базы данных и приложения SQL Server Ограничение в БД или в приложении? - PullRequest
1 голос
/ 26 января 2010

Мне нужны некоторые предложения для реализации бизнес-правила - сохранять ли его в БД (используя TRIGGER) или в коде приложения.

--- Table structure:---

# ORG - Master table for Organizations 
# USER - Master table for Users (each user belongs to an Org so there's a field OrgId which is FK ro ORG) 
# SITE - Master table for Sites

# ORGSITE - {OrgId, SiteId} links Site(s) with Org(s) 
# USERSITE - {UserId, SiteId} links Site(s) with User(s)

Ограничение заключается в следующем: «Сайт доступен ТОЛЬКО пользователю, если он доступен для его организации».


Теперь в приложении случается, что в день 1 мы связываем Site1 с Org1, а затем мы можем связать Site1 с User1 (User1 принадлежит Org1). На второй день я удаляю связь между Site1 и Org1 из ORGSITE (для этого необходимо также удалить соответствующую связь User1 & Site1 из таблицы USERSITE).

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

ПОДХОД # 1:

Развертывание TRIGGER в таблице ORGSITE и таблице USER, которые будут обрабатывать действия для:

  1. Вкл. После удаления для ORGSITE (удалить соответствующие записи USERSITE)

  2. После обновления для ПОЛЬЗОВАТЕЛЯ (если пользователь Орг изменился, тогда удали его все записи с USERSITE)

ПОДХОД # 2:

Обработайте все внутри кода - нажмите на события, которые запускают эти действия БД, и удалите записи с USERSITE (по мере необходимости). Нужно управлять через транзакцию.

ПОДХОД # 3:

Просто добавьте новое поле OrgSiteId в таблице USERSITE, которое является ссылкой FK, на «Auto Increment PK: Id» ORGSITE. Далее я разверну каскадное удаление для USERSITE.OrgSiteId FK. Это будет обрабатывать большинство вещей и делать это неявным!

Надеюсь, я хорошо объясню. Подход № 3 действительно сработает? Если нет - какие у вас предпочтения и почему?

Спасибо за ваше время.

Ответы [ 4 ]

4 голосов
/ 26 января 2010

Если вы думаете, что кто-то когда-либо будет запускать запрос прямо из БД (например, администратор БД), то вы должны обработать его в триггере. Если вы делаете это через приложение, вы должны всегда делать это через приложение.

3 голосов
/ 26 января 2010

Я бы предложил:

  • Удалить таблицу UserSite
  • Создать представление с именем UserSite

    SELECT a.UserId, b.SiteID ОТ пользователя СЛЕДУЮЩЕЕ СОЕДИНЯЙТЕСЬ

Возвращает сайты, которые пользователь может видеть, или NULL, если он или она не видит

1 голос
/ 26 января 2010

Органы иерархические? Есть ли поле ORG.parent_org_id?

Если это так, ваша проблема немного сложнее, потому что вам, вероятно, нужен человек, чтобы видеть все САЙТЫ, связанные с их организацией или дочерними элементами ее организации (что-то вроде разрешений для папок в файловой системе).

Решение представления от Sparky, приведенное выше, все еще может работать в этом случае, если ваша база данных поддерживает рекурсивные соединения или общие табличные выражения . ANSI-стандартный способ сделать это с помощью CTE (поддерживается только в SQL 2005 и более поздних версиях и PostgreSQL, я думаю). Oracle и другие БД имеют нестандартный синтаксис для той же функциональности рекурсии.

0 голосов
/ 26 января 2010

Вы можете использовать триггеры; это жизнеспособный вариант, который будет работать. Лично я бы не использовал каскадные удаления, поскольку это может быть опасно.

Я предпочитаю вариант кода, потому что он позволяет мне обрабатывать определенные ошибки, регистрировать и проверять ссылки. У вас есть кое-что в триггерах, но это мое личное предпочтение. Кроме того, это объединяет логику с другим кодом, изменяющим приложение, поэтому вся логика находится в одном месте и не разбивается на приложение / базу данных. Но опять же, это личное предпочтение для меня; триггеры - это очень хороший и жизнеспособный вариант.

НТН.

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