建模一對一關係
回答
這樣做,使其即使在多個會話進行更新時也是正確和正確的,這並不容易。如果您嘗試使用觸發器,您會陷入混亂,而Oracle的聲明性約束不足以表達這一點。
這是可以做到如下: -
- 創建兩個父和子表物化視圖日誌
- 創建物化加入認爲,把它們組合在一起,並計算分組的兒童人數由父母。這必須是REFRESH FAST ON COMMIT
- 將約束的物化加入認爲,兒童記錄的計數必須等於「N」(數據庫常數)
然後,您可以做一系列的插入/更新/刪除語句。當你提交時,物化視圖會刷新,如果不滿足條件,那麼你會在那個時候遇到違反約束的錯誤。
訣竅的一個好處是隻包含約束失敗到物化視圖的行(HAVING count(ChildId)<> 5),所以您不會浪費任何存儲空間。
我看不出如何。這是一個古老的問題,「先來,雞還是雞蛋?」。當沒有孩子添加時,如何約束父母,以及如何在沒有父母的情況下添加孩子?
您可以創建一個新表,名爲類似於「ValidParents」的表,該表只包含具有N個子級的父ID,並使其與觸發器保持同步。
這可能不是你想要的,但我確實有一種方法可以做類似的事情。
通常安排一個一對多的是這樣的:
Primary Table:
primary_id (PK)
primary_stuff
Secondary Table:
secondary_id (PK)
primary_id (FK)
secondary_stuff
的替代,來模擬一個嚴格的一對之一將是:
Primary Table:
primary_id (PK)
secondary_id (FK, non-null)
primary_stuff
Secondary Table:
secondary_id (PK)
secondary_stuff
這可能是有點奇怪,但它有效。當存在一對一一對一的情況下,這種變化可能會很有用,例如爲客戶提供多個地址,但只有一個賬單地址。
你需要插入孤兒行插入父行 – 2009-08-05 20:53:52
這是正確的,這就是爲什麼插入應在交易之前。 – 2009-08-05 21:00:05
基於earler「雞+雞蛋」的觀點,你可以創建可延期的約束,直到提交時間才能驗證......這些可能有幫助嗎?
例如
ALTER TABLE AGREEMENTS ADD CONSTRAINT name FOREIGN KEY (column) REFERENCES table (column) DEFERRABLE INITIALLY DEFERRED;
雞和雞蛋問題的另一種解決方案是使用INSERT ALL。因爲它是一個單一的聲明,它消除了對可延遲的外鍵約束的需要。它還提供了插入確切數量的相關行的機制。其他約束會阻止插入其他行。但是我們需要一個帶有外鍵的輔助表來防止意外刪除感興趣的行。
在此示例中,n = 3。
SQL> create table parent
2 (pk_col number not null
3 , col1 varchar2(20)
4 , constraint par_pk primary key (pk_col)
5 )
6/
Table created.
SQL>
SQL> create table child
2 (pk_col number not null
3 , seqno number(1,0) not null
4 , col2 date
5 , constraint ch_pk primary key
6 (pk_col, seqno)
7 , constraint ch_par_fk foreign key
8 (pk_col) references parent (pk_col)
9 , constraint ch_ck check (seqno between 1 and 3)
10 )
11/
Table created.
SQL>
SQL> create table child_lock
2 (pk_col_1 number not null
3 , seqno_1 number(1,0) not null
4 , pk_col_2 number not null
5 , seqno_2 number(1,0) not null
6 , pk_col_3 number not null
7 , seqno_3 number(1,0) not null
8 , constraint chlk_pk primary key
9 (pk_col_1, seqno_1, pk_col_2, seqno_2, pk_col_3, seqno_3)
10 , constraint chlk_par_1_fk foreign key
11 (pk_col_1, seqno_1) references child (pk_col, seqno)
12 , constraint chlk_par_2_fk foreign key
13 (pk_col_2, seqno_2) references child (pk_col, seqno)
14 , constraint chlk_par_3_fk foreign key
15 (pk_col_3, seqno_3) references child (pk_col, seqno)
16 )
17/
Table created.
SQL>
SQL> insert all
2 into parent values (pk_val, val_1)
3 into child values (pk_val, 1, sysdate)
4 into child values (pk_val, 2, sysdate+1)
5 into child values (pk_val, 3, sysdate+2)
6 into child_lock values (pk_val, 1, pk_val, 2, pk_val, 3)
7 select 999 as pk_val
8 , 'APPLE PIE' as val_1
9 from dual
10/
5 rows created.
SQL>
SQL> insert into child values (999, 4, sysdate+4)
2/
insert into child values (999, 4, sysdate+4)
*
ERROR at line 1:
ORA-02290: check constraint (APC.CH_CK) violated
SQL> insert into child values (999, 3, sysdate+4)
2/
insert into child values (999, 3, sysdate+4)
*
ERROR at line 1:
ORA-00001: unique constraint (APC.CH_PK) violated
SQL> insert into child values (999, 2.5, sysdate+4)
2/
insert into child values (999, 2.5, sysdate+4)
*
ERROR at line 1:
ORA-00001: unique constraint (APC.CH_PK) violated
SQL> delete from child
2/
delete from child
*
ERROR at line 1:
ORA-02292: integrity constraint (APC.CHLK_PAR_1_FK) violated - child record found
SQL>
我接受的解決方案是做作,並且還缺乏靈活性一件小事,但那麼是原來的要求。這也遠非防彈 - 從CHILD_LOCK刪除行,你可以刪除一個或多個CHILD記錄。
您可以創建表按正常的1:M的關係,那麼子表上有決定許多孩子如何存在父母,以及在唯一約束的檢查約束的計數列家長ID +數量列。例如:
CREATE TABLE Parent (PID NUMBER PRIMARY KEY);
CREATE TABLE Child (
PID NUMBER NOT NULL,
Count NUMBER(1) NOT NULL,
CONSTRAINT count_check CHECK (Count BETWEEN 1 AND 5),
CONSTRAINT parent_child_fk FOREIGN KEY (PID) REFERENCES Parent (PID),
CONSTRAINT count_unique UNIQUE (PID, Count));
這不能保證的唯一的事情是,每個父母至少有五個孩子;爲了解決這個問題,你可以創建一個物化視圖,如WW所示,或者在應用程序中創建一些額外的東西(例如「錯誤」報告)。
有一個替代的解決方案,以強制每個家長都恰好是0或N的兒童在使用只是檢查,外鍵和唯一性約束沒有物化視圖。爲此,必須給孩子編號並添加一個包含下一個兄弟姐妹編號的字段。這裏在PostgreSQL中,這適用於其他DBS一個n = 5的例子有可能適應型串行:
create table Tree(
id serial,
parent_id integer not null references Tree(id),
child_nr integer check(child_nr between 1 and 5),
next_sibling_nr integer,
unique (parent_id, child_nr),
check(next_sibling_nr in (child_nr+1, child_nr-4)),
check(((parent_id is null) and (child_nr is null) and
(next_sibling_nr is null)) or ((parent_id is not null)
and (child_nr is not null) and (next_sibling_nr is not null))),
foreign key (parent_id, next_sibling_nr) references Tree(parent_id, child_nr),
primary key (id)
);
最後(長)檢查約束確保領域PARENT_ID,child_nr和next_sibling_nr是全部爲空或全部不爲空。唯一性約束和對child_nr字段的檢查注意父母最多有5個孩子。對(parent_id,next_sibling_nr)上的其他檢查約束和外鍵約束確保不少於5個子項。
與命令插入根與自動生成的ID爲1後
insert into Tree (parent_id)
values (null);
一個可以包總是添加的5小孩:
insert into Tree (parent_id, child_nr, next_sibling_nr)
values (1, 1, 2),
(1, 2, 3),
(1, 3, 4),
(1, 4, 5),
(1, 5, 1);
將該溶液從答案衍生的類似我問了幾個星期的問題ago。
我剛纔看到其他人瞭解父母和孩子要在不同的桌子上,而我認爲他們在同一張桌子上。我的答案適應兩張表並不難。 – 2009-08-07 08:17:56
- 1. 一對一關係建模
- 2. 建模多對多的一元關係和1:一元關係
- 3. 建模零或一對多關係
- 4. CoreData - 一對多建模關係以一對一形式出現
- 5. 如何建模一個多一對多的關係,具有具有一對多的關係相關的軌道
- 6. EF一對一關係不會創建
- 7. R dataframe創建一對一的關係
- 8. 創建一對一的關係Flask-SQLAlchemy
- 9. 一對一關係
- 10. 一對一關係
- 11. 將兩個一對多關係建模爲一個
- 12. 實體框架建模一個一對多的關係
- 13. 創建PostgreSQL表格+關係 - 帶關係的問題 - 一對一
- 14. 建模數據庫中的「一對一」關係與建模「繼承」相同?
- 15. Laravel:一對多,許多對一個模型一對多關係
- 16. Backbone.js:對belongs_to關係建模
- 17. DBMS一對一關係
- 18. 一對一關係約束
- 19. Netlogo一對一關係
- 20. 選擇一對一關係
- 21. 休眠一對一關係
- 22. Silverstripe一對一的關係
- 23. EF7一對一的關係
- 24. Spring JDBC一對一關係
- 25. CoreData一對一關係
- 26. 一對一關係(1:1)
- 27. NHibernate - 一對一的關係
- 28. 單向一對一關係
- 29. MYSQL一對一關係
- 30. 一對一關係還是一對多?
優秀點。 – JohnFx 2009-08-05 20:37:05
可延遲約束。 – cagcowboy 2009-08-05 21:23:05
用觸發器很難做到。您需要取出表鎖以使其在桌面上的多個同時事務下正常工作。所有的交易都必須排在對方之後,並且表現不佳。 – 2009-08-05 21:31:10