如何使用Oracle声明具有或条件的外键?
题
我有一个表(a),其主要键是表(b)或表(c)的外键。
create table A (
akey number,
txt varchar2(10)
);
create table B (
bkey number,
txt varchar2(10)
);
create table C (
ckey number,
txt varchar2(10)
);
我想要的是:
alter table A add constraint BorCkey foreign key (akey) references B(bkey)` or C(ckey);
这可能吗?
解决方案
不,在甲骨文中不可能。
您的选择通常是
- 在bkey引用b.bkey和ckey引用c.ckey并创建一个约束条件,确保在任何时间点都不零。
- 创建B&C具有外国关键的某种“组合的B&C”实体,并在参考该组合实体的钥匙中制作外键。
如果您想要一个约束,以确保确切的两个列之一为null,而一行均不为null
create table one_key(
col1 number,
col2 number,
check( nvl2(col1,1,0) + nvl2(col2,1,0) = 1 )
)
其他提示
外国钥匙限制是 一张外国桌子.
这意味着您需要在这种情况下使用两个Alter表语句来设置外国密钥以引用两个表。那里没有机会指定关系中的或 A.akey
两者都必须存在 B.bkey
和 C.ckey
同时. 。例如,如果 B.bkey
具有零值,但 C.ckey
不 - 然后 A.akey
永远不会有零值。外键在Oracle中是延迟的,但是所描述的行为是同时启用两个外键的行为 - 如果所有值不满足关系,则将无法启用约束。
您需要查看如何简化关系的需求,因此它不需要两个表即可完成这项工作。
听起来您有某种形式的亚型/超级型关系。一个典型的例子是“人”,它可能是“客户”或“供应商”。
您可能在人表中拥有person_id的唯一键以及person_type('cust'或'supp')的属性。如果您在person_id上创建主键,则Person_Type可以在子类型表(供应商/客户)中引用该键。
然后,您对Person_ID添加了唯一的约束,以确保Person_ID的任何值必须是客户或供应商,而不是两者兼而有之,并检查子类型表上的约束,以便表中仅表示一种类型。
create table person
(person_id number,
person_type varchar2(4),
name varchar2(10),
constraint person_pk primary key (person_id, person_type),
constraint person_id_uk unique (person_id));
create table supplier
(supplier_id number,
supplier_type varchar2(4),
blah varchar2(10),
constraint supplier_pk primary key (supplier_id, supplier_type),
constraint supp_pers_fk foreign key (supplier_id, supplier_type)
REFERENCES person (person_id, person_type)
)
/
alter table supplier add constraint supp_type_ck check (supplier_type = 'SUPP');
它不是很漂亮,但是类型/子类型更像是对象概念,而不是关系概念。
我的解决方案受贾斯汀的启发:
CREATE OR REPLACE TRIGGER abc
BEFORE INSERT OR UPDATE ON a
FOR EACH ROW
DECLARE
v_testB NUMBER:= 0;
v_testC NUMBER:= 0;
BEGIN
SELECT
COUNT(bkey)
INTO
v_testB
FROM
b
WHERE
bkey = :new.aKey;
SELECT
COUNT(ckey)
INTO
v_testC
FROM
c
WHERE
ckey = :new.aKey;
IF ((v_testB + v_testC) <> 1) THEN
RAISE_APPLICATION_ERROR(-20002,'Foreign key to B or C missing.');
END IF;
END;
/
SHOW ERRORS TRIGGER abc
创建一个实体的观点,即工会表B&C,并将您的FK限制指向视图
不隶属于 StackOverflow