Oracle PL/SQL BULK COLLECT: FORALL Eksempel

โšก Smart oppsummering

MASSEHENTING i Oracle PL/SQL henter mange rader samtidig inn i en samling, mens FORALL sender masse-DML tilbake til databasen. Begge kutter kontekstbytter mellom SQL- og PL/SQL-motorene, noe som รธker ytelsen.

  • ๐Ÿ“ฆ MASSEINNSAMLING: Henter flere rader i รฉn omgang inn i en samlingsvariabel, og erstatter langsom henting rad for rad.
  • ๐Ÿ” FOR ALLE: Kjรธrer รฉn INSERT-, UPDATE- eller DELETE-funksjon pรฅ tvers av en hel samling med รฉn kontekstbryter.
  • ๐Ÿ“ LIMIT-klausul: Setter en grense for hvor mange rader hver BULK COLLECT henter laster, og beskytter รธktminnet pรฅ store tabeller.
  • ๐Ÿ“Š Attributter for MASSEINNSAMLING: Attributtet %BULK_ROWCOUNT(n) rapporterer hvor mange rader den n-te FORALL DML-setningen pรฅvirket.
  • โš™๏ธ Nรธdvendige samlinger: INTO-klausulen mรฅ vรฆre mรฅlrettet mot en samlingstype, for eksempel en nestet tabell eller en assosiativ matrise.
  • ๐Ÿค– AI-hjelp: AI-assistenter som GitHub Copilot utarbeider BULK COLLECT- og FORALL-blokker og flagger en manglende LIMIT-klausul.

Oracle Oversikt over PL/SQL BULK COLLECT og FORALL med LIMIT-klausul

Hva er BULK COLLECT?

MASSEINNSAMLING reduserer kontekstbytter mellom SQL og PL/SQL-motoren, og lar SQL-motoren hente postene samtidig.

Oracle PL / SQL gir funksjonaliteten til รฅ hente postene i bulk i stedet for รฅ hente dem รฉn etter รฉn. Denne BULK COLLECT-funksjonen kan brukes i en SELECT-setning for รฅ fylle ut postene i bulk, eller for รฅ hente en markรธr i bulk. Siden BULK COLLECT henter postene i bulk, bรธr INTO-klausulen alltid inneholde en variabel av samlingstypen. Hovedfordelen med รฅ bruke BULK COLLECT er at den รธker ytelsen ved รฅ redusere interaksjonen mellom databasen og PL/SQL-motoren.

Syntaks:

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

I syntaksen ovenfor brukes BULK COLLECT til รฅ samle inn dataene fra SELECT- og FETCH-setningene.

FORALL klausul

FORALL-setningen utfรธrer DML-operasjoner pรฅ data i bulk. Det ligner en FOR-lรธkkesetning, bortsett fra at i en FOR-lรธkke skjer handlinger pรฅ postnivรฅ, mens det i FORALL ikke finnes noe LOOP-konsept. I stedet behandles alle dataene som finnes i det gitte omrรฅdet samtidig.

Syntaks:

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

<DML operations>;

I syntaksen ovenfor vil den gitte DML-operasjonen bli utfรธrt for alle dataene som finnes mellom det nedre og รธvre omrรฅdet.

LIMIT-klausul

Konseptet med masseinnsamling laster alle dataene inn i mรฅlinnsamlingsvariabelen som en bulk, dvs. at alle dataene vil bli fylt inn i innsamlingsvariabelen pรฅ รฉn gang. Men dette er ikke tilrรฅdelig nรฅr det totale antallet poster som mรฅ lastes inn er veldig stort, fordi nรฅr PL/SQL prรธver รฅ laste inn alle dataene, bruker det mer sesjonsminne. Derfor er det alltid lurt รฅ begrense stรธrrelsen pรฅ denne masseinnsamlingsoperasjonen.

Denne stรธrrelsesgrensen kan enkelt oppnรฅs ved รฅ introdusere ROWNUM-betingelsen i SELECT-setningen, mens dette ikke er mulig for en markรธr.

For รฅ overvinne dette, Oracle har gitt LIMIT-klausulen som definerer antall poster som mรฅ inkluderes i bulk.

Syntaks:

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

I syntaksen ovenfor bruker markรธrhentingssetningen BULK COLLECT-setningen sammen med LIMIT-klausulen.

BULK COLLECT-attributter

I likhet med markรธrattributter har BULK COLLECT %BULK_ROWCOUNT(n) som returnerer antall rader som er pรฅvirket i den n-te DML-setningen i FORALL-setningen, dvs. den gir antallet poster som er pรฅvirket i FORALL-setningen for hver enkelt verdi fra samlingsvariabelen. Begrepet 'n' indikerer sekvensen av verdien i samlingen som radantallet er nรธdvendig for.

Eksempel 1: I dette eksemplet vil vi projisere alle ansattnavnene fra emp-tabellen ved hjelp av BULK COLLECT, og vi skal ogsรฅ รธke lรธnnen til alle ansatte med 5000 ved hjelp av FORALL.

Skjermbildet nedenfor viser dette BULK COLLECT- og FORALL-eksemplet sammen med utdataene i Oracle.

BULK COLLECT med LIMIT og FORALL eksempel pรฅ oppdatering av ansattlรธnn i 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;
/

Produksjon

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

Code Forklaring:

  • Code linje 2: Deklarerer markรธren guru99_det for setningen 'SELECT emp_name FROM emp'.
  • Code linje 3: Deklarerer lv_emp_name_tbl som en tabelltype for VARCHAR2(50).
  • Code linje 4: Deklarerer lv_emp_name som lv_emp_name_tbl-typen.
  • Code linje 6: ร…pne markรธren.
  • Code linje 7: Henter markรธren ved hjelp av BULK COLLECT med LIMIT-stรธrrelsen 5000 inn i variabelen lv_emp_name.
  • Code linje 8โ€“11: Setter opp en FOR-lรธkke for รฅ skrive ut alle postene i samlingen lv_emp_name.
  • Code linje 12: Bruk FORALL til รฅ oppdatere lรธnnen til alle ansatte med 5000.
  • Code linje 14: ร… begรฅ Transaksjonen.

Spรธrsmรฅl og svar

Nei. En BULK COLLECT SELECT genererer aldri NO_DATA_FOUND; i stedet returnerer den en tom samling. Test alltid samlingen med .COUNT-metoden fรธr du ser pรฅ den.ping, ellers kan du behandle null rader stille.

SAVE EXCEPTIONS lar FORALL fortsette รฅ kjรธre nรฅr individuelle rader feiler. Feilende rader lagres i SQL%BULK_EXCEPTIONS, deretter Oracle hever ORA-24381, som du fanger i en unntak behandler for รฅ inspisere hver feil.

Bruk BULK COLLECT nรฅr en lรธkke leser mange rader. markรธr FOR-lรธkken henter รฉn rad per bryter, sรฅ massehenting pluss FORALL kan kjรธre mange ganger raskere pรฅ store resultatsett.

BULK COLLECT returnerer mange rader samtidig, sรฅ den trenger en container med flere rader. INTO-mรฅlet mรฅ vรฆre et samling som for eksempel en nestet tabell, VARRAY eller assosiativ matrise, ikke en enkelt skalar variabel.

Nei. En FORALL-header kjรธrer nรธyaktig รฉn INSERT-, UPDATE-, DELETE- eller MERGE-klausul. Bare verdiene i VALUES- og WHERE-klausulene kan endres per iterasjon. For flere setninger, bruk separate FORALL-setninger.

Massebehandling kan vรฆre flere ganger til over hundre ganger raskere enn rad-for-rad-kode, fordi BULK COLLECT og FORALL kollapser tusenvis av motorkontekstbrytere til noen fรฅ, noe som reduserer overhead pรฅ store datavolumer kraftig.

Ja. GitHub Copilot lager utkast til BULK COLLECT-hentinger, FORALL DML-lรธkker og LIMIT-klausuler fra en kommentar, og foreslรฅr deklarasjoner av samlingstyper, men du bรธr gjennomgรฅ batchstรธrrelser og feilhรฅndtering selv.

AI-assistenter skanner lรธkker som henter eller endrer รฉn rad om gangen og anbefaler รฅ skrive dem om med BULK COLLECT, LIMIT og FORALL. Denne maskinlรฆringsgjennomgangen fanger opp manglende LIMIT-grenser og ytelsesflaskehalser fรธr produksjon.

Oppsummer dette innlegget med: