建模一对一关系
回答
这样做,使其即使在多个会话进行更新时也是正确和正确的,这并不容易。如果您尝试使用触发器,您会陷入混乱,而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. 一对一的关系建模
- 3. 建模多对多的一元关系和1:一元关系
- 4. 建模零或一对多关系
- 5. CoreData - 一对多建模关系以一对一形式出现
- 6. 创建一对多关系
- 7. 如何建模一个多一对多的关系,具有具有一对多的关系相关的轨道
- 8. R dataframe创建一对一的关系
- 9. 创建一对一的关系Flask-SQLAlchemy
- 10. EF一对一关系不会创建
- 11. 如何建立一对一的关系
- 12. 一对一关系
- 13. 一对一关系
- 14. 一对一关系
- 15. 一对一关系
- 16. 将两个一对多关系建模为一个
- 17. Python:在数据存储中建模一对一关系
- 18. 实体框架建模一个一对多的关系
- 19. 创建PostgreSQL表格+关系 - 带关系的问题 - 一对一
- 20. 建模数据库中的“一对一”关系与建模“继承”相同?
- 21. Laravel:一对多,许多对一个模型一对多关系
- 22. 建模多对多关系
- 23. Backbone.js:对belongs_to关系建模
- 24. 一对一或一对多关系模式
- 25. 创建一个多对多的关系,并给每个关系一个对象
- 26. Silverstripe一对一的关系
- 27. MYSQL一对一关系
- 28. codefirst一对一的关系
- 29. 一对一关系约束
- 30. EF:一对一关系
优秀点。 – JohnFx 2009-08-05 20:37:05
可延迟约束。 – cagcowboy 2009-08-05 21:23:05
用触发器很难做到。您需要取出表锁以使其在桌面上的多个同时事务下正常工作。所有的交易都必须排在对方之后,并且表现不佳。 – 2009-08-05 21:31:10