我有如下所述的要求:
table1
------------------------
A B C D E
------------------------
1 2 * P Q
1 2 A Q P
1 3 B W U
-----------------------
列A B C
是primary key
table1
table2
------------------------
A B C
------------------------
1 2 1
1 2 2
1 2 A
------------------------
列A B C
需要在table2上实现为复合外键
对于表1中的列A B C
,唯一的例外是,如果父表(表1)中的列C
为*
那么任何值都可以显示在column C
和column A
提供的子表(table2)的column B
中
两个表都相同。
我们正在寻找具有最小触发器的实现。目前,由于这种奇怪的要求,我们无法创建外键。
请建议任何替代方法,让我的一天:)
答案 0 :(得分:2)
我怀疑这是模型的问题。这两个表似乎代表了两种不同类型的东西,这就是为什么普通的FK约束不起作用的原因。
我认为你应该将两个表分成两个,例如:
table1_noC
------------------------
A B D E
------------------------
1 2 P Q
table2_noC (with a FK to table1_noC)
------------------------
A B C
------------------------
1 2 1
1 2 2
------------------------
table1_C
------------------------
A B C D E
------------------------
1 2 A Q P
1 3 B W U
-----------------------
table2_C (with a FK to table1_C)
------------------------
A B C
------------------------
1 2 A
------------------------
然后,您可以使用结合table1_noC
+ table1_C
的视图和结合table2_noC
+ table2_C
的其他视图重新创建原始设计。如果有必要,您甚至可以向视图添加“而不是”触发器,以将视图上的DML转换为基础表上的必要DML。
答案 1 :(得分:2)
无需任何新结构即可解决此问题。 只是在子表中引入new_column(NEW_C)(table2) 并在外键约束中使用此列而不是“列C”。 步骤如下:
1> alter table2 add (new_c varchar2(1));
2 - update table2 set new_c= c
;
3>在FK中使用新引入的列NEW_C而不是colum C
alter table table2
add constraint
fk_ref_table1 FOREIGN KEY (A,B,**NEW_C**)
references table1 (A,B,C);
4>在子表上创建一个简单的插入/更新触发器以维护新列NEW_C
。
CREATE OR REPLACE maintain_new_c
BEFORE
INSERT OR UPDATE
ON TABLE2 REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
v_count pls_integer;
BEGIN
SELECT COUNT(1)
INTO v_count
FROM table1 t1
WHERE t1.c='*'
AND t1.a= :NEW.a
AND t1.b= :NEW.b;
IF v_count=0 THEN
new_c := :NEW.c ;
ELSE
new_c := '*';
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR..........
END;
替代方法是在子表上引入新的虚拟列(oracle 11g), 使用确定性pl / sql函数 派生这个虚拟coulmn,然后创建外键约束 使用虚拟列。
但我更喜欢基于触发器的方法作为父表上的任何udate / delete操作 因为每次都需要派生和检查虚拟列,所以会受到影响。