我有一个应用程序表和一个资源表。由于许多资源可以在单个应用程序上运行,并且许多应用程序可以由单个资源处理,因此我创建了第3个表:
ApplicationResources :
- ID(int)
--ApplicationID(int)
- ResourceID(int)
- PctOfTime(浮动)
无论如何在数据库本身,我可以确保所有资源的总PctOfTime加起来达到100%?
答案 0 :(得分:1)
在SQL中没有声明性的方法。
您可以使用触发器(每当ApplicationResources表中的行被INSERTed,UPDATEd或DELETEd运行时运行的存储过程来完成此操作。触发器可以测试条件并拒绝更改,如果它会导致条件为false
问题是您可能需要允许表暂时无效。例如,如果删除资源的记录,则在添加或更新一个或多个记录以恢复到100%之前,条件将不成立。为了使其工作,您需要将触发器推迟到事务结束,并且这样做的能力因数据库而异。
如果您希望条件是没有资源可以超过 100%分配(并且允许资源未被充分利用),那么您的问题将更容易处理。
答案 1 :(得分:0)
你使用Oracle吗?
如果您使用Oracle,则可以使用快速刷新物化视图以声明方式验证数据,您必须向此物化视图添加检查约束。这意味着验证将在提交发生时完成。
<强> EDIT1 强>
让我感到遗憾的是,我没有回答我的非常简单的问题,所以我不知道他/她是否使用Oracle,但无论如何:
让我们创建一个包含物化视图日志的表,一个物理化视图,其中包含一个on by resourceid和一个检查约束,以检查每个resourceid的PctOfTime总和等于100。
create table applicationresources
(
id number(10) not null primary key,
applicationid number(10) not null,
resourceid number(10) not null,
pctoftime number(3) not null
);
create materialized view log on applicationresources
with rowid (id,applicationid,resourceid,pctoftime) including new values;
create materialized view pctoftimecheck
refresh fast on commit
as
select sum(pctoftime) sum_time,resourceid
from applicationresources
group by resourceid
/
alter table pctoftimecheck add constraint c1 check(sum_time=100);
现在有两个例子:
示例1(将成功):
insert into applicationresources values (1, 1, 1, 50);
insert into applicationresources values (2, 2, 1, 50);
commit;
示例2(因为sum = 101,将在提交时失败)
insert into applicationresources values (3, 1, 2, 50);
insert into applicationresources values (4, 2, 2, 50);
insert into applicationresources values (5, 3, 2, 1);
commit;
SQL> Error: ORA-02290: CHECK-constraint (DSEDD.C1) violated.
有关详细信息,请参阅:http://rwijk.blogspot.com/2009/06/fast-refreshable-materialized-view.html
答案 2 :(得分:0)
这可以通过触发器来完成,但问题是当总数不等于100%时要做什么。如果我将一个值从50%更改为60%(并且我已经有其他50%的其他记录)我是否要调低其他记录以达到100或拒绝更新。还有initail插入记录的问题。第一张唱片是60%,但根据你的规则,我必须以100%输入,直到我输入另一张唱片。最后,如果所有记录的总和不加100%,该怎么办。您是否拆分所有记录之间的差异,拆分未更改的记录之间的差异保持更改的值还是拒绝使总计不加起来的更改?
这是一个必须经过深思熟虑和设计的触发器。