Oracle PL/SQL-markør: implisitt, eksplisitt, for sløyfe med eksempel

⚡ Smart oppsummering

Markører i Oracle PL/SQL er pekere til kontekstområdet som inneholder radene som returneres av en SQL-setning. Det finnes to typer: implisitte markører, som opprettes automatisk for DML, og eksplisitte markører, som deklareres og kontrolleres av programmereren.

  • 📍 Kontekstområde: En markør peker på kontekstområdet som lagrer en SQL-setning og det returnerte aktive settet.
  • ⚙️ Implisitt markør: Oracle åpner en implisitt markør automatisk for hver DML-setning og SELECT INTO på én rad.
  • Eksplisitt markør: En programmerer deklarerer, åpner, henter og lukker en eksplisitt markør for full kontroll.
  • 🔎 Markørattributter: %FOUND, %NOTFOUND, %ISOPEN og %ROWCOUNT rapporterer statusen til den siste operasjonen.
  • 🔁 Markør FOR-løkke: En FOR-løkke åpner, henter og lukker en markør implisitt, uten behov for manuelle trinn.
  • 🤖 AI-hjelp: AI-assistenter som GitHub Copilot utkastmarkørløkker og flagger ikke-lukkede markører.

Oracle PL/SQL-markør, implisitt, eksplisitt og FOR-løkke

Hva er CURSOR i PL/SQL?

En markør er en peker til kontekstområdet. Oracle oppretter et kontekstområde for behandling av en SQL utsagn, og dette området inneholder all informasjon om utsagnet.

PL / SQL lar programmereren kontrollere kontekstområdet gjennom markøren. En markør inneholder radene som returneres av SQL-setningen, og settet med rader markøren inneholder kalles det aktive settet. Disse markørene kan også navngis slik at de kan refereres til fra et annet sted i koden.

Markøren er av to typer:

  • Implisitt markør
  • Eksplisitt markør

Implisitt markør

Når som helst DML-operasjon skjer i databasen, opprettes en implisitt markør som inneholder radene som er berørt i den bestemte operasjonen. Disse markørene kan ikke navngis, og de kan derfor ikke kontrolleres eller refereres til fra et annet sted i koden. Vi kan bare referere til den nyeste markøren gjennom markørattributtene.

Eksplisitt markør

Programmerere har lov til å opprette et navngitt kontekstområde for å utføre DML-operasjonene sine og få mer kontroll over det. Den eksplisitte markøren bør defineres i deklarasjonsdelen av PL/SQL-blokk, og den er opprettet for SELECT-setningen som må brukes i koden.

Nedenfor er trinnene som er involvert i å jobbe med eksplisitte markører:

  • Deklarere markøren: Å deklarere markøren betyr ganske enkelt å opprette et navngitt kontekstområde for SELECT-setningen som er definert i deklarasjonsdelen. Navnet på dette kontekstområdet er det samme som markørnavnet.
  • Åpne markøren: Når markøren åpnes, instrueres PL/SQL til å allokere minne til denne markøren. Dette gjør markøren klar til å hente postene.
  • Henter data fra markøren: I denne prosessen utføres SELECT-setningen, og de hentede radene lagres i det tildelte minnet. Disse kalles nå aktive sett. Henting av data fra markøren er en aktivitet på postnivå, som betyr at vi kan få tilgang til dataene post for post. Hver hentesetning henter ett aktivt sett og inneholder informasjonen om den bestemte posten. Denne setningen er den samme som en SELECT-setning som henter posten og tilordner den til variabelen i INTO-klausulen, men den vil ikke kaste noen unntak.
  • Lukking av markøren: Når alle postene er hentet, må vi lukke markøren slik at minnet som er tildelt dette kontekstområdet frigjøres.

syntax

DECLARE
CURSOR <cursor_name> IS <SELECT statement>;
<cursor_variable declaration>;
BEGIN
OPEN <cursor_name>;
FETCH <cursor_name> INTO <cursor_variable>;
.
.
CLOSE <cursor_name>;
END;

I syntaksen ovenfor inneholder deklarasjonsdelen deklarasjonen av markøren og markørvariabelen som de hentede dataene skal tilordnes til. Markøren opprettes for SELECT-setningen som er gitt i markørdeklarasjonen. I utførelsesdelen åpnes, hentes og lukkes den deklarerte markøren.

Markørattributter

Både den implisitte markøren og den eksplisitte markøren har visse attributter som er tilgjengelige. Disse attributtene gir mer informasjon om markøroperasjonene. Nedenfor finner du de forskjellige markørattributtene og bruken av dem.

Markørattributt Tekniske beskrivelser
%FANT Returnerer det boolske resultatet SANN hvis den siste henteoperasjonen hentet en post; ellers returnerer den USANN.
%IKKE FUNNET Fungerer motsatt av %FOUND. Den returnerer TRUE hvis den siste henteoperasjonen ikke kunne hente noen poster.
%ISOPEN Returnerer det boolske resultatet SANN hvis den gitte markøren allerede er åpen; ellers returneres USANN.
%ROWCOUNT Returnerer en numerisk verdi som gir det faktiske antallet poster som er påvirket eller hentet av operasjonen.

Eksempel på eksplisitt markør: I dette eksemplet skal vi se hvordan man deklarerer, åpner, henter og lukker en eksplisitt markør. Vi vil projisere alle ansattnavnene fra emp-tabellen ved hjelp av en markør. Vi vil også bruke et markørattributt for å angi at løkken skal hente alle postene fra markøren.

Skjermbildet nedenfor viser dette eksplisitte markøreksemplet og utdataene i Oracle.

Eksplisitt markøreksempel som henter ansattnavn fra emp-tabellen i Oracle PL / SQL

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
lv_emp_name emp.emp_name%type;
BEGIN
OPEN guru99_det;
LOOP
FETCH guru99_det INTO lv_emp_name;
IF guru99_det%NOTFOUND
THEN
EXIT;
END IF;
Dbms_output.put_line('Employee Fetched:'||lv_emp_name);
END LOOP;
Dbms_output.put_line('Total rows fetched is'||guru99_det%ROWCOUNT);
CLOSE guru99_det;
END;
/

Produksjon

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY
Total rows fetched is 3

Code Forklaring

  • Code linje 2: Deklarerer markøren guru99_det for setningen 'SELECT emp_name FROM emp'.
  • Code linje 3: Deklarering av variabelen lv_emp_name med %type forankret til emp.emp_name.
  • Code linje 5: Åpner markøren guru99_det.
  • Code linje 6: Setter den grunnleggende løkkesetningen for å hente alle postene i emp-tabellen.
  • Code linje 7: Henter guru99_det-dataene og tilordner verdien til lv_emp_name.
  • Code linje 8: Bruk markørattributtet %NOTFOUND til å sjekke om alle poster i markøren er hentet. Hvis hentet, returneres TRUE og kontroll avslutter løkken; ellers fortsetter kontroll å hente dataene fra markøren og skriver dem ut.
  • Code linje 10: EXIT-betingelse for loop-setningen.
  • Code linje 12: Skriv ut det hentede medarbeidernavnet.
  • Code linje 14: Bruk markørattributtet %ROWCOUNT til å finne det totale antallet poster hentet av markøren.
  • Code linje 15: Etter at løkken er avsluttet, lukkes markøren og det tildelte minnet frigjøres.

FOR Loop Cursor statement

En markør FOR løkke kan brukes til å jobbe med markører. Vi kan gi markørnavnet i stedet for en områdegrense i FOR-løkkesetningen, slik at løkken fungerer fra den første posten til markøren til den siste posten. Markørvariabelen, åpning av markøren, henting og lukking av markøren gjøres implisitt av FOR-løkken.

syntax

DECLARE
CURSOR <cursor_name> IS <SELECT statement>;
BEGIN
FOR I IN <cursor_name>
LOOP
.
.
END LOOP;
END;

I syntaksen ovenfor inneholder deklarasjonsdelen deklarasjonen av markøren. Markøren opprettes for SELECT-setningen som er gitt i markørdeklarasjonen. I utførelsesdelen settes den deklarerte markøren opp i FOR-løkken, og løkkevariabelen 'I' oppfører seg som markørvariabel i dette tilfellet.

Oracle Eksempel på markør for løkke: I dette eksemplet vil vi projisere alle ansattnavnene fra emp-tabellen ved hjelp av en markør-FOR-løkke.

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
BEGIN
FOR lv_emp_name IN guru99_det
LOOP
Dbms_output.put_line('Employee Fetched:'||lv_emp_name.emp_name);
END LOOP;
END;
/

Produksjon

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY

Code Forklaring

  • Code linje 2: Deklarerer markøren guru99_det for setningen 'SELECT emp_name FROM emp'.
  • Code linje 4: Konstruerer FOR-løkken for markøren med løkkevariabelen lv_emp_name.
  • Code linje 6: Skrive ut den ansattes navn i hver iterasjon av loopen.
  • Code linje 7: Avslutt løkken (SLUTT LOOP).

OBS: I en markør-FOR-løkke kan ikke markørattributter brukes, siden åpning, henting og lukking av markøren gjøres implisitt av FOR-løkken.

Spørsmål og svar

En REF-MARKØR (markørvariabel) er en peker til et resultatsett for en spørring. I motsetning til en statisk markør kan den åpne forskjellige spørringer under kjøring og sende resultater mellom PL/SQL-blokker eller til klientprogrammer.

En vanlig markør henter én rad per HENTING, noe som forårsaker mange kontekstbytter. MASSESAMLING laster mange rader inn i en samling i én henting, noe som reduserer kostnaden kraftig på store resultatsett.

Ja. Deklarer en parameterisert markør som CURSOR c(dept NUMBER) IS SELECT …, og send deretter verdier ved OPEN c(10). Parametere lar deg gjenbruke én markørdefinisjon med forskjellige filterverdier.

FOR UPDATE låser radene en markør velger, slik at ingen andre kan endre dem. WHERE CURRENT OF oppdaterer eller sletter deretter den nøyaktige raden som nettopp ble hentet, uten å gjenta WHERE-betingelsen.

Åpne markører beholder minnet sitt reservert og teller mot OPEN_CURSORS-grensen. Å la mange åpne øker til slutt ORA-01000: maksimalt antall åpne markører overskredet, så LUKK alltid en eksplisitt markør etter bruk.

Hver FETCH veksler mellom PL/SQL- og SQL-motorene. Tusenvis av slike kontekstbrytere summerer seg, så en enkelt settbasert SQL-setning eller BULK COLLECT behandler vanligvis de samme radene mye raskere.

Ja. GitHub Copilot lager utkast til eksplisitte OPEN-, FETCH- og CLOSE-løkker eller markør-FOR-løkker fra en kommentar, legger til %NOTFOUND-avslutningskontroller og foreslår attributtnavn, men du bør gjennomgå logikken først.

AI-assistenter flagger rad-for-rad-markørløkker som kan bli settbasert SQL eller BULK COLLECT, oppdager ikke-lukkede markører og forklarer %attributt-oppførsel. Denne maskinlæringsgjennomgangen forbedrer ytelsen før koden når produksjon.

Oppsummer dette innlegget med: