Oracle PL/SQL-markör: implicit, explicit, för loop med exempel

⚡ Smart sammanfattning

Markörer i Oracle PL/SQL är pekare till det kontextområde som innehåller raderna som returneras av ett SQL-uttryck. Det finns två typer: implicita markörer, som skapas automatiskt för DML, och explicita markörer, som deklareras och kontrolleras av programmeraren.

  • 📍 Kontextområde: En markör pekar på det kontextområde som lagrar ett SQL-uttryck och dess returnerade aktiva uppsättning.
  • ⚙️ Implicit markör: Oracle öppnar automatiskt en implicit markör för varje DML-sats och enradig SELECT INTO.
  • Explicit markör: En programmerare deklarerar, öppnar, hämtar och stänger en explicit markör för full kontroll.
  • 🔎 Markörattribut: %FOUND, %NOTFOUND, %ISOPEN och %ROWCOUNT rapporterar statusen för den senaste åtgärden.
  • 🔁 Markör FÖR-slinga: En FOR-loop öppnar, hämtar och stänger en markör implicit, utan att behöva några manuella steg.
  • 🤖 AI-hjälp: AI-assistenter som GitHub Copilot utkastmarkörloopar och flaggar oavslutade markörer.

Oracle PL/SQL-markör, implicit, explicit och FOR-loop

Vad är CURSOR i PL/SQL?

En markör är en pekare till kontextområdet. Oracle skapar ett kontextområde för bearbetning av en SQL utdrag, och det här området innehåller all information om utdraget.

PL / SQL låter programmeraren styra kontextområdet med hjälp av markören. En markör innehåller de rader som returneras av SQL-satsen, och den mängd rader som markören innehåller kallas den aktiva mängden. Dessa markörer kan också namnges så att de kan refereras till från en annan plats i koden.

Markören är av två typer:

  • Implicit markör
  • Explicit markör

Implicit markör

Närhelst någon DML-operation inträffar i databasen skapas en implicit markör som innehåller de rader som påverkas av den specifika operationen. Dessa markörer kan inte namnges och kan därför inte styras eller refereras till från någon annan plats i koden. Vi kan bara referera till den senaste markören genom markörattributen.

Explicit markör

Programmerare får skapa ett namngivet kontextområde för att utföra sina DML-operationer och få mer kontroll över det. Den explicita markören bör definieras i deklarationsavsnittet av PL/SQL-block, och den skapas för SELECT-satsen som behöver användas i koden.

Nedan följer stegen som ingår i att arbeta med explicita markörer:

  • Deklarera markören: Att deklarera markören innebär helt enkelt att skapa ett namngivet kontextområde för SELECT-satsen som definieras i deklarationsdelen. Namnet på detta kontextområde är detsamma som markörens namn.
  • Öppna markören: Att öppna markören instruerar PL/SQL att allokera minne för denna markör. Det gör markören redo att hämta posterna.
  • Hämtar data från markören: I den här processen körs SELECT-satsen och de hämtade raderna lagras i det allokerade minnet. Dessa kallas nu aktiva mängder. Att hämta data från markören är en aktivitet på postnivå, vilket innebär att vi kan komma åt data post för post. Varje fetch-sats hämtar en aktiv mängd och innehåller informationen för just den posten. Denna sats är densamma som en SELECT-sats som hämtar posten och tilldelar den variabeln i INTO-satsen, men den kommer inte att utlösa några undantag.
  • Stänga markören: När alla poster har hämtats måste vi stänga markören så att minnet som allokerats till detta kontextområde frigörs.

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 syntaxen ovan innehåller deklarationsdelen deklarationen av markören och markörvariabeln till vilken den hämtade datan kommer att tilldelas. Markören skapas för SELECT-satsen som ges i markördeklarationen. I exekveringsdelen öppnas, hämtas och stängs den deklarerade markören.

Markörattribut

Både den implicita markören och den explicita markören har vissa attribut som är åtkomliga. Dessa attribut ger mer information om markörens operationer. Nedan följer de olika markörattributen och deras användning.

Markörattribut BESKRIVNING
%HITTADES Returnerar det booleska resultatet SANT om den senaste hämtningsoperationen hämtade en post utan problem; annars returnerar den FALSKT.
%HITTADES INTE Fungerar motsatsen till %FOUND. Returnerar TRUE om den senaste hämtningsoperationen inte kunde hämta någon post.
%ÄR ÖPPEN Returnerar det booleska resultatet SANT om den givna markören redan är öppen; annars returnerar den FALSKT.
% ROWCOUNT Returnerar ett numeriskt värde som anger det faktiska antalet poster som påverkats eller hämtats av operationen.

Exempel på explicit markör: I det här exemplet ska vi se hur man deklarerar, öppnar, hämtar och stänger en explicit markör. Vi kommer att projicera alla medarbetarnamn från emp-tabellen med hjälp av en markör. Vi kommer också att använda ett markörattribut för att ställa in loopen för att hämta alla poster från markören.

Skärmdumpen nedan visar detta explicita markörexempel och dess utdata i Oracle.

Explicit markörexempel som hämtar medarbetarnamn från anställningstabellen 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;
/

Produktion

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

Code Förklaring

  • Code rad 2: Deklarerar markören guru99_det för uttrycket 'SELECT anställd_namn FROM anställd'.
  • Code rad 3: Deklarera variabeln lv_emp_name med %typ förankrad till emp.emp_name.
  • Code rad 5: Öppnar markören guru99_det.
  • Code rad 6: Ställer in den grundläggande loop-satsen för att hämta alla poster i emp-tabellen.
  • Code rad 7: Hämtar guru99_det-data och tilldelar värdet till lv_emp_name.
  • Code rad 8: Använd markörattributet %NOTFOUND för att kontrollera om alla poster i markören hämtas. Om hämtat returnerar det TRUE och control avslutar loopen; annars fortsätter control att hämta data från markören och skriver ut dem.
  • Code rad 10: EXIT-villkor för loop-satsen.
  • Code rad 12: Skriv ut det hämtade medarbetarnamnet.
  • Code rad 14: Använd markörattributet %ROWCOUNT för att hitta det totala antalet poster som hämtats av markören.
  • Code rad 15: Efter att loopen har avslutats stängs markören och det allokerade minnet frigörs.

FOR Loop Cursor uttalande

En markör FÖR slinga kan användas för att arbeta med markörer. Vi kan ange markörens namn istället för en intervallgräns i FOR-loop-satsen, så att loopen arbetar från markörens första post till markörens sista post. Markörvariabeln, öppning av markören, hämtning och stängning av markören görs alla implicit av FOR-loopen.

syntax

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

I syntaxen ovan innehåller deklarationsdelen deklarationen av markören. Markören skapas för SELECT-satsen som ges i markördeklarationen. I exekveringsdelen ställs den deklarerade markören in i FOR-slingan, och loopvariabeln 'I' beter sig som markörvariabel i detta fall.

Oracle Markör för loopexempel: I det här exemplet projicerar vi alla medarbetarnamn från emp-tabellen med hjälp av en markör-FOR-loop.

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;
/

Produktion

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

Code Förklaring

  • Code rad 2: Deklarerar markören guru99_det för uttrycket 'SELECT anställd_namn FROM anställd'.
  • Code rad 4: Konstruera FOR-slingan för markören med loopvariabeln lv_emp_name.
  • Code rad 6: Skriver ut anställds namn i varje iteration av loopen.
  • Code rad 7: Avsluta loopen (SLUT LOOP).

Obs: I en cursor-FOR-loop kan cursorattribut inte användas, eftersom öppning, hämtning och stängning av markören görs implicit av FOR-loopen.

Vanliga frågor

En REF-MARKÖR (markörvariabel) är en pekare till en frågeresultatmängd. Till skillnad från en statisk markör kan den öppna olika frågor vid körning och skicka resultat mellan PL/SQL-block eller till klientprogram.

En vanlig markör hämtar en rad per HÄMTNING, vilket orsakar många kontextväxlingar. MASSAMLA laddar många rader i en samling i en enda hämtning, vilket minskar kostnaden kraftigt för stora resultatmängder.

Ja. Deklarera en parametriserad markör som CURSOR c(dept NUMBER) IS SELECT …, och skicka sedan värden vid OPEN c(10). Parametrar låter dig återanvända en markördefinition med olika filtervärden.

FOR UPDATE låser raderna som en markör väljer så att ingen annan kan ändra dem. WHERE CURRENT OF uppdaterar eller tar sedan bort exakt den rad som just hämtades, utan att upprepa WHERE-villkoret.

Öppna markörer behåller sitt minne reserverat och räknas mot OPEN_CURSORS-gränsen. Om många öppna markörer lämnas öppna höjs ORA-01000: maximalt antal öppna markörer har överskridits, så STÄNG alltid en explicit markör efter användning.

Varje FETCH växlar mellan PL/SQL- och SQL-motorerna. Tusentals sådana kontextväxlar läggs till, så ett enda setbaserat SQL-uttryck eller BULK COLLECT bearbetar vanligtvis samma rader mycket snabbare.

Ja. GitHub Copilot utarbetar explicita OPEN-, FETCH- och CLOSE-loopar eller markörens FOR-loopar från en kommentar, lägger till %NOTFOUND-avslutningskontroller och föreslår attributnamn, men du bör granska logiken först.

AI-assistenter flaggar rad-för-rad-markörloopar som kan bli setbaserade SQL- eller BULK COLLECT-markörer, identifierar oavslutade markörer och förklarar %attributbeteendet. Denna maskininlärningsgranskning förbättrar prestandan innan koden når produktion.

Sammanfatta detta inlägg med: