DML触发器阻止用户通过EBS保存手动输入的数据

时间:2018-07-18 22:16:59

标签: oracle plsql triggers dml

我正在研究一个触发器,当他们成为另一位员工的主管时,它将通过电子邮件通知员工。这是一个复合触发器,因为在插入新分配数据时需要查询旧分配数据。它在索引表中为每一行收集相关数据,然后在after语句中处理所有数据。 “ email()”过程以及下面的代码中的其他一些名称都是占位符。

当用户通过EBS手动输入新员工数据并自动插入新工作分配时,就会触发该问题,从而引发触发器。由于任务记录几乎为空,因此触发器最终不会做任何事情,但是用户无法保存他们输入的新员工数据。他们没有收到任何错误消息。禁用触发器后,问题就消失了,但是我无法弄清楚它是如何引起的。另外,尽管我在这里没有写代码,但是我使用消息来精确跟踪在测试过程中执行触发器的哪些部分,并且在这种情况下没有任何逻辑错误。

任何建议将不胜感激!

CREATE OR REPLACE TRIGGER APPS.HRSS_SUPERVISOR_UPDATE
FOR UPDATE OR INSERT ON APPS.PER_ALL_ASSIGNMENTS_F
COMPOUND TRIGGER
    TYPE assignment_info_r IS RECORD (
        assignment_id           apps.per_all_assignments_f.assignment_id%TYPE
    ,   position_id             apps.per_all_assignments_f.position_id%TYPE
    ,   effective_start_date    apps.per_all_assignments_f.effective_start_date%TYPE
    ,   effective_end_date      apps.per_all_assignments_f.effective_end_date%TYPE
    ,   new_supervisor_id       apps.per_all_assignments_f.supervisor_id%TYPE
    ,   old_supervisor_id       apps.per_all_assignments_f.supervisor_id%TYPE
    ,   updating                BOOLEAN
    );

    TYPE assignment_info_t IS TABLE OF assignment_info_r INDEX BY PLS_INTEGER;

    assignment_info assignment_info_t; --created an associative array to store data for each row
    l_row_count INTEGER := 0;

AFTER EACH ROW IS
BEGIN
    l_row_count := l_row_count + 1;

    CASE
    WHEN UPDATING('supervisor_id') THEN
        assignment_info (l_row_count).updating := TRUE; --need to know if updating or inserting in the after statement
        assignment_info (l_row_count).assignment_id := :new.assignment_id;
        assignment_info (l_row_count).position_id := :new.position_id;
        assignment_info (l_row_count).effective_start_date := :new.effective_start_date;
        assignment_info (l_row_count).effective_end_date := :new.effective_end_date;
        assignment_info (l_row_count).new_supervisor_id := :new.supervisor_id;
        assignment_info (l_row_count).old_supervisor_id := :old.supervisor_id;
    WHEN INSERTING THEN
        assignment_info (l_row_count).updating := FALSE;
        assignment_info (l_row_count).assignment_id := :new.assignment_id;
        assignment_info (l_row_count).position_id := :new.position_id;
        assignment_info (l_row_count).effective_start_date := :new.effective_start_date;
        assignment_info (l_row_count).effective_end_date := :new.effective_end_date;
        assignment_info (l_row_count).new_supervisor_id := :new.supervisor_id;
    END CASE;
EXCEPTION
    WHEN OTHERS THEN
        email(p_recipient => 'developers',
              p_subject => 'errors');
END AFTER EACH ROW;

AFTER STATEMENT IS
    l_position_name apps.hr_all_positions_f.name%TYPE;
    l_old_supervisor_id apps.per_all_assignments_f.supervisor_id%TYPE;
    l_email_address apps.per_all_people_f.email_address%TYPE;

    indx PLS_INTEGER;
BEGIN
FOR indx IN 1 .. l_row_count
LOOP
IF assignment_info (indx).position_id IS NOT NULL THEN
    BEGIN --need the position name for the following condition
        SELECT DISTINCT hap.name
        INTO l_position_name
        FROM apps.hr_all_positions_f hap
        WHERE assignment_info (indx).position_id = hap.position_id
        AND assignment_info (indx).effective_start_date <= hap.effective_end_date
        AND assignment_info (indx).effective_end_date >= hap.effective_start_date
        AND hap.effective_start_date = (SELECT MAX(hap2.effective_start_date)
                                        FROM apps.hr_all_positions_f hap2
                                        WHERE assignment_info (indx).position_id = hap2.position_id
                                        AND assignment_info (indx).effective_start_date <= hap2.effective_end_date
                                        AND assignment_info (indx).effective_end_date >= hap2.effective_start_date);
    EXCEPTION
        WHEN OTHERS THEN
            email(p_recipient => 'developers',
                  p_subject => 'errors');
    END;

    IF l_position_name NOT LIKE 'E.%' THEN
    IF assignment_info (indx).new_supervisor_id IS NOT NULL THEN
        BEGIN
            SELECT email_address
            INTO l_email_address
            FROM apps.per_all_people_f
            WHERE person_id = assignment_info (indx).new_supervisor_id
            AND TRUNC(SYSDATE) BETWEEN effective_start_date AND effective_end_date;
        EXCEPTION
            WHEN OTHERS THEN
                email(p_recipient => 'developers',
                      p_subject => 'errors');
        END;

        CASE
        WHEN assignment_info (indx).updating THEN --check if supervisor has changed
            IF assignment_info (indx).new_supervisor_id != assignment_info (indx).old_supervisor_id OR assignment_info (indx).old_supervisor_id IS NULL THEN
                email(p_recipient => 'supervisor',
                      p_subject => 'new employee');
            END IF;
        ELSE --if inserting, check for previous assignment data
            BEGIN
                SELECT paaf.supervisor_id
                INTO l_old_supervisor_id
                FROM apps.per_all_assignments_f paaf,
                    apps.hr_all_positions_f hap
                WHERE paaf.assignment_id = assignment_info (indx).assignment_id
                AND paaf.effective_end_date = assignment_info (indx).effective_start_date - 1
                AND paaf.position_id = hap.position_id
                AND paaf.effective_end_date >= hap.effective_start_date
                AND paaf.effective_start_date <= hap.effective_end_date
                AND hap.name NOT LIKE 'E.%';
            EXCEPTION
                WHEN NO_DATA_FOUND THEN
                    IF assignment_info (indx).new_supervisor_id IS NOT NULL THEN
                        email(p_recipient => 'supervisor',
                              p_subject => 'new employee');
                    END IF;
                WHEN OTHERS THEN
                    email(p_recipient => 'developers',
                          p_subject => 'errors');
            END;
            IF assignment_info (indx).new_supervisor_id != l_old_supervisor_id THEN
                email(p_recipient => 'supervisor',
                      p_subject => 'new employee');
            END IF;
        END CASE;
    END IF;
    END IF;
END IF;
END LOOP;
EXCEPTION
    WHEN OTHERS THEN
    email(p_recipient => 'developers',
          p_subject => 'errors');
END AFTER STATEMENT;
END;
/

1 个答案:

答案 0 :(得分:1)

“他们没有收到任何错误消息。”闻起来像是NO_DATA_FOUND。

NO_DATA_FOUND是一个PL / SQL异常,通常会被SQL语句忽略,因为“我没有找到任何行”对于SELECT,INSERT..SELECT,UPDATE,DELETE,MERGE语句等不是错误。 (可以说它应该用于INSERT..VALUES,但不是)。

我会放一堆

WHEN NO_DATA_FOUND THEN RAISE_APPLICATION_ERROR(-20001,'No rows for ###');

触发器中每个SELECT ... INTO查询的异常处理程序。

我认为在“ SELECT DISTINCT hap.name INTO l_position_name”中,您可能只想为l_position_name分配空值(对于没有找到的行),然后继续进行循环的下一次迭代。