Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.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 SQL创建触发器以增加每行的序列号_Sql_Oracle_Triggers_Mutating Table - Fatal编程技术网

Oracle SQL创建触发器以增加每行的序列号

Oracle SQL创建触发器以增加每行的序列号,sql,oracle,triggers,mutating-table,Sql,Oracle,Triggers,Mutating Table,我试图创建一个触发器,但我知道我不能像我第一次尝试那样设计它,我将在下面展示。由于在修改表时从表中进行选择,这将导致“mutating table”错误。当一次只插入一条记录时,它实际上并没有导致此错误,但当我一次插入多条记录时,它确实会导致此错误 触发器的目的是统计表中客户与即将插入的客户相等的记录数,并将新订单数量值设置为count+1。我还有一个由从序列中提取的触发器设置的公钥值。一旦我删除了触发器的order_num部分和相关的SELECT,这个部分就可以正常工作了。我怎样才能实现我在这

我试图创建一个触发器,但我知道我不能像我第一次尝试那样设计它,我将在下面展示。由于在修改表时从表中进行选择,这将导致“mutating table”错误。当一次只插入一条记录时,它实际上并没有导致此错误,但当我一次插入多条记录时,它确实会导致此错误

触发器的目的是统计表中客户与即将插入的客户相等的记录数,并将新订单数量值设置为count+1。我还有一个由从序列中提取的触发器设置的公钥值。一旦我删除了触发器的order_num部分和相关的SELECT,这个部分就可以正常工作了。我怎样才能实现我在这里的目标?提前谢谢

CREATE OR REPLACE TRIGGER t_trg
    BEFORE INSERT ON t
    FOR EACH ROW
DECLARE
    rec_count NUMBER(2,0);
   BEGIN
     SELECT COUNT(*) INTO rec_count
     FROM t
     WHERE customer_id = :NEW.customer_id;

     :NEW.order_num:= rec_count+1;
     :NEW.order_pk_id:= table_seq.NEXTVAL;

   END;

两个触发器和临时表方法可以为您提供解决方案,防止表错误的突变。然而,性能很可能会受到影响

create global temporary table cust_temp(customer_id number, cust_cnt number);

create or replace trigger t_trig1
before insert on t
declare
begin
  insert into cust_temp select customer_id, count(*) from t group by customer_id;
end;
/

CREATE OR REPLACE TRIGGER t_trg2 
    BEFORE INSERT ON t
    FOR EACH ROW
DECLARE
    rec_count number;
   BEGIN
     BEGIN
       SELECT cust_cnt INTO rec_count
       FROM cust_temp
       WHERE customer_id = :NEW.customer_id;
    EXCEPTION when no_data_found then rec_count := 0;
    END;
     :NEW.order_num:= rec_count+1;
     :NEW.order_pk_id:= table_seq.NEXTVAL;
      update cust_temp set cust_cnt = rec_count + 1 
      where customer_id = :NEW.customer_id;

   END;
  /

有几个问题。首先,为什么要尝试这样做而不是使用合成键(即序列)?那么,假设您有一个有效的需求,任何解决方案都将取决于使用配置文件?有多少顾客?每个客户有多少订单?您能否同时处理每个客户的多个订单?所需的周转时间是多少?序列听起来不错,但我相信我必须为插入的每个新客户创建一个新序列-大约每年10万个。我使用客户、订单等作为抽象-我不是真正与客户和订单打交道。“客户”每批的“订单”不会超过1个-可能不会在同一年内。因此,我最初的方法是只计算现有表中的数据,而忽略正在处理的批处理中的数据。在一生中最多有百分之几的人会有2+个“订单”。我最担心的是cpu时间,因为我在生产服务器上执行此操作。为什么每次插入一行时都要计算行数?这是非常缓慢的,不会扩展,但最糟糕的是:它将存储错误的行计数。两个并发事务将在
:new.order\u num
中获得相同的值。