Рефакторинг кода без курсора PL / SQL
Как я могу рефакторировать эти строки кода без использования CURSOR
?
Я новичок в PL / SQL.
Любая помощь будет оценена по достоинству. Спасибо
DECLARE
CURSOR c_emps IS
SELECT employee_id
FROM bonus;
v_region HR.REGIONS.region_name%TYPE;
v_salary hr.employees.salary%TYPE;
BEGIN
FOR r_emps IN c_emps LOOP
SELECT reg.region_name, emp.salary
INTO v_region, v_salary
FROM hr.employees emp,
hr.departments dep,
hr.Locations loc,
hr.countries cot,
hr.regions reg
WHERE emp.department_id = dep.department_id AND
dep.location_id = loc.location_id AND
loc.country_id = cot.country_id AND
cot.region_id = reg.region_id AND
employee_id = r_emps.employee_id;
IF v_region = 'Europe' THEN
UPDATE bonus
SET bonus = bonus + (v_salary * .01)
WHERE employee_id = r_emps.employee_id;
ELSE
UPDATE bonus
SET bonus = v_salary * .01
WHERE employee_id = r_emps.employee_id;
END IF;
END LOOP;
COMMIT;
END;
/
2 ответа:
CURSOR c_emps IS SELECT employee_id FROM bonus;
Вам не нужно явно объявлять курсор. Вы можете сделать это в самом курсоре для цикла :
FOR r_emps IN (SELECT employee_id FROM bonus) LOOP
Если PL/SQL не является обязательным, то вы можете сделать это в простом SQL, используя CASE expression в операторе UPDATE.
Что-то вроде,
UPDATE bonus SET bonus = CASE WHEN region = 'Europe' THEN bonus + (v_salary * .01) ELSE v_salary * .01 ... and so on
Да, вам нужно переписать весь код PL / SQL в инструкцию SQL update. Но это было бы намного лучше и быстрее. Для цикла это ряд за рядом обработка, таким образом, этомедленно-медленно . Избегайте PL / SQL, если вы можете сделать то же самое в SQL.
При работе с SQL Server требуется очень много усилий, чтобы избежать курсоров, потому что они обрабатываются очень плохо. Использование курсора в SQL Server-это все равно что продираться по пояс в мелассе. Oracle обрабатывает курсоры намного лучше, поэтому вы видите гораздо больше строчной работы в Oracle. Слишком много, действительно. Даже в Oracle, если что-то можно сделать с помощью одного оператора SQL, это намного лучше, чем использование курсоров PL / SQL и циклических операций.
К сожалению, Oracle не разрешает соединения в
UPDATE
заявления. Но не волнуйтесь, более недавнее нововведение, утверждениеMERGE
делает.MERGE INTO BONUS B USING( SELECT EMP.EMPLOYEE_ID, EMP.SALARY, REG.REGION_NAME FROM HR.EMPLOYEES EMP JOIN HR.DEPARTMENTS DEP ON DEP.DEPARTMENT_ID = EMP.DEPARTMENT_ID JOIN HR.LOCATIONS LOC ON LOC.LOCATION_ID = DEP.LOCATION_ID JOIN HR.COUNTRIES COT ON COT.COUNTRY_ID = LOC.COUNTRY_ID JOIN HR.REGIONS REG ON REG.REGION_ID = COT.REGION_ID ) U ON( U.EMPLOYEE_ID = b.EMPLOYEE_ID ) WHEN MATCHED THEN UPDATE SET B.BONUS =( u.SALARY * 0.01 ) + CASE U.REGION_NAME WHEN 'Europe' THEN B.BONUS ELSE 0 END;
Как хорошо, что предложение
when not matched
не требуется, эффективно превращаяmerge
в очень гибкоеupdate
.