Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle:阻止插入超过N行(变量)的约束_Oracle - Fatal编程技术网

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中设置约束,以防止每个“客户-对象”耦合的记录超过“最大数量”

例如:

表1

cd_对象/最大_编号

xxx/1

yyy/2

表2

插入“客户1”,“xxx”->确定

插入“客户1”,“xxx”->KO

插入“客户1”,“yyy”->确定

插入“客户1”,“yyy”->确定

插入“客户1”,“yyy”->KO


提前感谢您的回复。

您可以使用
表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);