Oracle PL/SQL курсор: имплицитно, явно, For Loop с пример

⚡ Умно обобщение

Курсори в Oracle PL/SQL са указатели към контекстната област, която съдържа редовете, върнати от SQL оператор. Съществуват два вида: имплицитни курсори, създадени автоматично за DML, и експлицитни курсори, декларирани и контролирани от програмиста.

  • 📍 Контекстна област: Курсорът сочи към контекстната област, която съхранява SQL оператор и върнатия от него активен набор.
  • ️ Имплицитен курсор: Oracle отваря имплицитен курсор автоматично за всеки DML оператор и едноредов SELECT INTO.
  • ✋ Изричен курсор: Програмистът декларира, отваря, извлича и затваря експлицитен курсор за пълен контрол.
  • ???? Атрибути на курсора: %FOUND, %NOTFOUND, %ISOPEN и %ROWCOUNT отчитат състоянието на най-скорошната операция.
  • 🔁 Курсор FOR цикъл: Цикълът FOR отваря, извлича и затваря курсора имплицитно, без да е необходимо ръчно изпълнение.
  • 🤖 AI помощ: AI асистенти, като например GitHub Copilot, създават цикли на курсора в чернова и маркират незатворени курсори.

Oracle PL/SQL курсор, имплицитен, експлицитен и FOR цикъл

Какво е CURSOR в PL/SQL?

Курсорът е указател към контекстната област. Oracle създава контекстна област за обработка на SQL изявление и тази област съдържа цялата информация за изявлението.

PL / SQL позволява на програмиста да контролира контекстната област чрез курсора. Курсорът съдържа редовете, върнати от SQL оператора, а наборът от редове, които курсорът съдържа, се нарича активен набор. Тези курсори могат също да бъдат именувани така, че да могат да бъдат препращани към тях от друго място в кода.

Курсорът е от два вида:

  • Неявен курсор
  • Явен курсор

Неявен курсор

Винаги, когато някой DML операция в базата данни се създава имплицитен курсор, който съдържа редовете, засегнати от тази конкретна операция. Тези курсори не могат да бъдат именувани и следователно не могат да бъдат контролирани или препращани към тях от друго място в кода. Можем да препращаме само към най-скорошния курсор чрез атрибутите на курсора.

Явен курсор

Програмистите имат право да създават именувана контекстна област, за да изпълняват своите DML операции и да получат по-голям контрол върху нея. Изричният курсор трябва да бъде дефиниран в секцията за декларация на PL/SQL блоки е създаден за оператора SELECT, който трябва да се използва в кода.

По-долу са стъпките, необходими за работа с явни курсори:

  • Деклариране на курсора: Декларирането на курсора означава просто създаване на една именувана контекстна област за оператора SELECT, която е дефинирана в декларационната част. Името на тази контекстна област е същото като името на курсора.
  • Отваряне на курсора: Отварянето на курсора инструктира PL/SQL да разпредели памет за този курсор. Това подготвя курсора за извличане на записите.
  • Извличане на данни от курсора: В този процес се изпълнява командата SELECT и извлечените редове се съхраняват в разпределената памет. Те вече се наричат ​​активни набори. Извличането на данни от курсора е дейност на ниво запис, което означава, че можем да осъществяваме достъп до данните запис по запис. Всяка команда fetch извлича един активен набор и съхранява информацията за този конкретен запис. Тази команда е същата като команда SELECT, която извлича записа и го присвоява на променливата в клаузата INTO, но няма да генерира никакви грешки. изключения.
  • Затваряне на курсора: След като всички записи бъдат извлечени, трябва да затворим курсора, така че паметта, разпределена за тази контекстна област, да бъде освободена.

Синтаксис

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

В горния синтаксис, декларационната част съдържа декларацията на курсора и променливата на курсора, в която ще бъдат присвоени извлечените данни. Курсорът се създава за оператора SELECT, който е даден в декларацията на курсора. В частта за изпълнение, декларираният курсор се отваря, извлича и затваря.

Атрибути на курсора

Както имплицитният, така и експлицитният курсор имат определени атрибути, до които може да се осъществи достъп. Тези атрибути дават повече информация за операциите с курсора. По-долу са описани различните атрибути на курсора и тяхното използване.

Атрибут на курсора Descriptйон
% НАМЕРЕНО Връща булевия резултат TRUE, ако последната операция по извличане е извлякла запис успешно; в противен случай връща FALSE.
%НЕНАМЕРЕНО Работи обратно на %FOUND. Връща TRUE, ако последната операция за извличане не е успяла да извлече никакъв запис.
%ISOPEN Връща булевия резултат TRUE, ако даденият курсор вече е отворен; в противен случай връща FALSE.
%ROWCOUNT Връща числова стойност, показваща действителния брой записи, засегнати или извлечени от операцията.

Пример за изричен курсор: В този пример ще видим как да декларираме, отворим, извлечем и затворим експлицитен курсор. Ще проектираме всички имена на служители от emp таблицата, използвайки курсор. Ще използваме и атрибут cursor, за да настроим цикъла да извлича всички записи от курсора.

Снимката на екрана по-долу показва този пример за експлицитен курсор и неговия изход в Oracle.

Пример за изричен курсор, извличащ имената на служителите от emp таблицата в 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;
/

Продукция

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

Code Обяснение

  • Code ред 2: Деклариране на курсора guru99_det за оператора 'SELECT emp_name FROM emp'.
  • Code ред 3: Деклариране на променливата lv_emp_name с %тип закотвен към emp.emp_name.
  • Code ред 5: Отваряне на курсора guru99_det.
  • Code ред 6: Задаване на основния цикъл за извличане на всички записи в emp таблицата.
  • Code ред 7: Извлича данните от guru99_det и присвоява стойността на lv_emp_name.
  • Code ред 8: Използване на атрибута на курсора %NOTFOUND за проверка дали всички записи в курсора са извлечени. Ако са извлечени, връща TRUE и управлението излиза от цикъла; в противен случай управлението продължава да извлича данните от курсора и ги отпечатва.
  • Code ред 10: Условие EXIT за командата за цикъл.
  • Code ред 12: Отпечатайте извлеченото име на служител.
  • Code ред 14: Използване на атрибута на курсора %ROWCOUNT за намиране на общия брой записи, извлечени от курсора.
  • Code ред 15: След излизане от цикъла, курсорът се затваря и разпределената памет се освобождава.

FOR Loop Cursor инструкция

Курсор FOR цикъл може да се използва за работа с курсори. Можем да зададем име на курсора вместо ограничение на диапазона в оператора на цикъла FOR, така че цикълът да работи от първия запис на курсора до последния запис на курсора. Променливата на курсора, отварянето на курсора, извличането и затварянето на курсора се извършват имплицитно от цикъла FOR.

Синтаксис

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

В горния синтаксис, декларационната част съдържа декларацията на курсора. Курсорът се създава за оператора SELECT, който е даден в декларацията на курсора. В изпълнителната част, декларираният курсор се задава в цикъла FOR, а променливата на цикъла 'I' се държи като променлива на курсора в този случай.

Oracle Пример за курсор за цикъл: В този пример ще проектираме имената на всички служители от таблицата emp, използвайки цикъл cursor-FOR.

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

Продукция

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

Code Обяснение

  • Code ред 2: Деклариране на курсора guru99_det за оператора 'SELECT emp_name FROM emp'.
  • Code ред 4: Конструиране на цикъла FOR за курсора с променливата на цикъла lv_emp_name.
  • Code ред 6: Отпечатване на името на служителя във всяка итерация на цикъла.
  • Code ред 7: Изход от цикъла (END LOOP).

Забележка: В цикъл cursor-FOR, атрибутите на курсора не могат да се използват, тъй като отварянето, извличането и затварянето на курсора се извършва имплицитно от цикъла FOR.

Въпроси и Отговори

REF КУРСОР (курсорна променлива) е указател към набор от резултати от заявка. За разлика от статичния курсор, той може да отваря различни заявки по време на изпълнение и да предава резултати между PL/SQL блокове или към клиентски програми.

Нормалният курсор извлича по един ред на FETCH, което води до много превключвания на контекста. ГРУПОВО СЪБИРАНЕ зарежда много редове в колекция с едно извличане, което значително намалява натоварването при големи набори от резултати.

Да. Декларирайте параметризиран курсор, например CURSOR c(dept NUMBER) IS SELECT …, след което предайте стойности на OPEN c(10). Параметрите ви позволяват да използвате повторно една дефиниция на курсора с различни стойности на филтъра.

FOR UPDATE заключва редовете, избрани от курсора, така че никой друг да не може да ги променя. WHERE CURRENT OF след това актуализира или изтрива точно избрания ред, без да повтаря условието WHERE.

Отворените курсори запазват паметта си резервирана и се броят спрямо лимита OPEN_CURSORS. Оставянето на много отворени курсори евентуално води до ORA-01000: максималният брой отворени курсори е превишен, така че винаги ЗАТВАРЯЙТЕ изричен курсор след употреба.

Всеки FETCH превключва между PL/SQL и SQL механизмите. Хиляди такива контекстни превключватели се натрупват, така че един единствен SQL оператор, базиран на набор, или BULK COLLECT обикновено обработва едни и същи редове много по-бързо.

Да. Копилот на GitHub създава явни цикли OPEN, FETCH и CLOSE или цикли FOR за курсора от коментар, добавя проверки за изход %NOTFOUND и предлага имена на атрибути, въпреки че първо трябва да прегледате логиката.

Асистентите с изкуствен интелект маркират цикли на курсора ред по ред, които биха могли да се превърнат в SQL, базиран на множества, или BULK COLLECT, забелязват незатворени курсори и обясняват поведението на %attribute. Този преглед на машинното обучение подобрява производителността, преди кодът да достигне производствена версия.

Обобщете тази публикация с: