Oracle PL/SQL BULK COLLECT: FORALL Beispiel

โšก Intelligente Zusammenfassung

MENGENABHOLUNG in Oracle PL/SQL lรคdt viele Zeilen gleichzeitig in eine Sammlung, wรคhrend FORALL groรŸe DML-Operationen an die Datenbank zurรผcksendet. Beide reduzieren Kontextwechsel zwischen SQL- und PL/SQL-Engines und steigern so die Performance.

  • ๐Ÿ“ฆ MENGENABHOLUNG: Lรคdt mehrere Zeilen in einem einzigen Durchlauf in eine Sammlungsvariable und ersetzt so das langsame Abrufen Zeile fรผr Zeile.
  • ๐Ÿ” FรœR ALLE: Fรผhrt mit einem einzigen Kontextwechsel eine INSERT-, UPDATE- oder DELETE-Operation รผber die gesamte Sammlung aus.
  • ๐Ÿ“ LIMIT-Klausel: Begrenzt die Anzahl der Zeilen, die jeder BULK COLLECT-Abruf lรคdt, und schรผtzt so den Sitzungsspeicher bei groรŸen Tabellen.
  • ๐Ÿ“Š Eigenschaften der Mengenabholung: Das Attribut %BULK_ROWCOUNT(n) gibt an, wie viele Zeilen von der n-ten FORALL DML-Anweisung betroffen sind.
  • โš™๏ธ Erforderliche Sammlungen: Die INTO-Klausel muss auf einen Sammlungstyp abzielen, z. B. auf eine verschachtelte Tabelle oder ein assoziatives Array.
  • ๐Ÿค– KI-Unterstรผtzung: KI-Assistenten wie GitHub Copilot entwerfen BULK COLLECT- und FORALL-Blรถcke und weisen auf eine fehlende LIMIT-Klausel hin.

Oracle PL/SQL BULK COLLECT und FORALL mit LIMIT-Klausel โ€“ รœbersicht

Was ist BULK COLLECT?

BULK COLLECT reduziert Kontextwechsel zwischen den SQL und PL/SQL-Engine und ermรถglicht es der SQL-Engine, die Datensรคtze auf einmal abzurufen.

Oracle PL / SQL Bietet die Funktionalitรคt, Datensรคtze in groรŸen Mengen anstatt einzeln abzurufen. Diese BULK COLLECT-Anweisung kann in einer SELECT-Anweisung verwendet werden, um Datensรคtze in groรŸen Mengen abzurufen oder um eine Cursor Da BULK COLLECT die Datensรคtze gesammelt abruft, muss die INTO-Klausel immer eine Variable vom Typ โ€žCollectionโ€œ enthalten. Der Hauptvorteil von BULK COLLECT besteht in der Leistungssteigerung durch die Reduzierung der Interaktion zwischen Datenbank und PL/SQL-Engine.

Syntax:

SELECT <column1> BULK COLLECT INTO bulk_variable FROM <table name>;
FETCH <cursor_name> BULK COLLECT INTO <bulk_variable>;

In der obigen Syntax wird BULK COLLECT verwendet, um die Daten aus den SELECT- und FETCH-Anweisungen zu sammeln.

FORALL-Klausel

Die FORALL-Anweisung fรผhrt Folgendes aus DML-Operationen Bei groรŸen Datenmengen. Es รคhnelt einer FOR-Schleife, mit dem Unterschied, dass Aktionen in einer FOR-Schleife auf Datensatzebene ausgefรผhrt werden, wรคhrend FORALL kein Schleifenkonzept kennt. Stattdessen werden alle Daten im angegebenen Bereich gleichzeitig verarbeitet.

Syntax:

FORALL <loop_variable> in <lower range> .. <higher range>

<DML operations>;

In der obigen Syntax wird die angegebene DML-Operation fรผr alle Daten ausgefรผhrt, die sich zwischen dem unteren und dem oberen Bereich befinden.

LIMIT-Klausel

Das Konzept der Massensammlung lรคdt alle Daten als Paket in die Ziel-Sammlungsvariable, d. h. alle Daten werden in einem einzigen Schritt in die Sammlungsvariable eingefรผgt. Dies ist jedoch nicht empfehlenswert, wenn die Gesamtzahl der zu ladenden Datensรคtze sehr groรŸ ist, da PL/SQL beim Laden der gesamten Daten mehr Sitzungsspeicher belegt. Daher ist es ratsam, die GrรถรŸe dieser Massensammlungsoperation zu begrenzen.

Diese GrรถรŸenbeschrรคnkung kann leicht durch die Einfรผhrung der ROWNUM-Bedingung in der SELECT-Anweisung erreicht werden, im Falle eines Cursors ist dies jedoch nicht mรถglich.

Um dies zu รผberwinden, Oracle hat die LIMIT-Klausel bereitgestellt, die die Anzahl der Datensรคtze definiert, die in den Massenversand einbezogen werden mรผssen.

Syntax:

FETCH <cursor_name> BULK COLLECT INTO <bulk_variable> LIMIT <size>;

In der obigen Syntax verwendet die Cursor-Fetch-Anweisung die BULK COLLECT-Anweisung zusammen mit der LIMIT-Klausel.

BULK COLLECT-Attribute

ร„hnlich wie Cursorattribute verfรผgt BULK COLLECT รผber %BULK_ROWCOUNT(n), das die Anzahl der Zeilen zurรผckgibt, die in der n-ten DML-Anweisung der FORALL-Anweisung betroffen sind. Es gibt also die Anzahl der Datensรคtze an, die in der FORALL-Anweisung fรผr jeden einzelnen Wert der Sammlungsvariablen betroffen sind. Der Parameter 'n' gibt die Position des Wertes in der Sammlung an, fรผr den die Zeilenanzahl benรถtigt wird.

Beispiel 1: In diesem Beispiel werden wir alle Mitarbeiternamen aus der Tabelle โ€žempโ€œ mit BULK COLLECT projizieren und auรŸerdem das Gehalt aller Mitarbeiter mit FORALL um 5000 erhรถhen.

Der folgende Screenshot zeigt dieses BULK COLLECT- und FORALL-Beispiel zusammen mit seiner Ausgabe. Oracle.

Beispiel fรผr die Massenentnahme mit Limit und FORALL: Aktualisierung des Mitarbeitergehalts in Oracle PL / SQL

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
TYPE lv_emp_name_tbl IS TABLE OF VARCHAR2(50);
lv_emp_name lv_emp_name_tbl;
BEGIN
OPEN guru99_det;
FETCH guru99_det BULK COLLECT INTO lv_emp_name LIMIT 5000;
FOR c_emp_name IN lv_emp_name.FIRST .. lv_emp_name.LAST
LOOP
Dbms_output.put_line('Employee Fetched:'||c_emp_name);
END LOOP;
FORALL i IN lv_emp_name.FIRST .. lv_emp_name.LAST
UPDATE emp SET salary=salary+5000 WHERE emp_name=lv_emp_name(i);
COMMIT;
Dbms_output.put_line('Salary Updated');
CLOSE guru99_det;
END;
/

Ausgang

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY
Salary Updated

Code Erlรคuterung:

  • Code Zeile 2: Deklaration des Cursors guru99_det fรผr die Anweisung 'SELECT emp_name FROM emp'.
  • Code Zeile 3: Deklaration von lv_emp_name_tbl als Tabellentyp VARCHAR2(50).
  • Code Zeile 4: Deklaration von lv_emp_name als lv_emp_name_tbl-Typ.
  • Code Zeile 6: ร–ffnen des Cursors.
  • Code Zeile 7: Der Cursor wird mit BULK COLLECT und der LIMIT-GrรถรŸe von 5000 in die Variable lv_emp_name eingelesen.
  • Code Zeile 8-11: Einrichten einer FOR-Schleife zum Ausgeben aller Datensรคtze in der Sammlung lv_emp_name.
  • Code Zeile 12: Mit FORALL das Gehalt aller Mitarbeiter um 5000 erhรถhen.
  • Code Zeile 14: Begehen der Transaktion.

Hรคufig gestellte Fragen

Nein. Ein BULK COLLECT SELECT lรถst niemals NO_DATA_FOUND aus; stattdessen gibt er eine leere Collection zurรผck. Prรผfen Sie die Collection immer mit der .COUNT-Methode, bevor Sie sie durchsuchen.pingAndernfalls werden mรถglicherweise keine Zeilen verarbeitet, ohne dass die Verarbeitung unterbrochen wird.

SAVE EXCEPTIONS sorgt dafรผr, dass FORALL auch dann weiterlรคuft, wenn einzelne Zeilen fehlschlagen. Fehlgeschlagene Zeilen werden in SQL%BULK_EXCEPTIONS gespeichert. Oracle lรถst ORA-24381 aus, das Sie in einem abfangen Ausnahme Handler zur รœberprรผfung jedes Fehlers.

Verwenden Sie BULK COLLECT immer dann, wenn eine Schleife viele Zeilen liest. Cursor Die FOR-Schleife ruft pro Switch eine Zeile ab, sodass das Abrufen von Massendaten in Kombination mit FORALL bei groรŸen Ergebnismengen um ein Vielfaches schneller erfolgen kann.

BULK COLLECT gibt mehrere Zeilen gleichzeitig zurรผck und benรถtigt daher einen Container fรผr mehrere Zeilen. Das INTO-Ziel muss ein der Abholung wie beispielsweise eine verschachtelte Tabelle, VARRAY oder ein assoziatives Array, nicht eine einzelne skalare Variable.

Nein. Ein FORALL-Header steuert genau eine INSERT-, UPDATE-, DELETE- oder MERGE-Anweisung. Nur die Werte in den VALUES- und WHERE-Klauseln kรถnnen sich pro Iteration รคndern. Verwenden Sie fรผr mehrere Anweisungen separate FORALL-Anweisungen.

Die Verarbeitung groรŸer Datenmengen kann um ein Vielfaches bis รผber hundert Mal schneller sein als die Verarbeitung von Zeilen fรผr Zeilen, da BULK COLLECT und FORALL Tausende von Engine-Kontextwechseln auf wenige reduzieren und so den Aufwand bei groรŸen Datenmengen deutlich verringern.

Ja. GitHub-Copilot Entwirft BULK COLLECT-Abrufe, FORALL-DML-Schleifen und LIMIT-Klauseln aus einem Kommentar und schlรคgt Sammlungstypdeklarationen vor, obwohl Sie die BatchgrรถรŸen und die Fehlerbehandlung selbst รผberprรผfen sollten.

KI-Assistenten analysieren Schleifen, die jeweils eine Zeile abrufen oder รคndern, und empfehlen, diese mit BULK COLLECT, LIMIT und FORALL zu optimieren. Diese maschinelle Lernanalyse erkennt fehlende LIMIT-Begrenzungen und Leistungsengpรคsse vor der Produktion.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: