我有一些问题与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
仙境里一切都很好。
但是一些规格的变化,以及之后与客户的一些会议,我们的任务是准备不同版本的数据,以便在某个时间到来时取代静态数据。最后一部分很简单,我们可以创建每天/每周检查日期并更改数据的作业,但我们必须维护旧版本和新版本的数据……在同一张桌子上。现在StaticData看起来像:
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中添加UNIQUE约束,所以我不能保留外键。
我已经在网上搜索了这个(限制较少的外键)的解决方案,大多数时候的解决方案是使用触发器检查BEFORE INSERT|UPDATE|DELETE
但是这将是一项非常非常非常大的工作。
所以我问,我有其他的解决方案吗?有没有办法告诉Oracle引用另一个表的另一列,即使认为不是唯一的?(它肯定不是NULL)。
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);
不,目标列必须是唯一的,这就是整个想法。但是,您可以将一个附加的版本列从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)
);