我正在研究一个触发器,当他们成为另一位员工的主管时,它将通过电子邮件通知员工。这是一个复合触发器,因为在插入新分配数据时需要查询旧分配数据。它在索引表中为每一行收集相关数据,然后在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;
/
答案 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分配空值(对于没有找到的行),然后继续进行循环的下一次迭代。