Рефакторинг кода без курсора 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 2

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.