Oracle数据库具有很少的外键约束

时间:2012-09-20 07:50:16

标签: oracle foreign-key-relationship

我刚刚开始一个新项目,我遇到了一个只有3个外键约束的生产应用程序Oracle 10g数据库。我不习惯看到没有外键约束的数据库。我猜测可能存在一些不使用FK的性能/并发性考虑因素。原因是在逻辑数据库模式中,架构师已指定所有关系,但这些关系未在数据库中实现为外键约束。

问题:我读到我可以使用RELY NOVALIDATE定义一个不会影响性能的外键约束。是否值得在此数据库上定义RELY FK约束,以便可以很容易地看到这种关系?这个应用程序不是用ORM构建的,没有外键真的值得吗?

数据库使用以下示例进行非规范化处理

表1:FINProduct(ID(编号),描述(varchar(5)),FINproductCode(varchar(10))...)

表2:FINProductCode(ID(数字,FINproductCode(varchar(10)),LastUpdated(datetime)...)

因此,不是在表1和表2之间建立关系,而是在表1中复制FINproductCode列。

现在喝酒还为时过早,但我想我需要一个!

3 个答案:

答案 0 :(得分:2)

我会非常谨慎地认为缺少外键约束是对性能问题的合理回应。实施外键约束会产生开销(特别是在缺少适当的索引的情况下),但是应用程序可以比Oracle更有效地验证约束。所以问题实际上是你是想要外键约束的小开销还是几乎可以确定你会将无效数据插入到数据库中。这是一个你想要做出的权衡 - 我还没有遇到一个能够捕获错误和难以理解的数据的业务用户,即使这样做比捕获正确的数据要快一些

除非有更多的背景,否则我倾向于创建所有缺少的外键约束。可以创建RELY NOVALIDATE约束,但它会破坏外键约束的主要好处 - 防止无效数据首先进入数据库。

答案 1 :(得分:0)

这取决于您是仅为文档目的添加FK还是要阻止将来的INSERT / UPDATE具有无效的FK值。

如果您只想将其用于文档目的,我将使用RELY NOVALIDATE创建FK约束并在之后禁用它 - 否则,Oracle将检查它以用于将来的INSERT / UPDATE。

然而:除非你绝对需要,否则不要这样做!

我同意Justin Cave的观点:在大多数情况下,您应该添加“普通”FK约束 - 这样,您就可以确保现有数据正确无误。

答案 2 :(得分:0)

我会尝试创建约束并将违规报告到异常表中。修复数据并启用约束。

创建一些测试数据

create table parent (pk integer
                    ,data varchar2(1)
                    ,CONSTRAINT PARENT_PK PRIMARY KEY (PK)  ENABLE );

create table child (pk integer
                    ,pk_parent integer
                    ,data varchar2(1)
                    ,CONSTRAINT CHILD_PK PRIMARY KEY (PK)  ENABLE );

insert into parent values (1,'a');
insert into parent values (2,'b');


insert into child values (1,1,'a');
insert into child values (2,2,'b');
insert into child values (3,3,'c');

创建外键约束:

alter table child add constraint fk_parent foreign key(pk_parent) references parent(pk);

SQL Error: ORA-02298: Kan (ROB.FK_PARENT) niet valideren - bovenliggende sleutels zijn niet gevonden.
02298. 00000 - "cannot validate (%s.%s) - parent keys not found"
*Cause:    an alter table validating constraint failed because the table has
           child records.
*Action:   Obvious

使用'enable novalidate'选项

创建外键
alter table child add constraint fk_parent foreign key(pk_parent) references parent(pk) enable novalidate;
table CHILD altered.

insert into child values (4,4,'c');

SQL Error: ORA-02291: Integriteitsbeperking (ROB.FK_PARENT) is geschonden - bovenliggende sleutel is niet gevonden.
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause:    A foreign key value has no matching primary key value.
*Action:   Delete the foreign key or add a matching primary key.

不能插入违反FK的新数据。

现在让我们修复表中已违反FK约束的数据

创建例外表并尝试启用约束:

create table exceptions(row_id rowid,
                        owner varchar2(30),
                        table_name varchar2(30),
                        constraint varchar2(30));


ALTER TABLE child ENABLE constraint fk_parent  EXCEPTIONS INTO EXCEPTIONS; 


Error report:
SQL Error: ORA-02298: Kan (ROB.FK_PARENT) niet valideren - bovenliggende sleutels zijn niet gevonden.
02298. 00000 - "cannot validate (%s.%s) - parent keys not found"
*Cause:    an alter table validating constraint failed because the table has
           child records.
*Action:   Obvious

检查例外表中的问题:

select * from exceptions;

ROW_ID OWNER                          TABLE_NAME                     CONSTRAINT                   
------ ------------------------------ ------------------------------ ------------------------------
AABA78 ROB                            CHILD                          FK_PARENT                      
AAFAAA                                                                                              
Ow9AAC 

select  * from child where rowid = 'AABA78AAFAAAOw9AAC';

解决问题

delete from child where pk = 3;

1 rows deleted.

ALTER TABLE child ENABLE constraint fk_parent  EXCEPTIONS INTO EXCEPTIONS;

table CHILD altered.

启用约束并且数据正确