Sök…
Syntax
- Markörens markörnamn Är ditt_select_statement
- Markörens markörnamn (param TYPE) Är din_select_statement_using_param
- FÖR x in ( din_select_statement ) LOOP ...
Anmärkningar
Förklarade markörer är svåra att använda, och du bör föredra FOR
loopar i de flesta fall. Vad som är mycket intressant i markörer jämfört med enkla FOR
slingor är att du kan parametrera dem.
Det är bättre att undvika att göra slingor med PL / SQL och markörer istället för att använda Oracle SQL ändå. Men för människor som är vana vid procedurspråk kan det vara mycket lättare att förstå.
Om du vill kontrollera om en post finns och sedan göra olika saker beroende på om posten finns eller inte, är det vettigt att använda MERGE
uttalanden i rena ORACLE SQL-frågor istället för att använda markörslingor. (Observera att MERGE
endast finns i Oracle-utgåvor> = 9i).
Parameteriserad "FOR loop" markör
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;
/
Implicit "FOR loop" -markör
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;
/
- Den första fördelen är att det inte finns någon långtråkig deklaration att göra (tänk på den hemska "CURSOR" -saken du hade i tidigare versioner)
- den andra fördelen är att du först bygger din utvalda fråga, sedan när du har vad du vill kan du omedelbart få åtkomst till fälten för din fråga (
x.<myfield>
) i din PL / SQL-slinga - Loopen öppnar markören och hämtar en post åt gången för varje slinga. I slutet av slingan är markören stängd.
- Implicita markörer är snabbare eftersom tolkens arbete växer när koden blir längre. Ju mindre kod, desto mindre arbete har tolken att göra.
Arbetar med SYS_REFCURSOR
SYS_REFCURSOR
kan användas som SYS_REFCURSOR
när du enkelt behöver hantera en lista som returneras inte från en tabell, men mer specifikt från en funktion:
funktion som returnerar en markör
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;
/
och hur man använder det:
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;
/
Hantering av en CURSOR
- Förklara markören för att skanna en lista med poster
- Öppna den
- Hämta aktuell post i variabler (denna stegvisa position)
- Använd
%notfound
att upptäcka slutlistan - Glöm inte att stänga markören för att begränsa resursförbrukningen i nuvarande sammanhang
-
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;
/