2014-03-06 68 views
1

添加約束我有2個表:使用子查詢其他表

  1. MESSAGES (ID(pk), SENDER)

  2. RECIEVERS (ID references MESSAGE(ID), RECIEVER, pk(ID, RECIEVER))

這裏的交易:

  1. A M消息只能有一個發件人。 DONE

  2. 消息可以有多個接收者,但接收者不能多次接收同一消息。 DONE

  3. 發件人不能發送消息給自己。 我該如何做這部分?

我嘗試這樣做:

update table RECIEVERS add constraint "RECIEVERS_CK_SELF_SEND" 
(RECIEVER not in 
    (select SENDER 
     from MESSAGES 
     where MESSAGE.ID=RECIEVER.ID)); 

在Oracle數據庫10g企業版,但我收到以下錯誤:

SUB QUERY NOT ALLOWED HERE

+1

請參閱http:// stackoverflow。com/questions/16045505/can-a-check-constraint-related-to-another-table-oracle –

+1

請注意,在英語中,單詞拼寫爲rec ** ei ** vers(經驗法則* '** i **'在'** e **'之前,除了'** c **'*「在小孩被帶入我身後之後)。 – eggyal

+0

@eggyal - 當然'規則'比規則有更多的例外 - 事實! – Strawberry

回答

0

一個工作周圍,你可以做的是建立一個包含標識「壞行」的查詢的物化視圖。

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行,對吧? 物化視圖的作用是在任何人對錶messagesreceivers提交DML操作時自行刷新。因此理論上,如果有人向自己插入消息,則查詢將返回bad_rows = 1。但是,我還在物化視圖中包含了一個約束,表示列bad_rows的唯一允許值爲0. Oracle不會讓您提交任何提供其他值的事務。

所以,如果你看看第二對插入語句,你可以看到我設法在接收者中插入了錯誤的行,但是當我嘗試提交時,Oracle給出了約束違規。

+0

是的,它會解決問題,但不幸的是這太重了 – smnbbrv

+0

請解釋你在這裏試圖做什麼,我是一個你認識的新手。 –

+0

感謝您的幫助,我現在明白了。您能否提出一些閱讀材料來學習關於數據庫的獨特之處,如您在此使用的MATERIALIZED VIEW。 –