我目前正在做一个学校项目,我们需要在其中创建房地产管理公司的数据库。我们有一个OWNER
表,一个BUILDING
表和一个OWNERSHIP
表。
我想确保当我输入所有权权益百分比的值时,来自不同所有者的所有所有权权益之和不超过100%。目前我还不知道该怎么做。
CREATE TABLE Building (
buildingID NUMBER (10) NOT NULL PRIMARY KEY,
qtyUnits NUMBER (3) NOT NULL,
landValue NUMBER (15) NOT NULL,
purchasePrice NUMBER (15) NOT NULL
);
CREATE TABLE Owners (
ownerID NUMBER (5) NOT NULL PRIMARY KEY,
lastName VARCHAR2 (50) NOT NULL,
firstName VARCHAR2 (50) NOT NULL,
telephone VARCHAR2(50) NOT NULL,
email VARCHAR2(10) NOT NULL
);
CREATE TABLE Ownership (
ownerID NUMBER (5) NOT NULL,
buildingID NUMBER (5) NOT NULL,
ownershipStake NUMBER (5,2) NOT NULL,
CONSTRAINT PK_Ownership PRIMARY KEY (ownerID,buildingID)
);
答案 0 :(得分:4)
所有与触发器相关的解决方案都有一个问题:只要系统中有多个用户,它们就不足以保证约束得到维持。例如,如果会话A插入51%的x
,并且会话B插入51%的ownershipshare
,则这两个插入都将成功,因为两个会话均未提交。然后,两个会话都提交,您的所有者总hpshare为102%。
解决这个问题的一种方法是使用带有约束的ownershipshare
实例化视图。不幸的是,我认为实例化视图仅在Oracle Enterprise Edition中可用,而在Standard或Express中则不可用。我没有可供测试的EE实例,但是我认为这可以满足您的要求:
ON COMMIT
我做了一些额外的工作来使物化视图快速刷新,因此不必在每次提交时都重建整个东西,而只需在受影响的buildid上重新构建。
答案 1 :(得分:0)
编辑 :最初删除此内容是因为我意识到参与多个会话时还不够。取消删除以显示不显示“变异表”问题的解决方案的示例。您必须锁定表,以便一次只能有一个会话影响它。
您可以使用AFTER STATEMENT
触发器进行此操作。整个语句完成后,该操作每insert
,update
或delete
运行一次。这有点草率,因为它可以验证表中的 all 行,甚至包括那些未受影响但出于您的目的可能已经足够的行。
create or replace trigger trig1
after insert or update on ownership
declare
l_count number;
begin
select count(*) into l_count from (
select buildingid, sum(ownershipstake)
from ownership
group by buildingid
having sum(ownershipstake) > 100
);
if l_count > 0 then
raise_application_error( -20001, 'Totals cant be over 100' );
end if;
end;
/
insert into ownership values ( 1, 1, 99 );
insert into ownership values ( 2, 1, 2 );
Error starting at line : 24 in command -
insert into ownership values ( 2, 1, 2 )
Error report -
ORA-20001: Totals cant be over 100
正如我所说,这将验证整个表,即使我仅在此处插入了影响1座建筑物的行。因此,如果您有一百万座建筑物,它会不必要地验证999,999行,并且会对性能产生重大影响。
一种改进的方法是使用复合触发器,在before each row
时间点,您将记录要更改的行的建筑物ID。然后,在after statement
时间点,您将仅验证已修改的建筑标识。
答案 2 :(得分:0)
使用复合触发器
.category-ken4ward h5 {
color: red;
}
答案 3 :(得分:-1)
首先-您可以使用前端在单独的查询中进行管理(即,将最大赌注限制为剩余数量)。
您是否希望进行数据库检查-在“所有权”表上创建行级触发器会有所帮助。
已编辑:添加更多详细信息 因此,也许您已经发现触发器将遇到“变异表”,并且想知道“这家伙在说什么?” 好,让我解释一下:这不是问题的完整答案。
我首选的处理方式是结合使用行级AFTER触发器,表中的额外补充字段和检查约束。
Ownership
表中添加一个额外的字段,我们称之为owned_pct
owned_pct <= 100
的字段上添加检查约束update Ownership set owned_pct= nvl(owned_pct,0)+:new.ownership_pct where building_id = :new.building_id;
此过程将尝试更新owned_pct
列并导致违反约束,这将回滚事务,包括初始DML语句。