Oracle PL/SQL-cursor: impliciet, expliciet, for-lus met voorbeeld

โšก Slimme samenvatting

Cursors in Oracle PL/SQL-cursors verwijzen naar het contextgebied dat de rijen bevat die door een SQL-statement worden geretourneerd. Er bestaan โ€‹โ€‹twee soorten: impliciete cursors, die automatisch worden aangemaakt voor DML-bewerkingen, en expliciete cursors, die door de programmeur worden gedeclareerd en beheerd.

  • ๐Ÿ“ Contextgebied: Een cursor wijst naar het contextgebied waarin een SQL-instructie en de bijbehorende actieve set zijn opgeslagen.
  • โš™๏ธ Impliciete cursor: Oracle Opent automatisch een impliciete cursor voor elke DML-instructie en SELECT INTO-query met รฉรฉn rij.
  • โœ‹ Expliciete cursor: Een programmeur declareert, opent, haalt op en sluit een expliciete cursor voor volledige controle.
  • ๐Ÿ”Ž Cursorkenmerken: %FOUND, %NOTFOUND, %ISOPEN en %ROWCOUNT geven de status van de meest recente bewerking weer.
  • ๐Ÿ” Cursor FOR-lus: Een FOR-lus opent, haalt op en sluit een cursor impliciet, zonder dat er handmatige stappen nodig zijn.
  • ๐Ÿค– AI-assistentie: AI-assistenten zoals GitHub Copilot genereren cursorloops en markeren niet-gesloten cursors.

Oracle PL/SQL Cursor Impliciet Expliciet en FOR-lus

Wat is CURSOR in PL/SQL?

Een cursor is een aanwijzer naar het contextgebied. Oracle creรซert een contextgebied voor de verwerking van een SQL verklaring, en dit gedeelte bevat alle informatie over die verklaring.

PL / SQL Hiermee kan de programmeur het contextgebied beheren via de cursor. Een cursor bevat de rijen die door de SQL-instructie worden geretourneerd, en de set rijen die de cursor bevat, wordt de actieve set genoemd. Deze cursors kunnen ook een naam krijgen, zodat ernaar kan worden verwezen vanuit een andere plaats in de code.

De cursor is er in twee typen:

  • Impliciete cursor
  • Expliciete cursor

Impliciete cursor

Wanneer dan ook DML-bewerking Wanneer een bewerking in de database plaatsvindt, wordt een impliciete cursor aangemaakt die de rijen bevat die bij die specifieke bewerking betrokken zijn. Deze cursors kunnen niet worden benoemd en kunnen daarom niet worden beheerd of aangeroepen vanuit een andere plek in de code. We kunnen alleen naar de meest recente cursor verwijzen via de cursorattributen.

Expliciete cursor

Programmeurs mogen een benoemd contextgebied creรซren om hun DML-bewerkingen uit te voeren en er meer controle over te krijgen. De expliciete cursor moet worden gedefinieerd in het declaratiegedeelte van de code. PL/SQL-blokHet is bedoeld voor de SELECT-instructie die in de code gebruikt moet worden.

Hieronder volgen de stappen die nodig zijn om met expliciete cursors te werken:

  • De cursor declareren: Het declareren van de cursor betekent simpelweg het creรซren van een benoemd contextgebied voor de SELECT-instructie die in het declaratiegedeelte is gedefinieerd. De naam van dit contextgebied is gelijk aan de naam van de cursor.
  • De cursor openen: Door de cursor te openen, geeft u PL/SQL de opdracht om geheugen voor deze cursor toe te wijzen. Hierdoor is de cursor klaar om de records op te halen.
  • Gegevens ophalen uit de cursor: Tijdens dit proces wordt de SELECT-instructie uitgevoerd en worden de opgehaalde rijen opgeslagen in het toegewezen geheugen. Deze worden nu actieve sets genoemd. Het ophalen van gegevens uit de cursor is een activiteit op recordniveau, wat betekent dat we de gegevens record voor record kunnen benaderen. Elke fetch-instructie haalt รฉรฉn actieve set op en bevat de informatie van dat specifieke record. Deze instructie is hetzelfde als een SELECT-instructie die het record ophaalt en toewijst aan de variabele in de INTO-clausule, maar er wordt geen foutmelding gegenereerd. uitzonderingen.
  • De cursor sluiten: Zodra alle records zijn opgehaald, moeten we de cursor sluiten zodat het geheugen dat aan dit contextgebied is toegewezen, wordt vrijgegeven.

Syntaxis

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

In de bovenstaande syntaxis bevat het declaratiegedeelte de declaratie van de cursor en de cursorvariabele waaraan de opgehaalde gegevens worden toegewezen. De cursor wordt aangemaakt voor de SELECT-instructie die in de cursordeclaratie is opgegeven. In het uitvoeringsgedeelte wordt de gedeclareerde cursor geopend, worden de gegevens opgehaald en wordt de cursor gesloten.

Cursorkenmerken

Zowel de impliciete als de expliciete cursor hebben bepaalde attributen die toegankelijk zijn. Deze attributen geven meer informatie over de cursorbewerkingen. Hieronder staan โ€‹โ€‹de verschillende cursorattributen en hun gebruik.

Cursorkenmerk Beschrijving
% GEVONDEN Geeft de Booleaanse waarde TRUE terug als de meest recente ophaalbewerking een record succesvol heeft opgehaald; anders retourneert deze FALSE.
%NIET GEVONDEN Werkt tegengesteld aan %FOUND. Het retourneert TRUE als de meest recente ophaalbewerking geen records heeft kunnen vinden.
%IS GEOPEND Geeft de Booleaanse waarde TRUE terug als de opgegeven cursor al geopend is; anders retourneert deze FALSE.
%AANTAL RIJEN Retourneert een numerieke waarde die het werkelijke aantal records aangeeft dat door de bewerking is beรฏnvloed of opgehaald.

Expliciet cursorvoorbeeld: In dit voorbeeld laten we zien hoe je een expliciete cursor declareert, opent, ophaalt en sluit. We projecteren alle werknemersnamen uit de tabel 'emp' met behulp van een cursor. We gebruiken ook een cursorattribuut om de lus in te stellen die alle records uit de cursor ophaalt.

De onderstaande schermafbeelding toont dit expliciete cursorvoorbeeld en de bijbehorende uitvoer. Oracle.

Expliciet cursorvoorbeeld voor het ophalen van werknemersnamen uit de tabel 'emp' in 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;
/

uitgang

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

Code Uitleg

  • Code lijn 2: De cursor guru99_det wordt gedeclareerd voor de instructie 'SELECT emp_name FROM emp'.
  • Code lijn 3: De variabele lv_emp_name declareren met de %type verankerd aan emp.emp_name.
  • Code lijn 5: De cursor openen guru99_det.
  • Code lijn 6: De basislus instellen om alle records in de tabel 'emp' op te halen.
  • Code lijn 7: Haalt de guru99_det-gegevens op en kent de waarde toe aan lv_emp_name.
  • Code lijn 8: Met behulp van het cursorattribuut %NOTFOUND wordt gecontroleerd of alle records in de cursor zijn opgehaald. Indien opgehaald, retourneert het TRUE en verlaat de lus; anders blijft de besturing de gegevens uit de cursor ophalen en afdrukken.
  • Code lijn 10: EXIT-voorwaarde voor de lusinstructie.
  • Code lijn 12: Druk de opgehaalde werknemersnaam af.
  • Code lijn 14: Gebruik het cursorattribuut %ROWCOUNT om het totale aantal records te vinden dat door de cursor is opgehaald.
  • Code lijn 15: Na het verlaten van de lus wordt de cursor gesloten en het toegewezen geheugen vrijgegeven.

FOR Loop Cursor-instructie

Een cursor For loop Dit kan gebruikt worden voor het werken met cursors. We kunnen de cursornaam opgeven in plaats van een bereiklimiet in de FOR-lus, zodat de lus loopt van het eerste tot het laatste record van de cursor. De cursorvariabele, het openen van de cursor, het ophalen en het sluiten van de cursor worden allemaal impliciet door de FOR-lus afgehandeld.

Syntaxis

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

In de bovenstaande syntaxis bevat het declaratiegedeelte de declaratie van de cursor. De cursor wordt aangemaakt voor de SELECT-instructie die in de cursordeclaratie is opgegeven. In het uitvoeringsgedeelte wordt de gedeclareerde cursor ingesteld in de FOR-lus, waarbij de lusvariabele 'I' in dit geval fungeert als cursorvariabele.

Oracle Cursor for-lusvoorbeeld: In dit voorbeeld projecteren we alle werknemersnamen uit de tabel 'emp' met behulp van een cursor-FOR-lus.

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

uitgang

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

Code Uitleg

  • Code lijn 2: De cursor guru99_det wordt gedeclareerd voor de instructie 'SELECT emp_name FROM emp'.
  • Code lijn 4: Het construeren van de FOR-lus voor de cursor met de lusvariabele lv_emp_name.
  • Code lijn 6: Het afdrukken van de naam van de werknemer in elke iteratie van de lus.
  • Code lijn 7: Verlaat de lus (END LOOP).

Let op: In een cursor-FOR-lus kunnen cursorattributen niet worden gebruikt, omdat het openen, ophalen en sluiten van de cursor impliciet door de FOR-lus gebeurt.

Veelgestelde vragen

Een REF CURSOR (cursorvariabele) is een aanwijzer naar een queryresultaatset. In tegenstelling tot een statische cursor kan deze tijdens de uitvoering verschillende query's openen en resultaten doorgeven tussen PL/SQL-blokken of aan clientprogramma's.

Een normale cursor haalt รฉรฉn rij per FETCH op, wat veel contextwisselingen veroorzaakt. BULK VERZAMELEN Laadt veel rijen in รฉรฉn keer in een verzameling, waardoor de overhead bij grote resultaatsets aanzienlijk wordt verminderd.

Ja. Declareer een geparameteriseerde cursor, bijvoorbeeld CURSOR c(dept NUMBER) IS SELECT โ€ฆ, en geef vervolgens waarden door bij OPEN c(10). Parameters stellen u in staat om รฉรฉn cursordefinitie te hergebruiken met verschillende filterwaarden.

FOR UPDATE vergrendelt de rijen die een cursor selecteert, zodat niemand anders ze kan wijzigen. WHERE CURRENT OF werkt vervolgens de zojuist opgehaalde exacte rij bij of verwijdert deze, zonder de WHERE-voorwaarde te herhalen.

Open cursors behouden hun geheugen en tellen mee voor de OPEN_CURSORS-limiet. Het open laten van veel cursors kan uiteindelijk leiden tot ORA-01000: maximum open cursors exceeded, dus sluit altijd een expliciete cursor na gebruik.

Elke FETCH-bewerking schakelt tussen de PL/SQL- en SQL-engines. Duizenden van zulke contextwisselingen tellen op, waardoor een enkele setgebaseerde SQL-instructie of BULK COLLECT dezelfde rijen doorgaans veel sneller verwerkt.

Ja. GitHub-copiloot Het programma ontwerpt expliciete OPEN-, FETCH- en CLOSE-lussen of cursor-FOR-lussen op basis van een opmerking, voegt %NOTFOUND-uitgangscontroles toe en suggereert attribuutnamen, hoewel u de logica eerst moet controleren.

AI-assistenten signaleren cursorlussen die rij voor rij doorlopen en mogelijk leiden tot setgebaseerde SQL of BULK COLLECT, sporen niet-gesloten cursors op en leggen het gedrag van %attributen uit. Deze machine learning-review verbetert de prestaties voordat de code in productie wordt genomen.

Vat dit bericht samen met: