Zoeken…
Syntaxis
- Cursor cursor_naam Is uw_select_statement
- Cursor cursor_naam (param TYPE) Is uw_select_statement_using_param
- VOOR x in ( uw_select_statement ) LUS ...
Opmerkingen
Aangegeven cursors zijn moeilijk te gebruiken en in de meeste gevallen moet u de voorkeur geven aan FOR
lussen. Wat erg interessant is in cursors in vergelijking met eenvoudige FOR
lussen, is dat je ze kunt parametreren.
Het is beter om lussen met PL / SQL en cursors te vermijden in plaats van Oracle SQL toch te gebruiken. Voor mensen die gewend zijn aan procedurele taal, kan het echter veel gemakkelijker te begrijpen zijn.
Als u wilt controleren of een record bestaat en vervolgens verschillende dingen doet, afhankelijk van of de record al dan niet bestaat, is het zinvol MERGE
instructies te gebruiken in pure ORACLE SQL-query's in plaats van het gebruik van cursorlussen. (Merk op dat MERGE
alleen beschikbaar is in Oracle-releases> = 9i).
Parameter "FOR loop" Cursor
DECLARE
CURSOR c_emp_to_be_raised(p_sal emp.sal%TYPE) IS
SELECT * FROM emp WHERE sal < p_sal;
BEGIN
FOR cRowEmp IN c_emp_to_be_raised(1000) LOOP
dbms_Output.Put_Line(cRowEmp .eName ||' ' ||cRowEmp.sal||'... should be raised ;)');
END LOOP;
END;
/
Impliciete cursor "FOR loop"
BEGIN
FOR x IN (SELECT * FROM emp WHERE sal < 100) LOOP
dbms_Output.Put_Line(x.eName ||' '||x.sal||'... should REALLY be raised :D');
END LOOP;
END;
/
- Het eerste voordeel is dat er geen vervelende verklaring is om te doen (denk aan dit vreselijke 'CURSOR'-ding dat je in vorige versies had)
- tweede voordeel is dat u eerst uw geselecteerde query bouwt, en wanneer u hebt wat u wilt, kunt u onmiddellijk toegang krijgen tot de velden van uw query (
x.<myfield>
) in uw PL / SQL-lus - De lus opent de cursor en haalt voor elke lus één record per keer op. Aan het einde van de lus is de cursor gesloten.
- Impliciete cursors zijn sneller omdat het werk van de tolk groeit naarmate de code langer wordt. Hoe minder code, hoe minder werk de tolk hoeft te doen.
Werken met SYS_REFCURSOR
SYS_REFCURSOR
kan worden gebruikt als een SYS_REFCURSOR
wanneer u gemakkelijk een lijst moet verwerken die niet uit een tabel, maar meer specifiek uit een functie wordt geretourneerd:
functie retourneert een cursor
CREATE OR REPLACE FUNCTION list_of (required_type_in IN VARCHAR2)
RETURN SYS_REFCURSOR
IS
v_ SYS_REFCURSOR;
BEGIN
CASE required_type_in
WHEN 'CATS'
THEN
OPEN v_ FOR
SELECT nickname FROM (
select 'minou' nickname from dual
union all select 'minâ' from dual
union all select 'minon' from dual
);
WHEN 'DOGS'
THEN
OPEN v_ FOR
SELECT dog_call FROM (
select 'bill' dog_call from dual
union all select 'nestor' from dual
union all select 'raoul' from dual
);
END CASE;
-- Whit this use, you must not close the cursor.
RETURN v_;
END list_of;
/
en hoe het te gebruiken:
DECLARE
v_names SYS_REFCURSOR;
v_ VARCHAR2 (32767);
BEGIN
v_names := list_of('CATS');
LOOP
FETCH v_names INTO v_;
EXIT WHEN v_names%NOTFOUND;
DBMS_OUTPUT.put_line(v_);
END LOOP;
-- here you close it
CLOSE v_names;
END;
/
Omgaan met een CURSOR
- Declareer de cursor om een lijst met records te scannen
- Open het
- Huidige record ophalen in variabelen (deze positie wordt verhoogd)
- Gebruik
%notfound
om het einde van de lijst te detecteren - Vergeet niet de cursor te sluiten om het verbruik van hulpbronnen in de huidige context te beperken
-
DECLARE
CURSOR curCols IS -- select column name and type from a given table
SELECT column_name, data_type FROM all_tab_columns where table_name='MY_TABLE';
v_tab_column all_tab_columns.column_name%TYPE;
v_data_type all_tab_columns.data_type%TYPE;
v_ INTEGER := 1;
BEGIN
OPEN curCols;
LOOP
FETCH curCols INTO v_tab_column, v_data_type;
IF curCols%notfound OR v_ > 2000 THEN
EXIT;
END IF;
dbms_output.put_line(v_||':Column '||v_tab_column||' is of '|| v_data_type||' Type.');
v_:= v_ + 1;
END LOOP;
-- Close in any case
IF curCols%ISOPEN THEN
CLOSE curCols;
END IF;
END;
/