Как определить составной внешний ключ для ограничений домена при наличии суррогатных ключей? - PullRequest
1 голос
/ 31 марта 2010

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

Вот что я мог бы представить как "Путь Рельсов". Это то, с чего я начал.

Companies:
    id: integer, serial
    company_code: char, unique, not null

Invoices:
    id: integer, serial
    company_id: integer, not null

Products:
    id: integer, serial
    sku: char, unique, not null
    company_id: integer, not null

LineItems:
    id: integer, serial
    invoice_id: integer, not null, references Invoices (id)
    product_id: integer, not null, references Products (id)

Проблема в том, что продукт одной компании может появиться в счете для другой компании. Я добавил (company_id: integer, а не NULL) в LineItems, как если бы я использовал только натуральные ключи и серийные номера, а затем добавил составной внешний ключ.

LineItems (product_id, company_id) references Products (id, company_id)
LineItems (invoice_id, company_id) references Invoices (id, company_id)

Это правильно ограничивает LineItems для одной компании, но кажется чрезмерно сложным и неправильным. company_id в LineItems является посторонним, потому что суррогатные внешние ключи уже уникальны во внешней таблице. Postgres требует, чтобы я добавил уникальный индекс для указанных атрибутов, поэтому я создаю уникальный индекс для (id, company_id) в продуктах и ​​счетах, даже если id просто уникален.

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

LineItems:
    company_code: char, not null
    sku: char, not null
    invoice_id: integer, not null

Я могу игнорировать суррогатные ключи в таблице LineItems, но это также кажется неправильным. Зачем делать так, чтобы база данных объединялась на char, если в ней уже есть целое число? Кроме того, выполнение этого в точности так, как описано выше, потребует от меня добавления company_code, естественного внешнего ключа, к продуктам и счетам.

Компромисс ...

LineItems:
    company_id: integer, not null
    sku: integer, not null
    invoice_id: integer, not null

не требует естественных внешних ключей в других таблицах, но он все еще соединяется с char, когда доступно целое число.

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

1 Ответ

1 голос
/ 02 апреля 2010

Вы упоминаете, что id уже уникален выше, но вы должны сделать id, company_id уникальным, потому что вы используете его в ссылке FK, которая должна быть уверена, что он ссылается только на 1 уникальный элемент, а не на что-либо еще.

Я понимаю, что вы хотите "защитить" данные, но я бы сказал, что они чрезмерно спроектированы и согласны с вами. Любая система, которая использует эти данные и не работает должным образом (подбирает правильные продукты для компании), будет немедленно заметна. Это приведет к бремени работы с большим количеством данных при программировании и может привести к путанице.

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

Я думаю, что данные достаточно защищены благодаря «естественному» использованию в приложении. Когда вы собираетесь создать новый счет-фактуру и ищете товары для выставления счета-фактуры, вы будете использовать тот же идентификатор компании для поиска продуктов, который вы используете для создания счета-фактуры. Если вы каким-то образом получите неправильные идентификаторы (плохой код, пользователи непосредственно в БД), то плохие результаты будут заметны сразу.

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

Почему вы так беспокоитесь о том, что в него могут быть вставлены бессмысленные ключи? Будет ли у пользователя доступ к этим данным нестандартным способом?

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