Oracle
 sql >> Baza danych >  >> RDS >> Oracle

aktualizacja za pomocą pętli for w plsql

Nie potrzebujesz FOR LOOP , wystarczy jedna aktualizacja:

UPDATE emp
  SET comm = extra
WHERE comm IS NULL AND extra IS NOT NULL;

Oto demo:http://www.sqlfiddle.com/#!4/ aacc3/1

--- EDYTUJ ----

Nie zauważyłem, że w oczekiwanym wyniku deptno 10 zostało zaktualizowane do 20,
aby zaktualizować deptno potrzebne jest inne zapytanie:

UPDATE emp
   SET deptno = 20
WHERE deptno = 10;



---- EDYTUJ -----

Jeśli chcesz wstawić zmienione wartości do innej tabeli, wypróbuj procedurę z RETURNING..BULK COLLECT i FORALL:

CREATE OR REPLACE PROCEDURE pro_cedure( p_dept_id number  ) 
IS
      TYPE changed_table_type IS TABLE OF changed%ROWTYPE;
      changed_buff changed_table_type;
BEGIN
      SELECT deptno, comm, extra BULK COLLECT INTO changed_buff
      FROM emp
      WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id
      FOR UPDATE;
      UPDATE emp
      SET comm = extra
      WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id;
      FORALL i IN 1 .. changed_buff.count
        INSERT INTO changed VALUES changed_buff( i );
END;
/

Procedura powinna zadziałać, jeśli nie zamierzasz przetwarzać ogromnej liczby rekordów w jednym połączeniu (ponad 1000...lub maksymalnie kilka tysięcy). Jeśli jeden dept_id może zawierać dziesięć tysięcy i więcej wierszy, wtedy ta procedura może być powolna, ponieważ zużyje ogromną ilość pamięci PGA. W takim przypadku wymagane jest inne podejście z zbiorczym gromadzeniem w porcjach.

-- EDYCJA --- jak przechowywać wartości sekwencji -------

Zakładam, że tabela changed ma 4 kolumny, tak:

  CREATE TABLE "TEST"."CHANGED" 
   (    "DEPTNO" NUMBER, 
        "OLDVAL" NUMBER, 
        "NEWVAL" NUMBER, 
        "SEQ_NEXTVAL" NUMBER 
   ) ;

i będziemy przechowywać wartości sekwencji w seq_nextval kolumna.

W takim przypadku procedura może wyglądać tak:

create or replace 
PROCEDURE pro_cedure( p_dept_id number  ) 
IS
      TYPE changed_table_type IS TABLE OF changed%ROWTYPE;
      changed_buff changed_table_type;
BEGIN
      SELECT deptno, comm, extra, sequence_name.nextval 
        BULK COLLECT INTO changed_buff
        FROM emp
        WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id
        FOR UPDATE;
      UPDATE emp
        SET comm = extra
        WHERE comm IS NULL AND extra IS NOT NULL AND deptno = p_dept_id;
      FORALL i IN 1 .. changed_buff.count
        INSERT INTO changed VALUES changed_buff( i );
END;



--- EDYCJA --- wersja z kursorem dla małych zestawów danych -----

Tak, dla małych zbiorów danych masowe zbieranie nie daje znaczącego wzrostu szybkości, a zwykły kursor z for..loop jest w takim przypadku wystarczający.
Poniżej przykład jak używać kursora razem z aktualizacją, zwróć uwagę na FOR UPDATE klauzula, jest wymagana, gdy planujemy zaktualizować rekord pobrany z kursora za pomocą WHERE CURRENT OF klauzula.
Tym razem wartość sekwencji jest oceniana w instrukcji INSERT.

create or replace 
PROCEDURE pro_cedure( p_dept_id number  ) 
IS
      CURSOR mycursor IS 
         SELECT deptno, comm, extra
         FROM emp
         WHERE comm IS NULL AND extra IS NOT NULL 
               AND deptno = p_dept_id
         FOR UPDATE;    
BEGIN
      FOR emp_rec IN  mycursor
      LOOP
         UPDATE emp 
            SET comm = extra
            WHERE CURRENT OF mycursor;
         INSERT INTO changed( deptno, oldval, newval, seq_nextval)
                VALUES( emp_rec.deptno, emp_rec.comm, 
                        emp_rec.extra, sequence_name.nextval );
      END LOOP;
END;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wyjątek wdrożenia Weblogic :PaddingException:nie można wykonać uzupełnienia:nieprawidłowy bajt wypełnienia

  2. Czy instrukcja CASE i DECODE są równoważne?

  3. Jak odinstalować / całkowicie usunąć Oracle 11g (klient)?

  4. jak podzielić kolumny w wyniku zapytania w bazie danych Oracle

  5. Uporządkuj wiersze przy użyciu kolumn od mniejszej liczby wartości null do braku wartości null