2

我正在看着這個數據模型,我想出來,感覺不舒服。我已經改變了實體名稱,所以它(希望)更有意義。無論如何,你將如何建模以下內容?如何建立與RDBMS的多重繼承關係?

我有3個實體。政府客戶,私人客戶,公衆客戶。私人和公共客戶都是CorporateCustomers。公司和政府客戶是賬戶。所有賬戶共享相同的密鑰空間(因此,如果PrivateCustomer的PK值爲1,公共或政府客戶的PK值不應該爲1)。 CorporateCustomers有一些1:M的關係,GovernmentCustomer沒有。 PublicCustomers有一些PrivateCustomers不支持的1:M關係。

繼承:

Account 
    CorporateCustomer 
    PrivateCustomer 
    PublicCustomer 
    GovernmentCustomer 

現在我的模型有5桌。 「帳戶」表是這個層次結構的根,每個子表的PK對其父母的PK都是FK。所以所有的表都有相同的PK。

所以是的,你會如何模型?我希望這裏有些東西沒有大錯特錯:)。

編輯:

另外: - 我想的DB要照顧裁判完整性不應用程序。 - CorporateCustomer不可能是私人或公共客戶。它的抽象。

回答

0

除非在不同類型的cusomter中跟蹤的屬性存在顯着差異,否則我只有一個名爲Account的表,其中包含一些CustomerType字段。你可以通過具有FK到AccountID的細節表來表達1:m關係。

編輯:現代數據庫可以添加超出FK參照完整性的數據完整性規則。例如,對於SQL Server,您可以添加CHECK Constraints以強制AccountType成爲GovernmentCustomer,用於某些明細表的主數據。它可能看起來像這樣:

CREATE FUNCTION EnforceGovernmentCustomer(@AccountID int) 
RETURNS bit 
AS 
BEGIN 
    DECLARE @retval bit 
    SELECT @retval = 0 
    SELECT @retval = 1 
    FROM Account 
    WHERE AccountID = @AccountID AND AccountType = 3 

    RETURN @retval 
END; 
GO 
ALTER TABLE GovernmentCustomerDetail 
ADD CONSTRAINT chkGovernmentCustomer CHECK (dbo.EnforceGovernmentCustomer(AccountID) = 1); 
GO 
+0

如果我正確理解這種方法,我的應用程序將不得不管理一些數據完整性。例如,對於具有政府客戶類型的賬戶可能有許多財務報表。只有公司客戶應該有這種關係。我對嗎?我更新了這個問題,以使ref的完整性更清晰。 – 2009-06-19 12:51:48

+0

@TheDeeno,我更新了答案以反映您的意見。 – 2009-06-19 14:41:25

+0

@ eed3si9n謝謝!我將不得不看看是否可以考慮自定義檢查約束進行建模。所以你一般反對5桌分享PK想法? – 2009-06-19 20:10:15

0

我想你應該只有一個帳戶和一個客戶表,以及一個CustomerRelationship表。不同類型的客戶可以通過某種類型的代碼進行區分,並且可以使用CustomerRelationship表維護關係。

1

的一種方法是:

ACCOUNTS -> ACCOUNT_CUSTOMERS <- CUSTOMERS 

讓客戶有一個CUSTOMER_TYPE列,它是類型的企業(C),私人(P),公共(Z),政府(G)。由於所有公共和pivate客戶也是企業,如果你需要讓所有的企業客戶,你可以這樣做:

SELECT * 
    FROM ACCOUNTS 
    , ACCOUNT_CUSTOMERS 
    , CUSTOMERS 
WHERE ACCOUNTS.ID = ACCOUNT_CUSTOMERS.ACCT_ID 
    AND CUSTOMERS.ID = ACCOUNT_CUSTOMERS.CUST_ID 
    AND CUSTOMERS.CUSTOMER_TYPE in ('C','P','Z') 

我用ORACLE語法,但我認爲你的想法。

In response to your edit: 

這聽起來像你只有兩種類型的客戶。公司和政府。這更容易。我會在CUSTOMERS上使用一個名爲PUBLIC_IND的布爾指示符,當false是私有的,或者另一種類型如可能是Private(P),Public(Z)或None(N)的ENTITY_TYPE時。然後,如果你想獲得的所有公共公司客戶用戶:

SELECT * 
     FROM ACCOUNTS 
     , ACCOUNT_CUSTOMERS 
     , CUSTOMERS 
    WHERE ACCOUNTS.ID = ACCOUNT_CUSTOMERS.ACCT_ID 
     AND CUSTOMERS.ID = ACCOUNT_CUSTOMERS.CUST_ID 
     AND CUSTOMERS.CUSTOMER_TYPE in ('C') 
     AND CUSTOMERS.ENTITY_TYPE = 'Z' 
0

我,如果不同類型客戶的是一個類似於customerType場就足夠了別人同意。

表示,也許只是企業客戶共享表格,但政府客戶不同,他們需要在他們自己的表中定義。如果這是有保證的,一個設計可以幫助你實施PK約束,那就是擁有一個MasterAccount表,它可以通過id(PK約束)引用所有客戶,並且在下一個級別上引用它們的類型層次結構(公司或政府)。

您仍然需要映射1- *關係,您可以使用另一個表格 - 關係表和帳戶關係映射表。

0

在您承諾將每個類放在同一個表中之前,我會查看它們所涉及的關係 - 而不是屬性。如果記錄類型爲'X',那麼將某些字段留空即可,但試圖建立僅適用於表中某些記錄的關係是非常難以操作的。

如果類與其他實體的關係完全相同,那麼您可以將它們全部填入一張表中,而沒有真正的缺點。

0

我知道這個問題很舊,但由於它還沒有被接受的答案,所以我有幾個想法。

一種可能性是使用ORDBMS功能 - 換句話說,使用表繼承。在PostgreSQL你可能會喜歡這個型號:

(請參閱有關PostgreSQL的繼承http://www.postgresql.org/docs/9.3/static/ddl-inherit.html的文檔)

CREATE TABLE account 
(
    account_id INT, 
    PRIMARY KEY(account_id) 
); 

CREATE TABLE corporate_customer 
(
    company_name VARCHAR(32), 
    country_code CHAR(2), 
    PRIMARY KEY(company_name) 
) INHERITS(account); 

CREATE TABLE private_corp_customer 
(
    private_comp_id INT, 
    company_owner VARCHAR(32), 
    PRIMARY KEY(private_comp_int) 
) INHERITS(corporate_customer); 

CREATE TABLE public_corp_customer 
(
    stock_ticker VARCHAR(6), 
    PRIMARY KEY(stock_ticker) 
) INHERITS(corporate_customer); 

CREATE TABLE government_customer 
(
    dept_nbr INT, 
    country CHAR(2), 
    PRIMARY KEY(dept_nbr) 
) INHERITS(account); 

不同的DBMS廠商會以不同的方式實現這一點。在PostgreSQL中,這裏有描述一些重要的注意事項:

http://ledgersmbdev.blogspot.com/2012/08/postgresql-or-modelling-part-3-table.html

特別要注意關於未繼承主鍵和外鍵的一部分。

如果您不喜歡數據庫管理系統的限制或者使用的是不具備對象關係特性的數據庫管理系統,那麼另一種選擇是使用上述文章中提出的替代方案並使用輔助鍵。這將建模如下:

CREATE TABLE account 
(
    account_id INT, 
    account_type INT NOT NULL, 
    PRIMARY KEY(account_id), 
    UNIQUE (account_id, account_type) 
); 

CREATE TABLE corporate_customer 
(
    account_id INT, 
    account_type INT NOT NULL CHECK(account_type IN (1,2)), 
    company_name VARCHAR(32), 
    country_code CHAR(2), 
    PRIMARY KEY(account_id, account_type), 
    FOREIGN KEY(account_id, account_type) REFERENCES account(account_id, account_type), 
    UNIQUE(account_id, account_type, company_name) 
); 

CREATE TABLE private_corp_customer 
(
    account_id INT, 
    account_type INT NOT NULL CHECK(account_type = 1), 
    company_name VARCHAR(32), 
    company_owner VARCHAR(32), 
    PRIMARY KEY(account_id, account_type, company_name), 
    FOREIGN KEY(account_id, account_type, company_name) REFERENCES corporate_customer (account_id, account_type, company_name) 
); 

CREATE TABLE public_corp_customer 
(
    account_id INT, 
    account_type INT NOT NULL CHECK (account_type = 2), 
    company_name VARCHAR(32), 
    stock_ticker CHAR(6), 
    PRIMARY KEY(account_id, account_type, company_name), 
    FOREIGN KEY(account_id, account_type, company_name) 
    REFERENCES corporate_customer (account_id, account_type, company_name) 
) INHERITS(corporate_customer); 

CREATE TABLE government_customer 
(
    account_id INT, 
    account_type INT NOT NULL CHECK(account_type = 3), 
    dept_nbr INT, 
    country_code CHAR(2), 
    PRIMARY KEY(account_id, account_type), 
    FOREIGN KEY(account_id, account_type) REFERENCES account(account_id, account_type), 
    UNIQUE(account_id, account_type, dept_nbr) 
); 

上述設計也有一些重要的限制(這也在上面的文章中描述)。首先,雖然不應該有一個不是私人,公共或政府客戶的賬戶,但可以這樣做;你可以只擁有帳戶,既不公開也不私密的公司帳戶......這成爲一個噩夢來維護。約束條件也會損害性能,並且您會注意到子實體中存在數據重複以及公司子實體(country_code)中缺少信息。

您選擇哪些限制將取決於您的DBMS供應商以及您想要管理多少頭痛。