it-swarm-eu.dev

Proč místo explicitních smyček používat explicitní kurzory?

Psal jsem základní webové aplikace rok (pro Oracle db), a protože funkce jsou velmi jednoduché, většina z nás se drží pravidelných smyček FOR pro získání našich dat:

for i in (select * from STUDENTS) loop
      htp.prn(i.student_last_name || ', ' || i.student_first_name || ' ' || i.student_dob);
end loop;

Kurzory se však zdají být „správným“ způsobem, jak dělat věci. Dokážu najít spoustu informací o tom, co jsou kurzory a různé způsoby, jak je procházet, ale nemůžu najít solidní důvod, proč je používat přes pravidelné smyčky FOR. Závisí to na potřebách postupu? Existují podstatné výhody, o kterých bych měl vědět?

12
ini

Kurzor může být explicitní nebo implicitní a oba typy lze použít ve smyčce FOR. Na vaši otázku jsou skutečně dva aspekty.

  1. Proč používat explicitní kurzor FOR smyčka přes implicitní kurzor FOR smyčka?

    • Když bude dotaz znovu použit, použijte explicitní kurzor FOR smyčky, jinak je preferován implicitní kurzor.
  2. Proč používat smyčku s FETCH spíše než pro smyčku FOR, která nemá explicitní FETCH?

    • Pokud potřebujete hromadně shromažďovat nebo když potřebujete dynamický SQL, použijte FETCH uvnitř smyčky.

Zde je několik užitečných informací z dokumentace.

Příklad implicitního kurzoru PRO LOOP

BEGIN
   FOR vItems IN (
      SELECT last_name
      FROM employees
      WHERE manager_id > 120
      ORDER BY last_name
   ) 
   LOOP
      DBMS_OUTPUT.PUT_LINE ('Name = ' || vItems.last_name);
   END LOOP;
END;
/

Příklad explicitního kurzoru PRO LOOP

DECLARE
   CURSOR c1 IS
      SELECT last_name
      FROM employees
      WHERE manager_id > 120
      ORDER BY last_name;
BEGIN
   FOR vItems IN c1 LOOP
      DBMS_OUTPUT.PUT_LINE ('Name = ' || vItems.last_name);
   END LOOP;
END;
/

Implicitní kurzor

Implicitní kurzor je relační kurzor, který je konstruován a spravován pomocí PL/SQL. PL/SQL otevře implicitní kurzor při každém spuštění příkazu SELECT nebo DML. Implicitní kurzor nelze ovládat, ale můžete získat informace z jeho atributů.

Po spuštění přidruženého příkazu se implicitní kurzor uzavře; jeho hodnoty atributů však zůstávají dostupné, dokud se nespustí jiný příkaz SELECT nebo DML.

Implicitní atributy kurzoru jsou: SQL% ISOPEN, SQL% FOUND, SQL% NOTFOUND, SQL% ROWCOUNT, SQL% BULK_ROWCOUNT, SQL% BULK_EXCEPTIONS

Explicitní kurzor

Explicitní kurzor je relační kurzor, který konstruujete a spravujete. Musíte deklarovat a definovat explicitní kurzor, dát mu jméno a přiřadit jej k dotazu (obvykle dotaz vrátí více řádků). Potom můžete zpracovat sadu výsledků dotazu jedním z těchto způsobů:

Otevřete explicitní kurzor (pomocí příkazu OPEN), načtěte řádky ze sady výsledků (pomocí příkazu FETCH) a zavřete explicitní kurzor (pomocí příkazu ZAVŘÍT).

Použijte explicitní kurzor v příkazu FOR LOOP (viz „Zpracování sady výsledků dotazu pomocí kurzoru pro příkazy LOOP“).

Nelze přiřadit hodnotu explicitnímu kurzoru, použít ho ve výrazu nebo použít jako formální parametr podprogramu nebo hostitelskou proměnnou. Tyto věci můžete dělat s proměnnou kurzoru (viz „Proměnné kurzoru“).

Na rozdíl od implicitního kurzoru můžete odkazovat na explicitní kurzor nebo proměnnou kurzoru podle jeho názvu. Explicitní kurzor nebo proměnná kurzoru se proto nazývá pojmenovaný kurzor.

Kurzor pro příkazy LOOP

Kurzor FOR LOOP příkaz umožňuje spustit příkaz SELECT a poté okamžitě procházet řádky sady výsledků. Tento příkaz může použít implicitní nebo explicitní kurzor.

7
Leigh Riffel

Kód, který jste zveřejnili, používá kurzor. Používá implicitní smyčku kurzoru.

Existují případy, kdy použití explicitní smyčky kurzoru (tj. Deklarace proměnné CURSOR v sekci prohlášení) vytvoří čistší kód nebo lepší výkon

  1. Pokud máte složitější dotazy, které nemůžete změnit v zobrazeních, může to usnadnit čtení kódu, pokud se smyčka opakuje přes student_cursor namísto zahrnutí 30řádkového příkazu SQL, který obsahuje spoustu logiky. Pokud jste například vytiskli všechny studenty, které byly schváleny k absolvování a které zahrnovaly připojení k tabulkám, které měly jejich akademické záznamy, požadavky jejich studijního programu, tabulky s informacemi o akademických pozicích, tabulky s informacemi o knihovních knihách po splatnosti, tabulky s informacemi o nezaplacených poplatcích, administrativních přepisech atd., pravděpodobně by mělo smysl zmapovat kód tak, aby tento dotaz nebyl zaseknut uprostřed kódu, který se týká prezentace seznamu uživateli. To by mohlo zahrnovat vytvoření pohledu, který by zapouzdřil celou tuto logiku. Nebo by to mohlo zahrnovat vytvoření explicitního kurzoru, který byl deklarován buď jako součást aktuálního bloku PL/SQL nebo v nějakém vyšší úrovni PL/SQL bloku (tj. Kurzor deklarovaný v balíčku), takže je znovu použitelný. Nebo by to mohlo znamenat udělat něco jiného pro zapouzdření a znovu použitelnost (řekněme, místo toho vytvoření funkce pipelined table).
  2. Pokud chcete používat hromadné operace v PL/SQL, obvykle chcete použít explicitní kurzory. Zde je vlákno StackOverflow, které pojednává o rozdíly ve výkonu mezi explicitními a implicitními kurzory . Pokud vše, co děláte, je volání htp.prn, dělá BULK COLLECT vám pravděpodobně nic nekoupí. V jiných případech však může dojít k podstatnému zlepšení výkonu.
16
Justin Cave

Vidím, že mnoho vývojářů používá explicitní kurzory místo implicitních kurzorů ze starého zvyku. To proto, že v Oracle verzi 7 to byl vždy efektivnější způsob, jak jít. V dnešní době existuje obecně opačná cesta. Speciálně s optimalizátorem, který v případě potřeby může přepsat implicitní kurzor pro smyčky do hromadného sběru.

2
Peter Åkerlund

Nedávno jsem musel přepsat spoustu dotazů z implicitní smyčky FOR do explicitních kurzorů. Důvodem bylo to, že dotazy vyvolaly data z externí databáze prostřednictvím odkazu a tato databáze měla jiné kódování než naše lokální databáze. Při přenosu dat z implicitního kurzoru do lokálně definovaného typu záznamu došlo k mylným občasným chybám (pouze na určitých konkrétních řádcích). Naše DBA nám to vysvětlila, my bychom se sami nedostali na dno. Zdá se, že se jedná o chybu v Oracle, která byla nahlášena.

Bylo nám doporučeno přepsat vše pomocí explicitních kurzorů a chyba byla pryč.

Ne primární důvod, proč byste mohli chtít použít explicitně přes implicitní, ale stojí za poznámku.

ÚPRAVA: Oracle 12c.

0
Robotron