2017-04-14 69 views
0

我剛剛開始學習數據庫設計,我正在使用Oracle 11G和SQL Developer。如何確保無關表格之間的完整性?

我有一個DB這3個業務規則:

  • 每個人員必須在一個註冊只有一個保險公司。每個保險公司可以註冊一個或多個官員
  • 每個保險公司必須提供至少五種不同類型的保險類型。每種保險類型最多可由4家保險公司提供,或根本沒有提供
  • 每種保險類型可由一個或多個官員訂購。每個官員可以訂閱最多五個由同一家公司提供的不同保險箱。

。 。 。

到目前爲止,這麼好,我想出了五個表(INS_COY,OFFR,INS_TYPE,PROVIDE,和訂閱)。 PROVIDE和SUBSCRIBE是作爲組合表而來的,因爲INS_COY和INS_TYPE之間的關係,以及OFFR和INS_TYPE都是M:M關係。

每個表中的PK和FK屬性是如下:

INS_COY TABLE
coy_id - PK

主任TABLE
offr_id - PK
coy_id - (FK參考INS_COY.coy_id))

INS_TYPE TABLE
TYPE_ID - PK

PROVIDE
coy_idTYPE_ID - (複合PK)
coy_id - (FK引用COY.coy_id)
type_id - (FK引用ins_type.type_id)

SUBSCRIBE
naf_noTYPE_ID - (複合PK)
naf_no - (FK引用offr.offr_id)
TYPE_ID(FK參考ins_type.type_id)



表已成功創建,並插入了示例數據。

所以,問題是 - 在SUBSCRIBE TABLE上,我如何確保TYPE_ID附加到OFFR_ID的完整性是由註冊的COY提供的INS_TYPE?

sample data tables

即...從表格中,「主任4250」被登記在「忸怩1」,「靦腆1」不提供「ins_type 13」,但是,因爲沒有約束爲了檢查這個,「訂閱者1」訂閱了訂閱表上的「ins_type 13」。

回答

1

可以使用控制冗餘和複合FK約束做到這一點:

CREATE TABLE offr (
    offr_id INT NOT NULL, 
    coy_id INT NOT NULL, 
    PRIMARY KEY (offr_id), 
    FOREIGN KEY (coy_id) REFERENCES ins_coy (coy_id), 
    UNIQUE KEY (offr_id, coy_id) 
); 

我加了一個複合唯一鍵(offr_id,coy_id),以支持在subscribe表的複合鍵約束。

CREATE TABLE provide (
    coy_id INT NOT NULL, 
    type_id INT NOT NULL, 
    PRIMARY KEY (coy_id, type_id), 
    FOREIGN KEY (coy_id) REFERENCES ins_coy (coy_id) 
); 

此處的複合主鍵非常適用於subscribe表上的複合FK約束。

CREATE TABLE subscribe (
    naf_no INT NOT NULL, 
    coy_id INT NOT NULL, 
    type_id INT NOT NULL, 
    PRIMARY KEY (naf_no, type_id), 
    FOREIGN KEY (naf_no, coy_id) REFERENCES offr (offr_id, coy_id), 
    FOREIGN KEY (coy_id, type_id) REFERENCES provide (coy_id, type_id) 
); 

重疊複合FK約束將確保官員只能訂閱由他/她在就讀該公司提供保險。coy_id在邏輯上是多餘的,但對於要求完好而且也由於沒有更新異常的風險FK限制。

或者,你可以使用觸發器來檢查值通過內部相關聯接:

CREATE TRIGGER check_subscribe BEFORE INSERT OR UPDATE ON subscribe 
FOR EACH ROW 
WHEN NOT EXISTS (
    SELECT 1 
    FROM offr 
    INNER JOIN provide ON offr.coy_id = provide.coy_id 
    WHERE offr.offr_id = new.naf_no AND provide.type_id = new.type_id 
) 
RAISE_APPLICATION_ERROR (num => -20000, msg => 'Officers can only subscribe to types provided by their company'); 

免責聲明:我無法測試這個在SqlFiddle並沒有安裝了Oracle,但希望它」我會指出你在正確的方向。

+0

Thanks @reaanb。好的解決方案我想我更喜歡使用觸發器,因爲我儘可能地避免冗餘。但是,我從來沒有使用過觸發器。那麼,如何使用觸發器來實現這一點? – IGee

+0

我添加了一個例子,希望它有幫助。 – reaanb