2016-01-23 99 views
0

我試圖創建一個觸發器,但是我已經瞭解到我無法將它設計爲在我第一次嘗試中,我將在下面顯示它。這會導致一個'變異表'錯誤,因爲它正在被修改時從表中選擇。實際上,在一次只插入一條記錄時實際上不會導致此錯誤,但是當我一次插入多條記錄時,它會發生此錯誤。Oracle SQL創建觸發器以增加每行的序列號

觸發器的用途是計算表中客戶等於要插入的客戶的記錄數,並將新的order_num值設置爲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; 
+0

有幾個問題。首先,你爲什麼要這樣做,而不是使用合成密鑰(即序列)?那麼,假設你有一個有效的需求,任何解決方案將取決於使用情況?有多少客戶?每個客戶有多少個訂單?您可以同時爲每個客戶處理多個訂單嗎?週轉時間是多少? – APC

+0

一個序列聽起來很棒,但是我相信我將不得不爲每個插入的新客戶創建一個新的序列 - 每年約100K。 我使用客戶,訂單等作爲抽象 - 我沒有真正處理客戶和訂單。 '客戶'每批不會有'1'的訂單 - 可能不在同一年內。因此,我的原始方法只計算現有表中的值,並忽略正在處理的批次中的內容。最多隻有百分之幾的人會在一生中擁有2+'訂單'。我最關心的是CPU時間,因爲我在生產服務器上這樣做。 – mb158127

+1

爲什麼每次插入行時都要計算行數?這是死的緩慢,不會擴展,但最糟糕的是:它會存儲錯誤的行數。兩個併發事務將在':new.order_num'中得到**相同的**值。 –

回答

0

兩個觸發器和臨時表方法可以爲您尋找解決方案,防止突變表錯誤。然而,表現很可能會受到影響。

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; 
/