我的表格是:
CREATE TABLE member
(
svn INTEGER,
campid INTEGER,
tentname VARCHAR(4),
CONSTRAINT member_fk_svn FOREIGN KEY (svn) REFERENCES people,
CONSTRAINT member_fk_campid FOREIGN KEY (campid) REFERENCES camp ON
DELETE CASCADE,
CONSTRAINT member_pk PRIMARY KEY (svn, campid),
CONSTRAINT member_fk_tentname FOREIGN KEY (tentname) REFERENCES tent,
CONSTRAINT check_teilnehmer_zelt CHECK (Count(zeltname) over (PARTITION BY (zeltname
AND lagerid)) )<= zelt.schlafplaetze
);
使用最后一个约束,我想检查分配给帐篷的成员数量多于其容量。
感谢你的帮助
答案 0 :(得分:2)
不,不是。来自文档:
如果应用于搜索条件,则必须始终返回相同的值 相同的价值观。因此,它不能包含以下任何内容:
* Dynamic parameters (?) * Date/Time Functions (CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP) * Subqueries * User Functions (such as USER, SESSION_USER, CURRENT_USER)
答案 1 :(得分:2)
这需要SQL 断言,Oracle目前(或任何DBMS)目前都不支持。但是,Oracle是considering adding support for these in the future(请提出这个想法!)
使用物化视图的解决方案
目前,您可以使用带有检查约束的物化视图(MV)来实现此约束 - I blogged about many years ago。在您的情况下,物化视图查询将类似于:
select t.tent_id
from tents t, members m
where m.tent_id = t.tent_id
group by t.tent_id
having sum(m.num_members) > t.capacity;
检查约束可以是:
check (t.tent_id is null)
对于物化视图返回的任何行,将违反检查约束,因此确保MV始终为空,即不存在容量超过的帐篷。
注意:
使用触发器的替代解决方案
另一种方法是将一个列total_members
添加到tents
表,并使用members
上的触发器来维持这一点。
create trigger members_trg
after insert or delete or update of num_members on members
for each row
declare
l_total_members tents.total_members%type;
begin
select total_members
into l_total_members
from tents
where tent_id = nvl(:new.tent_id,:old.tent_id)
for update of total_members;
if inserting then
l_total_members := l_total_members + :new.num_members;
elsif deleting then
l_total_members := l_total_members - :old.num_members;
elsif updating then
l_total_members := l_total_members - :old.num_members + :new.num_members;
end if;
update tents
set total_members = l_total_members
where tent_id = nvl(:new.tent_id,:old.tent_id);
end;
然后只需添加检查约束:
alter table tents add constraint tents_chk
check (total_members <= capacity);
通过维护tents
表中的总数,此解决方案可以序列化事务,从而避免在多用户环境中使用其他基于触发器的解决方案时数据损坏。