我有一個模型,它看起來是這樣的:在建模標題/細節關係時消除冗餘關係?
一個帳戶擁有衆多分支機構,併爲一個賬戶中產生的每條語句。該模型是多餘的,因爲帳戶(標題上的AccountID)可以從事務的BranchID中推斷出來(一個語句總是會有一個或多個事務)。
應該從StatementHeader中刪除AccountID,還是這種冗餘級別好?還是有更好的解決方案?
我有一個模型,它看起來是這樣的:在建模標題/細節關係時消除冗餘關係?
一個帳戶擁有衆多分支機構,併爲一個賬戶中產生的每條語句。該模型是多餘的,因爲帳戶(標題上的AccountID)可以從事務的BranchID中推斷出來(一個語句總是會有一個或多個事務)。
應該從StatementHeader中刪除AccountID,還是這種冗餘級別好?還是有更好的解決方案?
如果你有StatementHeader,那麼它應該有AccountID來保持參照完整性。
但是,最好將StatementHeader完全移除並將StatementDate移動到Statement記錄中。這會使事情變得更清潔,並使模型更好地描述你想要的東西。
雖然這只是將冗餘移動到記錄,因爲每條記錄都具有相同的聲明日期。 – ilitirit 2010-03-01 12:30:07
它使每個聲明記錄自成一體,這是很好的。 並非所有冗餘都不好 - 在這種情況下,性能會更好,因爲您可以消除連接以獲取日期。 我明白,在聲明日期可能發生變化的情況下,有一個'StatementHeader'表允許操縱日期,但除非我是錯誤的聲明日期在這種情況下不會經常改變,所以它是可以接受的。 – 2010-03-01 13:09:24
作爲一個陳述是歷史性的,通常只讀,數據一些redundency是好的。我同意Richard Harrison的意見,並將[AccountID]和[StatementDate]都移至[Statement]表中;我的理由是你說一個賬戶有很多分支機構,所以你將爲一個賬戶生成一個聲明。
將所有這些數據存儲在同一個地方將減少連接和加快報告,我認爲這是數據庫的原因。
有時,(真實的或感知的)冗餘是業務規則的結果。在這種情況下,業務規則是:「發給賬戶的聲明應僅包含屬於該特定賬戶的分行的交易。」
要強制執行該規則,您可以嘗試創建一個數據庫模式,使其無法違反它,或者使用約束或觸發器顯式強制執行。而且這似乎更容易與StatementHeader.AccountID。在Oracle中,你可以寫這樣的事情:在StatementHeader
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;
沒有帳戶ID,你必須寫與共享同一StatementID所有其他語句中的所有其他AccountIDs進行比較,從而產生更復雜報表序列。
所以我會將AccountID作爲一個外鍵在StatementHeader中,並用觸發器明確地強制執行業務規則。
我會避免使用「ID」作爲每個表中主鍵的名稱;你最終會在你的模型中加載它們,並且永遠無法確定你所指的是哪一個。 如果您使用代理鍵,那麼我建議您在整個模型中使用相同的名稱。您已將AccountID作爲外鍵,因此對主鍵使用相同的名稱。 – Tony 2010-03-01 13:14:33
命名約定由其他人設定,所以我不能真正改變它。我讚賞你的理由,但我也有同樣的擔憂。 – ilitirit 2010-03-01 14:15:43
什麼是StatementHeader的實體?在現實世界中,具有相同的StatementHeaderID的語句是相互連接的,還是AccountID和StatementDate都是共享的?後者會使StatementHeader類似於帶有SatementHeaderID的日曆作爲僞裝日期... – wallenborn 2010-03-03 13:30:06