Oracle Kursor PL/SQL: niejawny, jawny, pętla For z przykładem

⚡ Inteligentne podsumowanie

Kursory w Oracle PL/SQL to wskaźniki do obszaru kontekstu, który przechowuje wiersze zwrócone przez instrukcję SQL. Istnieją dwa rodzaje kursorów: kursory niejawne, tworzone automatycznie dla języka DML, oraz kursory jawne, deklarowane i kontrolowane przez programistę.

  • 📍 Obszar kontekstu: Kursor wskazuje na obszar kontekstu, w którym przechowywane jest polecenie SQL i zwrócony aktywny zestaw.
  • ⚙️ Niejawny kursor: Oracle automatycznie otwiera niejawny kursor dla każdego polecenia DML i jednowierszowego polecenia SELECT INTO.
  • Jawny kursor: Programista deklaruje, otwiera, pobiera i zamyka konkretny kursor, aby uzyskać pełną kontrolę.
  • 🔎 Atrybuty kursora: %FOUND, %NOTFOUND, %ISOPEN i %ROWCOUNT raportują stan ostatniej operacji.
  • 🔁 Pętla kursora FOR: Pętla FOR otwiera, pobiera i zamyka kursor w sposób niejawny, bez konieczności wykonywania żadnych czynności manualnych.
  • 🤖 Pomoc AI: Asystenci AI, tacy jak GitHub Copilot, tworzą pętle kursorów i oznaczają niezamknięte kursory.

Oracle Kursor PL/SQL niejawny, jawny i pętla FOR

Co to jest KURSOR w PL/SQL?

Kursor jest wskaźnikiem obszaru kontekstowego. Oracle tworzy obszar kontekstowy do przetwarzania SQL oświadczenie, a ten obszar zawiera wszystkie informacje na temat oświadczenia.

PL / SQL Umożliwia programiście sterowanie obszarem kontekstu za pomocą kursora. Kursor przechowuje wiersze zwrócone przez instrukcję SQL, a zbiór wierszy, który zawiera kursor, nazywany jest zbiorem aktywnym. Kursory te można również nazwać, aby można było się do nich odwoływać z innego miejsca w kodzie.

Istnieją dwa typy kursorów:

  • Niejawny kursor
  • Jawny kursor

Niejawny kursor

Kiedykolwiek Operacja DML W przypadku wystąpienia zdarzenia w bazie danych tworzony jest niejawny kursor, który przechowuje wiersze objęte daną operacją. Kursory te nie mogą mieć nazw, a zatem nie można nimi sterować ani odwoływać się do nich z innego miejsca w kodzie. Możemy odwołać się tylko do najnowszego kursora za pomocą atrybutów kursora.

Jawny kursor

Programiści mogą tworzyć nazwany obszar kontekstu, aby wykonywać operacje DML i uzyskać nad nim większą kontrolę. Jawny kursor powinien być zdefiniowany w sekcji deklaracji. Blok PL/SQLi jest tworzony dla instrukcji SELECT, która ma zostać użyta w kodzie.

Poniżej przedstawiono kroki dotyczące pracy z jawnymi kursorami:

  • Deklarowanie kursora: Deklaracja kursora oznacza po prostu utworzenie jednego nazwanego obszaru kontekstu dla instrukcji SELECT zdefiniowanej w części deklaracyjnej. Nazwa tego obszaru kontekstu jest taka sama jak nazwa kursora.
  • Otwieranie kursora: Otwarcie kursora powoduje, że PL/SQL przydziela pamięć dla tego kursora. Dzięki temu kursor jest gotowy do pobrania rekordów.
  • Pobieranie danych z kursora: W tym procesie wykonywana jest instrukcja SELECT, a pobrane wiersze są zapisywane w przydzielonej pamięci. Nazywa się je teraz aktywnymi zestawami. Pobieranie danych z kursora to czynność na poziomie rekordu, co oznacza, że ​​możemy uzyskiwać do nich dostęp rekord po rekordzie. Każda instrukcja pobierania pobiera jeden aktywny zestaw i przechowuje informacje o tym konkretnym rekordzie. Ta instrukcja działa tak samo jak instrukcja SELECT, która pobiera rekord i przypisuje go do zmiennej w klauzuli INTO, ale nie generuje żadnego wyjątku. wyjątki.
  • Zamknięcie kursora: Po pobraniu wszystkich rekordów należy zamknąć kursor, aby zwolnić pamięć przydzieloną temu obszarowi kontekstu.

Składnia

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

W powyższej składni część deklaracji zawiera deklarację kursora oraz zmienną kursora, do której zostaną przypisane pobrane dane. Kursor jest tworzony dla instrukcji SELECT podanej w deklaracji kursora. W części wykonania zadeklarowany kursor jest otwierany, pobierany i zamykany.

Atrybuty kursora

Zarówno kursor niejawny, jak i kursor jawny mają pewne atrybuty, do których można uzyskać dostęp. Atrybuty te dostarczają więcej informacji o operacjach kursora. Poniżej przedstawiono różne atrybuty kursora i ich zastosowanie.

Atrybut kursora OPIS
%UZNANY Zwraca wynik logiczny TRUE, jeśli ostatnia operacja pobierania zakończyła się pomyślnym pobraniem rekordu; w przeciwnym razie zwraca FALSE.
%NIE ZNALEZIONO Działa odwrotnie niż %FOUND. Zwraca wartość TRUE, jeśli ostatnia operacja pobierania nie pobrała żadnego rekordu.
%JEST OTWARTE Zwraca wynik logiczny TRUE, jeśli dany kursor jest już otwarty; w przeciwnym razie zwraca FALSE.
% ROWCOUNT Zwraca wartość liczbową podającą rzeczywistą liczbę rekordów objętych lub pobranych przez operację.

Przykład jawnego kursora: W tym przykładzie pokażemy, jak zadeklarować, otworzyć, pobrać i zamknąć jawny kursor. Za pomocą kursora wyświetlimy wszystkie nazwiska pracowników z tabeli emp. Użyjemy również atrybutu kursora, aby ustawić pętlę tak, aby pobierała wszystkie rekordy z kursora.

Poniższy zrzut ekranu pokazuje przykład tego jawnego kursora i jego wynik Oracle.

Przykład jawnego kursora pobierającego nazwiska pracowników z tabeli emp w 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;
/

Wydajność

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

Code Wyjaśnienie

  • Code linia 2: Deklaracja kursora guru99_det dla polecenia „SELECT emp_name FROM emp”.
  • Code linia 3: Deklarowanie zmiennej lv_emp_name za pomocą %rodzaj zakotwiczone w emp.emp_name.
  • Code linia 5: Otwieranie kursora guru99_det.
  • Code linia 6: Ustawienie podstawowego polecenia pętli w celu pobrania wszystkich rekordów w tabeli emp.
  • Code linia 7: Pobiera dane guru99_det i przypisuje wartość do lv_emp_name.
  • Code linia 8: Używając atrybutu kursora %NOTFOUND, sprawdza, czy wszystkie rekordy w kursorze zostały pobrane. Jeśli pobrane, zwraca wartość TRUE i sterowanie wychodzi z pętli; w przeciwnym razie sterowanie kontynuuje pobieranie danych z kursora i wyświetla je.
  • Code linia 10: Warunek EXIT dla instrukcji pętli.
  • Code linia 12: Wydrukuj pobrane nazwisko pracownika.
  • Code linia 14: Korzystając z atrybutu kursora %ROWCOUNT, można znaleźć całkowitą liczbę rekordów pobranych przez kursor.
  • Code linia 15: Po wyjściu z pętli kursor zostaje zamknięty, a przydzielona pamięć zostaje zwolniona.

Instrukcja kursora pętli FOR

Kursor Dla pętli Można go używać do pracy z kursorami. Zamiast limitu zakresu w instrukcji pętli FOR możemy podać nazwę kursora, dzięki czemu pętla będzie działać od pierwszego do ostatniego rekordu kursora. Zmienna kursora, otwieranie kursora, pobieranie i zamykanie kursora są wykonywane niejawnie przez pętlę FOR.

Składnia

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

W powyższej składni część deklaracji zawiera deklarację kursora. Kursor jest tworzony dla instrukcji SELECT podanej w deklaracji kursora. W części wykonawczej zadeklarowany kursor jest ustawiany w pętli FOR, a zmienna pętli „I” zachowuje się w tym przypadku jak zmienna kursora.

Oracle Przykład pętli kursora: W tym przykładzie wyświetlimy wszystkie nazwiska pracowników z tabeli emp za pomocą pętli FOR-kursor.

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

Wydajność

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

Code Wyjaśnienie

  • Code linia 2: Deklaracja kursora guru99_det dla polecenia „SELECT emp_name FROM emp”.
  • Code linia 4: Konstruowanie pętli FOR dla kursora ze zmienną pętli lv_emp_name.
  • Code linia 6: Drukowanie nazwiska pracownika w każdej iteracji pętli.
  • Code linia 7: Wyjdź z pętli (KONIEC PĘTLI).

Uwaga: W pętli FOR kursora nie można używać atrybutów kursora, ponieważ otwieranie, pobieranie i zamykanie kursora jest wykonywane niejawnie przez pętlę FOR.

FAQ

KURSOR REF (zmienna kursora) to wskaźnik do zestawu wyników zapytania. W przeciwieństwie do kursora statycznego, może otwierać różne zapytania w czasie wykonywania i przekazywać wyniki między blokami PL/SQL lub do programów klienckich.

Zwykły kursor pobiera jeden wiersz na raz, co powoduje wiele przełączeń kontekstu. ZBIÓRKA ZBIOROWA ładuje wiele wierszy do kolekcji podczas jednego pobrania, znacznie zmniejszając obciążenie w przypadku dużych zestawów wyników.

Tak. Zadeklaruj sparametryzowany kursor, taki jak CURSOR c(dept NUMBER) IS SELECT …, a następnie przekaż wartości w OPEN c(10). Parametry pozwalają na ponowne użycie jednej definicji kursora z różnymi wartościami filtru.

Instrukcja FOR UPDATE blokuje wiersze wybrane przez kursor, aby nikt inny nie mógł ich zmienić. Instrukcja WHERE CURRENT OF aktualizuje lub usuwa dokładnie pobrany wiersz, nie powtarzając warunku WHERE.

Otwarte kursory zachowują zarezerwowaną pamięć i są wliczane do limitu OPEN_CURSORS. Pozostawienie wielu otwartych kursorów ostatecznie powoduje błąd ORA-01000: przekroczono maksymalną liczbę otwartych kursorów, dlatego zawsze ZAMKNIJ jawny kursor po jego użyciu.

Każde polecenie FETCH przełącza między silnikami PL/SQL i SQL. Tysiące takich przełączeń kontekstowych sumują się, więc pojedyncza instrukcja SQL oparta na zbiorze lub polecenie BULK COLLECT zazwyczaj przetwarza te same wiersze znacznie szybciej.

Tak. Drugi pilot GitHub tworzy wyraźne pętle OPEN, FETCH i CLOSE lub pętle kursora FOR z komentarza, dodaje sprawdzenia wyjścia %NOTFOUND i sugeruje nazwy atrybutów, choć najpierw należy przejrzeć logikę.

Asystenci AI sygnalizują pętle kursora wiersz po wierszu, które mogą stać się oparte na zbiorach SQL lub BULK COLLECT, wykrywają niedomknięte kursory i wyjaśniają zachowanie %attribute. Ta analiza uczenia maszynowego poprawia wydajność, zanim kod trafi do produkcji.

Podsumuj ten post następująco: