2012-07-20 76 views
0

我有一個現有的TABLE postn_matrix其中包含員工列表和他們的責任計數。在組織中的職位。光標在觸發器

每當用戶的位置添加或刪除,相應的計數體現在表救援人員到場該觸發器(VIA UPDATE)現在

,如果有新的用戶,他不會有一個入口在postn_matrix中,所以我必須爲他/她插入新的記錄(VIA INSERT)。這需要從BASE TABLE中引入。

該更新似乎工作正常,但我無法引入一個新的用戶到表中。

我一直在試圖用遊標來處理這種情況。但它還沒有任何幫助。 我希望有些專家可以告訴我光.. :)。除了使用光標任何其他建議將非常感激

CREATE OR REPLACE TRIGGER TRIG1 
BEFORE INSERT OR DELETE ON (BASETABLE) 
FOR EACH ROW 
DECLARE 
    cursor c1 is 
    select person_id 
    from postn_matrix; 

    v_temp varchar2(15); 
BEGIN 
    IF INSERTING THEN 
    open c1;  
    LOOP 
     fetch c1 into v_temp; 

     if v_temp!=:new.person_id THEN 
     insert into POSTN_MATRIX (PERSON_ID) 
     VALUES (:new.PERSON_ID); 
     else 
     UPDATE POSTN_MATRIX 
     //this is working fine ; 

     END IF; 
    end loop; 
    close c1; 

END 
/
+2

我不明白。如果在BASETABLE中有新記錄,並且您已經知道POSTN_MATRIX中沒有記錄,那麼爲什麼要在POSTN_MATRIX上循環遊標?只需插入一條新記錄。 – Rene 2012-07-20 13:41:20

+0

請閱讀SQL基礎知識並閱讀它。你確實需要一個遊標來做到這一點,而且你的SQL通常不應該有'if then'語句。 SQL是一種定位語言。請參閱http://www.codeproject.com/Articles/10144/SQL-as-a-set-oriented-language – ThomasMcLeod 2012-07-20 13:42:51

回答

4

由於環路(這是缺少退出條款 - 希望你剛剛失去了翻譯成一個問題,這個)你要去嘗試將記錄插入pstn_matrix記錄遊標返回值,是否有任何匹配的:new.person_id;如果有匹配,你也會做update。這可能不是你想要的,你可能會遇到違反約束的問題。你也沒有設置你的計數器字段 - 如果這不是可以空的,那就會出錯。但是你沒有說過你會得到什麼錯誤,如果有的話。

如果你必須通過一個觸發做到這一點,那麼你可以檢查是否有一排新的人都沒有:

DECLARE 
    v_temp postn_matrix.person_id%TYPE; 
BEGIN 
    IF INSERTING THEN 
    select max(person_id) into v_temp 
    from postn_matrix 
    where person_id = :new.person_id; 

    if v_temp is null then 
     -- no record found, so insert one 
     insert into postn_matrix (person_id, position_count) 
     values (:new.person_id, 1); 
    else 
     -- record exists, so update 
     update postn_matrix ... 
    end if; 
    ... 

...或使用merge

但是我不喜歡這個模型,而且你正在設置數據差異的可能性,同時修改基表。試圖保持這樣的計數並不一定像看起來那麼簡單。

通常我寧願讓這個觀點,這將永遠是最新的,不需要觸發複雜的事情:

create view postn_matrix as 
    select person_id, count(*) 
    from basetable 
    group by person_id; 

當然,我可能會誤解或過於簡單化了你的基表(s)確實和你需要postn_matrix。作爲一種觀點,這似乎有點微不足道。如果你有獨立的personperson_position表,說出來的話,你可以在外部添加加盟見人,沒有位置:

create view postn_matrix as 
    select p.person_id, count(pp.position_id) 
    from person p 
    left join person_position pp on pp.person_id = p.person_id 
    group by p.person_id; 
+0

嗨,亞歷克斯,謝謝很多的信息。我非常理解使用max(person_id)的含義。你能解釋一下嗎? – MayankG 2012-07-20 17:04:36

+2

通過使用MAX,他確信SELECT始終只返回一行,從而避免需要異常處理程序。 – DCookie 2012-07-20 17:22:20

+1

@MayankG - 它檢查是否存在該記錄:new.person_id。如果它只是'將person_id選入v_temp',那麼如果沒有現有記錄,就會得到'ORA-01403',如果有多個,你會得到'ORA-02112'。使用'max()'意味着你總是得到一行;如果有任何數量的匹配記錄,它將有ID,否則它將爲空。如果找到更清晰的數據,你也可以使用count()來檢查找到的零或非零行。 – 2012-07-20 17:25:38