一個工作周圍,你可以做的是建立一個包含標識「壞行」的查詢的物化視圖。
create table messages(
message_id number not null
,sender_id varchar2(20) not null
,primary key(message_id)
);
create table receivers(
message_id number not null
,receiver_id varchar2(20) not null
,primary key(message_id,receiver_id)
,foreign key(message_id) references messages(message_id)
);
create materialized view log
on receivers with primary key, rowid including new values;
create materialized view log
on messages with primary key, rowid (sender_id) including new values;
create materialized view mv
refresh fast on commit
as
select count(*) as bad_rows
from messages m
join receivers r using(message_id)
where m.sender_id = r.receiver_id;
alter materialized view mv
add constraint dont_send_to_self check(bad_rows = 0);
現在,讓我們嘗試插入一些行:
SQL> insert into messages(message_id, sender_id) values(1, 'Ronnie');
1 row created.
SQL> insert into receivers(message_id, receiver_id) values(1, 'Mayank Sharma');
1 row created.
SQL> commit;
Commit complete.
這很順利。現在,讓我們將消息發送給自己:
SQL> insert into messages(message_id, sender_id) values(2, 'Ronnie');
1 row created.
SQL> insert into receivers(message_id, receiver_id) values(2, 'Ronnie');
1 row created.
SQL> commit;
commit
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-02290: check constraint (RNBN.DONT_SEND_TO_SELF) violated
編輯,更解釋: 好吧,這個查詢(在物化視圖的定義),識別和計算所有正在發送給自己的消息。也就是說,所有行都是違反的規則。
select count(*) as bad_rows
from messages m
join receivers r using(message_id)
where m.sender_id = r.receiver_id;
所以查詢應該一直返回0行,對吧? 物化視圖的作用是在任何人對錶messages
或receivers
提交DML操作時自行刷新。因此理論上,如果有人向自己插入消息,則查詢將返回bad_rows = 1
。但是,我還在物化視圖中包含了一個約束,表示列bad_rows
的唯一允許值爲0. Oracle不會讓您提交任何提供其他值的事務。
所以,如果你看看第二對插入語句,你可以看到我設法在接收者中插入了錯誤的行,但是當我嘗試提交時,Oracle給出了約束違規。
請參閱http:// stackoverflow。com/questions/16045505/can-a-check-constraint-related-to-another-table-oracle –
請注意,在英語中,單詞拼寫爲rec ** ei ** vers(經驗法則* '** i **'在'** e **'之前,除了'** c **'*「在小孩被帶入我身後之後)。 – eggyal
@eggyal - 當然'規則'比規則有更多的例外 - 事實! – Strawberry