通常,它执行正常,但有时一周执行一次或两次,在Oracle中挂起或变慢。
是否有更好的方法对其进行优化?
FOR i IN ( SELECT * FROM process_data) LOOP
BEGIN
SELECT employee_plan_id
INTO lc_emp_plan_id
FROM employee
WHERE employeeid = i.emp_id
AND join_year = (
SELECT join_year
FROM employeedata
WHERE employeeid = i.emp_id
AND i.joining_date BETWEEN join_date AND termination_date
);
END;
SELECT employee_plan_type
INTO lc_emp_type
FROM employee_plans
WHERE employee_plan_id = lc_emp_plan_id;
-- Mark failed record if emp_lastname is null
UPDATE process_data
SET
is_failure = 1
WHERE emp_lastname IS NULL
AND emp_plan_type = lc_emp_type;
END LOOP;
记住
SELECT join_year
FROM employeedata
WHERE employeeid = i.emp_id
AND i.joining_date BETWEEN joining_date AND termination_date;
它将始终返回1条记录,并且已被证明。
lc_emp_plan_id
是一个变量,并且此for循环在过程内执行吗?
答案 0 :(得分:2)
对观察到的行为的最原始的解释是,要处理的行数(process_data
)有所不同。
总经过时间与已处理的行数成线性比例,因此在行数较多的日子,循环“挂起”。
提高速度的最佳方法是不要在PL / SQL中使用FOR LOOP
。
在SQL语句中对其进行简单的重新构造(这并非总是可能的,有时会导致复杂的SQL,但可能会大大提高速度。
在您的情况下,这应该是相当简单的练习:
此查询返回的结果与您的第一个循环相同。
SELECT e.employee_plan_id
FROM process_data p
JOIN employee e ON p.emp_id = e.employeeid
JOIN employeedata ed ON p.emp_id = ed.employeeid
AND p.joining_date BETWEEN ed.join_date AND ed.termination_date;
因此,您可以使用一个UPDATE语句重写整个过程。
UPDATE process_data
SET is_failure = 1
WHERE emp_lastname IS NULL
AND emp_plan_type IN (
SELECT employee_plan_type
FROM employee_plans
WHERE employee_plan_id IN (
/* copy the query above here */
)
);