2012-07-20 43 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