2015-04-09 5 views
2

Как я могу реорганизовать эти строки кода без использования CURSOR? Я новичок в PL/SQL. Любая помощь будет оценена по достоинству. СпасибоКод refactor без курсора 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; 
/
+0

Удаление курсора и использование реляционной логики - хорошая практика +1 – jean

+2

Вы можете сделать это в одном операторе обновления, используя оператор case. Нет необходимости в процедурном, поэтапном подходе. Почему бы вам не попробовать написать инструкцию для обновления, и если вы застряли, отредактируйте свой вопрос с тем, что вам удалось достичь, и мы поможем вам дальше. – Boneist

+0

стр. вам может показаться полезным прочитать [this] (http://www.orchestrapit.co.uk/?p=171) – Boneist

ответ

6
CURSOR c_emps IS 
    SELECT employee_id 
     FROM bonus; 

Вам не нужно явно объявить CURSOR. Вы можете сделать это в CURSOR FOR LOOP сам:

FOR r_emps IN (SELECT employee_id FROM bonus) 
LOOP 

Если PL/SQL не является обязательным, то вы могли бы сделать это в простом SQL используя выражение CASE, в UPDATE заявление.

Что-то подобное,

UPDATE bonus 
SET bonus = 
    CASE 
    WHEN region = 'Europe' 
    THEN bonus + (v_salary * .01) 
    ELSE v_salary * .01 
... 
and so on 

Да, вам нужно переписать весь PL код/​​SQL в заявлении обновления SQL. Но было бы намного лучше и быстрее. Для цикла ряд строк обработка, таким образом, это slow-by-slow. Избегайте PL/SQL, если вы можете сделать то же самое в SQL.

1

При работе с 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.

Смежные вопросы