我创建了一个程序包,其程序如下:
PROCEDURE person_phone_data_load
IS
CURSOR cur_phone_info
is
SELECT itnpi.ROWID row_id, itnpi.*
from xx_TAL_NEWHIRE_PHONE_INT ITNPI,
xx_tal_newhire_employ_int emp
where 1 = 1 and ITNPI.STATUS in ('N', 'E')
and EMP.CANDIDATE_NUMBER=ITNPI.CANDIDATE_NUMBER
and BUSINESS_UNIT='APGEN BUSINESS GROUP'
;
/**
select phone.ROWID row_id, phone.candidate_number, DECODE(phone.phone_type,'Work Phone','WORK','Home Phone','HOME','Cellular Phone','MOBILE',phone.phone_type) PHONE_TYPE,
case phone.phone_type
when 'Mobile Phone' then mobile_number
when 'Work Phone' then WORK_PHONE
when 'Home Phone' then home_number
end as phone_number
from xx_tal_newhire_phone_int phone
Where 1 = 1 And Phone.Status In ('N', 'E');
**/
CURSOR lcu_get_person_id (p_candidate_number VARCHAR2)
IS
SELECT papf.person_id, papf.start_date
FROM per_all_people_f papf, per_people_extra_info ppei
WHERE papf.person_id = ppei.person_id
AND ppei.information_type = 'XXHR_TAL_NEWHIRE_READER'
AND ppei.pei_information1 = p_candidate_number
AND papf.effective_start_date =
(SELECT MAX (papf1.effective_start_date)
FROM per_all_people_f papf1
WHERE papf1.person_id = papf.person_id)
GROUP BY papf.person_id, papf.start_date;
CURSOR lcu_check_phone (p_personid NUMBER, p_phone_type VARCHAR2)
IS
SELECT phone_number
FROM per_phones
WHERE SYSDATE BETWEEN date_from AND NVL (date_to, '31-DEC-4712')
AND phone_type = p_phone_type
AND parent_id = p_personid;
lv_phone_type VARCHAR2 (240);
ln_phone_type_excep VARCHAR2 (2000);
an_phone_type_excep VARCHAR2 (2000);
ln_phone_id NUMBER;
ln_object_version_number NUMBER;
ld_ph_date_from DATE;
ld_ph_date_to DATE;
lv_phone_number VARCHAR2 (100);
ln_person_id NUMBER;
ln_phone_err_msg VARCHAR2 (2000);
ln_person_excep VARCHAR2 (2000);
an_person_excep VARCHAR2 (2000);
lc_rec_status VARCHAR2 (1);
ln_phoneno NUMBER;
ln_start_date DATE;
BEGIN
fnd_file.put_line (fnd_file.LOG,
'**********************************************'
);
fnd_file.put_line (fnd_file.LOG,
'** New Hire Phone load Program Starts **'
);
FOR phone_info_rec IN cur_phone_info
LOOP
BEGIN
lv_phone_type := NULL;
ln_phone_id := NULL;
ln_object_version_number := NULL;
ln_person_id := NULL;
ln_phone_err_msg := NULL;
ld_ph_date_from := TRUNC (SYSDATE);
ld_ph_date_to := NULL;
lv_phone_number := phone_info_rec.phone_number ;
ln_phone_type_excep := NULL;
ln_person_excep := NULL;
lc_rec_status := 'S';
IF phone_info_rec.phone_type IS NOT NULL
THEN
lv_phone_type :=
get_lookup_code ('PHONE_TYPE', phone_info_rec.phone_type);
IF lv_phone_type = 'NO_VALUE'
THEN
lc_rec_status := 'E';
-- Could not decode the SEX for the Employee.
ln_phone_err_msg :=
ln_phone_err_msg
|| 'Invalid Phone Type for candidate_number: '
|| phone_info_rec.candidate_number
|| ' # ';
END IF;
END IF;
IF phone_info_rec.candidate_number IS NOT NULL
THEN
ln_person_id := NULL;
OPEN lcu_get_person_id (phone_info_rec.candidate_number);
FETCH lcu_get_person_id
INTO ln_person_id, ln_start_date;
CLOSE lcu_get_person_id;
IF ln_person_id IS NULL
THEN
lc_rec_status := 'E';
-- Employee Not Created for the Candidate Number.
ln_phone_err_msg :=
ln_phone_err_msg
|| 'Employee Record not created for the candidate_number: '
|| phone_info_rec.candidate_number
|| ' # ';
ELSIF ln_person_id IS NOT NULL
THEN
OPEN lcu_check_phone (ln_person_id, lv_phone_type);
FETCH lcu_check_phone
Into Ln_Phoneno;
Close lcu_check_phone;
If Lcu_Check_Phone%Isopen Then
Close Lcu_Check_Phone;
END IF;
IF ln_phoneno = phone_info_rec.phone_number
Then
lc_rec_status := 'P';
ln_phone_err_msg :=
ln_phone_err_msg
|| 'Phone already exists for the candidate_number: '
|| phone_info_rec.candidate_number
|| ' # ';
END IF;
END IF;
ELSE
lc_rec_status := 'E';
-- Candidate Number is NULL.
ln_phone_err_msg :=
ln_phone_err_msg
|| 'Candidate Number is NULL; So Could not find the Employee for Address creation';
END IF;
IF lc_rec_status = 'S'
THEN
BEGIN
UPDATE xx_tal_newhire_phone_int iph
SET status = 'P',
error_msg = NULL
WHERE iph.ROWID = phone_info_rec.row_id;
COMMIT;
fnd_file.put_line
(fnd_file.LOG,
'Successfully Processed phone record for candidate_number: '
|| phone_info_rec.candidate_number
);
EXCEPTION
WHEN OTHERS
THEN
ln_phone_err_msg :=
'Phone API Error while processing candidate_number: '
|| phone_info_rec.candidate_number
|| ' , '
|| SUBSTR (SQLERRM, 1, 150);
UPDATE xx_tal_newhire_phone_int iph
SET status = 'E',
error_msg = ln_phone_err_msg
WHERE iph.ROWID = phone_info_rec.row_id;
fnd_file.put_line
(fnd_file.LOG,
'Person API Error while processing candidate_number: '
|| phone_info_rec.candidate_number
|| ' , '
|| SUBSTR (SQLERRM, 1, 150)||DBMS_UTILITY.FORMAT_ERROR_BACKTRACE()
);
END;
ELSE
UPDATE xx_tal_newhire_phone_int iph
SET status = lc_rec_status,
error_msg = ln_phone_err_msg
WHERE iph.ROWID = phone_info_rec.row_id;
END IF;
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
ln_phone_err_msg :=
'Phone Error : ' || SUBSTR (SQLERRM, 1, 150)||DBMS_UTILITY.FORMAT_ERROR_BACKTRACE();
Update xx_Tal_Newhire_Phone_Int Iph
SET status = 'E',
error_msg = ln_phone_err_msg
WHERE iph.ROWID = phone_info_rec.row_id;
COMMIT;
END;
End Loop;
fnd_file.put_line (fnd_file.LOG,
'** New Hire Phone load Program Ends **'
);
EXCEPTION
WHEN OTHERS
THEN
fnd_file.put_line (fnd_file.LOG,
'In phone main :' || SUBSTR (SQLERRM, 1, 150)
);
ROLLBACK;
END person_phone_data_load;
我得到的是:"Phone Error : ORA-06511: PL/SQL: cursor already open
错误。这适用于光标lcu_check_phone
。我还明确添加了一个if语句,以便在打开时关闭游标。我仍然得到这个错误。
答案 0 :(得分:3)
我认为你遇到的问题是这个
OPEN lcu_check_phone (ln_person_id, lv_phone_type);
FETCH lcu_check_phone
Into Ln_Phoneno;
Close lcu_check_phone;
电话号码不是数字字段 - 但Ln_Phoneno定义为数字。你的fetch语句抛出了一个被处理的异常,但这会绕过你的两个close语句。然后在下一次迭代中,您无法重新打开光标。
如果你要拥有所有这些嵌套循环,那么你需要在异常处理程序中放置close语句。
替代方案是更加模块化 - 使用许多小程序来分解你的代码 - 然后你不必担心范围这么多,因为每个游标只会在一次迭代的持续时间内存在。如果这是有道理的......
答案 1 :(得分:1)
要避免打开/关闭/获取游标问题,请尽可能使用游标循环。您不必担心在一次获取中从游标中获取所有值以及关于循环计数,因为它本身是由循环控制的(例如:来自其他语言的每个循环)。我通常使用标准的open / fetch / close来检查游标是否加载了一些数据,当它没有将%NOTFOUND标志设置为true时,例如在错误处理中,如果没有选择任何数据,则选择投入NO_DATA_FOUND