Oracle
 sql >> база данни >  >> RDS >> Oracle

актуализиране чрез for цикъл в plsql

Нямате нужда от FOR LOOP , само една АКТУАЛИЗАЦИЯ върши работата:

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

Ето демонстрация:http://www.sqlfiddle.com/#!4/ aacc3/1

--- РЕДАКТИРАНЕ ----

Не забелязах, че в очаквания резултат deptno 10 беше актуализирано до 20,
за актуализиране на deptno необходима е друга заявка:

UPDATE emp
   SET deptno = 20
WHERE deptno = 10;



---- РЕДАКТИРАНЕ -----

Ако искате да вмъкнете променени стойности в другата таблица, опитайте процедура с RETURNING..BULK COLLECT и 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;
/

Процедурата трябва да работи, ако няма да обработвате огромен брой записи в едно повикване (повече от 1000 ... или максимум няколко хиляди). Ако един dept_id може да съдържа десет хиляди и повече редове, тогава тази процедура може да е бавна, тъй като ще изразходва огромно количество PGA памет. В такъв случай се изисква друг подход с групово събиранеg на парчета.

-- РЕДАКТИРАНЕ --- как да съхранявате стойности на последователност -------

Предполагам, че таблицата changed има 4 колони, като тази:

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

и ние ще съхраняваме стойностите на последователността в seq_nextval колона.

В такъв случай процедурата може да изглежда така:

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;



--- РЕДАКТИРАНЕ --- версия с курсор за малки набори от данни -----

Да, за малки набори от данни масовото събиране не дава значително увеличение на скоростта и обикновен курсор с for..loop е достатъчен в такъв случай.
По-долу е пример как използвате курсора заедно с актуализацията, забележете FOR UPDATE клауза, тя е необходима, когато планираме да актуализираме запис, извлечен от курсора, използвайки WHERE CURRENT OF клауза.
Този път стойност на последователност се оценява в оператора 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. Oracle преобразуване на UNIX timestamp в timestamp с часова зона

  2. Свържете база данни на MS SQL Server към база данни на Oracle 11g

  3. SQL Sub-Query - как да намерите минимална стойност

  4. c# Entity Framework EF 4.1 Промяна на името на схемата и базата данни по време на изпълнение

  5. Извличане на съобщения от пощенска кутия с помощта на PL/SQL Mail_Client API