我有两张桌子:
MESSAGES ( ID(pk), SENDER )
RECIEVERS ( ID references MESSAGE(ID), RECIEVER, pk(ID, RECIEVER) )
这是交易:
邮件只能有一个发件人。的完成
消息可以有多个接收者,但接收者不能多次接收相同的消息。的完成
发件人无法向自己发送消息。 我该如何做这部分?
我试过了:
update table RECIEVERS add constraint "RECIEVERS_CK_SELF_SEND"
( RECIEVER not in
( select SENDER
from MESSAGES
where MESSAGE.ID=RECIEVER.ID));
在Oracle数据库10g XE上,但是我收到以下错误:
此处不允许进行子查询
答案 0 :(得分: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行,对吧?
物化视图的作用是在任何人对表messages
或receivers
提交DML操作时刷新自身。所以理论上,如果有人向自己插入消息,查询将返回bad_rows = 1
。但是,我还在物化视图中包含了一个约束,表示列bad_rows
唯一允许的值为0. Oracle不允许您提交任何给出其他值的事务。
因此,如果你查看第二对insert语句,你可以看到我设法在接收器中插入了错误的行,但是当我尝试提交时,Oracle会出现约束违规。