0

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

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

该数据库通过以下示例进行了非规范化

表 1 : FINProduct(ID (number), Description(varchar(5)), FINproductCode(varchar(10))...)

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

因此,在表 1 和表 2 之间没有关系,FINproductCode 列只是在表 1 中复制。

现在喝太早了,但我想我需要一个!

4

3 回答 3

2

我会非常谨慎地假设没有外键约束是对性能问题的合理回应。强制执行外键约束会产生开销(特别是在缺少适当索引的情况下),但您的应用程序不太可能比 Oracle 更有效地验证约束。所以问题实际上是您是否想要外键约束的小开销,或者几乎可以肯定您会将无效数据插入数据库。这不太可能是您想要做出的权衡 - 我还没有遇到一个愿意捕获不正确和难以理解的数据的业务用户,即使这样做比捕获正确数据要快一点.

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

于 2012-09-20T08:02:33.563 回答
0

这取决于您是否要仅出于文档目的添加 FK,还是要防止将来使用无效的 FK 值进行 INSERT/UPDATE。

如果您只想将它​​用于文档目的,我将使用 RELY NOVALIDATE 创建 FK 约束并在之后禁用它 - 否则,Oracle 将检查它是否有未来的 INSERTs / UPDATEs。

但是:除非您绝对需要,否则不要这样做!

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

于 2012-09-20T08:14:19.823 回答
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

使用“启用 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.

启用约束且数据正确

于 2012-09-20T11:14:33.283 回答