2010-03-01 1 views
0

У меня есть модель, которая выглядит примерно так:Устранение избыточных отношений при моделировании отношений заголовка/детали?

Model

Один аккаунт имеет много ветвей, и каждое заявление генерируется для одного аккаунта. Модель избыточна, поскольку учетная запись (идентификатор учетной записи в заголовке) может быть выведена из идентификатора BranchID в транзакции (оператор всегда будет иметь одну или несколько транзакций).

Следует ли удалить идентификатор учетной записи из StatementHeader или это уровень избыточности ОК? Или есть лучшее решение?

+0

Я бы не использовал «ID» в качестве имени первичного ключа в каждой таблице; вы в конечном итоге загружаете их в свою модель и никогда не можете быть уверены в том, что вы имеете в виду. Если вы используете суррогатные ключи, я бы предложил вам использовать одно и то же имя на всей вашей модели. У вас уже есть AccountID в качестве внешнего ключа, поэтому используйте одно и то же имя для основного. – Tony

+0

Неопределенно соглашение об именах было установлено кем-то другим, поэтому я не могу его изменить. Я ценю ваше обоснование, хотя у меня такие же проблемы. – ilitirit

+0

Что такое объект StatementHeader? Являются ли утверждения с одним и тем же StatementHeaderID соединены друг с другом в реальном мире или являются идентификатором AccountID и StatementDate? Последнее будет делать StatementHeader чем-то вроде календаря с SatementHeaderID в качестве маскировки даты ... – wallenborn

ответ

0

Если у вас есть StatementHeader, тогда у него должен быть ID учетной записи, чтобы сохранить ссылочную целостность.

Однако может быть лучше полностью удалить StatementHeader и переместить StatementDate в запись Statement. Это сделает вещи более чистыми и сделает модель лучше описывать то, что вы хотите.

+0

Это просто перенесет избыточность на запись, поскольку каждая запись будет иметь одинаковую дату. – ilitirit

+0

Он делает запись каждого заявления самодостаточной, которая хороша. Не все избыточность плохая - в этом случае производительность будет лучше, потому что вы можете удалить соединение, чтобы получить дату. Я понимаю, что в ситуациях, когда дата утверждения может измениться, наличие таблицы «StatementHeader» позволяет манипулировать датой, но если я не ошибаюсь, даты дат не часто меняются в этом сценарии, поэтому это приемлемо. –

0

Как утверждение является историческим, и, как правило, только для чтения, данные имеют определенную избыточность. Я согласен с Ричардом Харрисоном и переместил оба [AccountID] и [StatementDate] в таблицу [Statement]; Мое рассуждение заключается в том, что вы говорите, что учетная запись имеет много филиалов, поэтому вы будете генерировать отчет для учетной записи.

Хранение всех этих данных в одном и том же месте приведет к сокращению объединений и ускорению отчетности, что я считаю причиной этой базы данных.

0

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

Чтобы обеспечить соблюдение этого правила, вы можете попытаться создать схему базы данных, которая делает невозможным ее нарушение или принудительно принудительно применяется с ограничением или триггером. И это проще с помощью StatementHeader.AccountID. В Oracle, вы могли бы написать что-то вроде этого:

create or replace trigger statement_has_unique_account 
before insert or update on Statement 
referencing old as old new as new 
for each row 
declare 
    m integer; 
    n integer; 
begin 
    select b.AccountID 
    into m 
    from Branch b 
    where b.ID = new.BranchID; 

    select s.AccountID 
    into n 
    from StatementHeader s 
    where s.ID = new.StatementID; 

    if m <> n then 
    raise_application_error(-1000, 'No way!'); 
    end if; 
end; 

Без AccountID в StatementHeader, вы должны написать сравнение со всеми другими AccountIDs от всех других заявлений, которые разделяют те же StatementId, что приводит к более сложным последовательность утверждений.

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