Oracle:阻止插入超过N行(变量)的约束
我有一个表定义了每个客户的最大对象数Oracle:阻止插入超过N行(变量)的约束,oracle,Oracle,我有一个表定义了每个客户的最大对象数 表1 id\u表\u 1数字主键 cd_对象varchar2(20) 最大值 另一个表存储分配给每个客户的对象 表2 id\u表\u 2数字主键 cd_客户varchar2(20) cd_对象varchar2(20) 如何在表2中设置约束,以防止每个“客户-对象”耦合的记录超过“最大数量” 例如: 表1 cd_对象/最大_编号 xxx/1 yyy/2 表2 插入“客户1”,“xxx”->确定 插入“客户1”,“xxx”->KO 插入“客户1”
- 表1
- id\u表\u 1数字主键
- cd_对象varchar2(20)
- 最大值
- 表2
- id\u表\u 2数字主键
- cd_客户varchar2(20)
- cd_对象varchar2(20)
提前感谢您的回复。您可以使用
表2
上的触发器,如下所示:
--创建表格
SQL> CREATE TABLE TABLE_1 (
2 ID_TABLE_1 NUMBER PRIMARY KEY,
3 CD_OBJECT VARCHAR2(20),
4 MAX_NUMBER NUMBER
5 );
Table created.
SQL> CREATE TABLE TABLE_2 (
2 ID_TABLE_2 NUMBER PRIMARY KEY,
3 CD_CUSTOMER VARCHAR2(20),
4 CD_OBJECT VARCHAR2(20)
5 );
Table created.
--创建触发器
--测试代码
——检查表2中的数据
SQL> SELECT * FROM TABLE_2;
ID_TABLE_2 CD_CUSTOMER CD_OBJECT
---------- -------------------- --------------------
1 customer_1 xxx
3 customer_1 yyy
4 customer_1 yyy
SQL>
干杯 此约束比检查约束所能处理的更复杂。总有一天,我们希望Oracle能够支持任意复杂的约束
同时,可以使用物化视图(MVs)和约束来实现这一点(小心重新执行)。几年前我可能会问:您的要求与我的示例3非常相似。应用到您的案例中,它将类似于:
create materialized view table_2_mv
build immediate
refresh complete on commit as
select t2.cd_customer, t2.cd_object, t1.max_number, count(*) cnt
from table_2 t2
join table_1 t1 on t1.cd_object = t2.cd_object
group by t2.cd_customer, t2.cd_object, t1.max_number;
alter table table_2_mv
add constraint table_2_mv_chk
check (cnt <= max_number)
deferrable;
在表_1上使用一个或多个触发器以确保denorm.max_编号始终正确-例如,当表_1.max_编号更新为新值时,更新相应的denorm表行
使用表_2上的一个或多个触发器来更新denorm.cnt值-例如,当添加一行时,递增denorm.cnt,当删除一行时,递减denorm.cnt
将检查约束添加到denorm
altertabledenorm
添加约束denorm_chk
检查(cnt你可以为此创建一个触发器这在大多数情况下都会起作用,但当两个用户同时插入行时会失败。这可能是可以接受的,但请注意!我忘了说我在web环境中。每个插入都是在不同的会话中执行的。因此,我认为你的解决方案无法应用于我的情况。是的。这正是我们所需要的ed,因为,正如我在前面的评论中所说,我们在一个web环境中,每个insert语句都在一个单独的sql会话中执行。但我认为您的解决方案中的问题是性能,因为“table_2”有许多记录(现在有200万条记录,而且增长很快!)我几乎想写一个清理重复记录的程序,并且每分钟执行一次……是的,我同意2M行,一个实体化视图的完全刷新可能是不明智的!@ Alsand and RoalalBalai我用一个替代的解决方案更新了你可以想到的——讽刺的是使用触发器!
SQL> SELECT * FROM TABLE_2;
ID_TABLE_2 CD_CUSTOMER CD_OBJECT
---------- -------------------- --------------------
1 customer_1 xxx
3 customer_1 yyy
4 customer_1 yyy
SQL>
create materialized view table_2_mv
build immediate
refresh complete on commit as
select t2.cd_customer, t2.cd_object, t1.max_number, count(*) cnt
from table_2 t2
join table_1 t1 on t1.cd_object = t2.cd_object
group by t2.cd_customer, t2.cd_object, t1.max_number;
alter table table_2_mv
add constraint table_2_mv_chk
check (cnt <= max_number)
deferrable;
create table denorm as
select t2.cd_customer, t2.cd_object, t1.max_number, count(*) cnt
from table_2 t2
join table_1 t1 on t1.cd_object = t2.cd_object
group by t2.cd_customer, t2.cd_object, t1.max_number;
alter table denorm
add constraint denorm_chk
check (cnt <= max_number);