Oracle非唯一的部分外键

Oracle非唯一的部分外键,oracle,oracle11g,foreign-keys,triggers,Oracle,Oracle11g,Foreign Keys,Triggers,你好,互联网的古人 今天,我在使用Oracle外部复合密钥时遇到了一些问题。我有一个应用程序,有点大(你知道,5000多个表,诸如此类),我们将一些“静态”(实际上可以更改)数据存储到一些表集中。该数据通过数据库被许多表引用,因此其工作原理如下: TABLE StaticData ID(PK) Data 1 StaticData1 2 StaticData2 ... n StaticDataN TABLE TypicalTable ID(PK)

你好,互联网的古人

今天,我在使用Oracle外部复合密钥时遇到了一些问题。我有一个应用程序,有点大(你知道,5000多个表,诸如此类),我们将一些“静态”(实际上可以更改)数据存储到一些表集中。该数据通过数据库被许多表引用,因此其工作原理如下:

TABLE StaticData 
ID(PK)  Data    
1       StaticData1
2       StaticData2
...
n       StaticDataN

TABLE TypicalTable
ID(PK)  StaticDataID(FK to StaticData)  
1       1
2       1
3       7
4       2
...
n       n
在仙境中一切都很好

但是规范的一些更改,以及之后与客户的一些会议,我们的任务是准备好不同的数据“版本”,以便在某个时间到来时替换静态数据。最后一部分很简单,我们可以创建每天/每周检查日期和更改数据的作业,但我们必须维护数据的旧版本和新版本。。。在同一张桌子上。现在静态数据看起来像:

TABLE StaticData 
ID(PK)  Data            KickInDate(Also PK)
1       StaticData1.1       01/01/1900
1       StaticData1.2       10/07/2014
1       StaticData1.3       12/12/2015
2       StaticData2.1       01/01/1900
...
n       StaticDataN.1       01/01/1900
当然,所有的完整性参考资料都被删除了。当然,因为我不能在ID中设置唯一的约束,所以我不能保留外键

我在网上搜索了一个解决方案(限制较少的外键),大多数情况下,解决方案是在插入|更新|删除之前使用触发器检查

但这将是一项非常非常大的工作

所以我问,我还有其他解决办法吗? 有没有什么方法可以让Oracle引用另一个表的另一列,即使它不是唯一的?(它肯定不会为空)

谢谢你的建议:)

不,目标列必须是唯一的,这就是全部想法。但是,您可以将其他版本列从StaticData传播到TypicalTable:

CREATE TABLE StaticData (
   id           NUMBER, 
   version      NUMBER, 
   col1 ... coln, 
   PRIMARY KEY (id,version)
);

CREATE TABLE TypicalTable (
   StaticDataID NUMBER,
   version      NUMBER,
   colx ... coly,
   FOREIGN KEY (StaticDataID, version) REFERENCES StaticData(id, version)
);
Oracle中的主键可以有重复项。可以使用非唯一索引构建主键,并且可以通过使用
NOVALIDATE
创建约束来排除现有值。这是一个很少使用的功能,会让人困惑,而且不是一个干净的解决方案。但在现实世界中,有时数据不干净,没有时间寻找完美的解决方案

示例架构和数据。

create table staticData
(
    id number not null,
    data varchar2(100),
    constraint staticData_pk primary key (id)
);

create table typicalTable
(
    id number not null,
    staticDataID number,
    constraint typicalTable_pk primary key (id),
    constraint typicalTable_fk foreign key (staticDataID)
        references staticData(id)
);

insert into staticData values (1, 'StaticData1');
insert into staticData values (2, 'StaticData2');

insert into typicalTable values(1, 1);
insert into typicalTable values(2, 1);
--Drop constraints.
alter table typicalTable drop constraint typicalTable_fk;
alter table staticData drop constraint staticData_pk;

--Add semi-duplicate data.
insert into staticData values (1, 'StaticData1.2');

--Use a non-unique index to build a NOVALIDATE primary key.
create index staticData_pk on staticData(id);
alter table staticData add constraint staticData_pk primary key (id) novalidate;
alter table typicalTable add constraint typicalTable_fk foreign key(staticDataID)
    references staticData(id);
删除约束、添加重复数据和重新启用约束的过程。

create table staticData
(
    id number not null,
    data varchar2(100),
    constraint staticData_pk primary key (id)
);

create table typicalTable
(
    id number not null,
    staticDataID number,
    constraint typicalTable_pk primary key (id),
    constraint typicalTable_fk foreign key (staticDataID)
        references staticData(id)
);

insert into staticData values (1, 'StaticData1');
insert into staticData values (2, 'StaticData2');

insert into typicalTable values(1, 1);
insert into typicalTable values(2, 1);
--Drop constraints.
alter table typicalTable drop constraint typicalTable_fk;
alter table staticData drop constraint staticData_pk;

--Add semi-duplicate data.
insert into staticData values (1, 'StaticData1.2');

--Use a non-unique index to build a NOVALIDATE primary key.
create index staticData_pk on staticData(id);
alter table staticData add constraint staticData_pk primary key (id) novalidate;
alter table typicalTable add constraint typicalTable_fk foreign key(staticDataID)
    references staticData(id);

+1这是正确的方法。我的答案通常是错误的,但更有趣。:)谢谢,我会这样做的,但是大多数表都有多个FK到不同的静态数据(更像是五个或六个),在每个典型表中添加四个或五个列来添加版本是我们无法想象的。无论如何,谢谢你给出了正确的答案!:)从没听说过诺瓦利达。明天我将测试这个,并标记为正确,如果它的工作,谢谢!