Поиск…
Синтаксис
- Курсор cursor_name: your_select_statement
- Курсор cursor_name (param TYPE) Является вашим_select_statement_using_param
- FOR x in ( your_select_statement ) LOOP ...
замечания
Объявленные курсоры сложны в использовании, и в большинстве случаев вы должны предпочитать цикл FOR
. Что очень интересно в курсорах по сравнению с простыми циклами FOR
, так это то, что вы можете их параметризовать.
Лучше избегать выполнения циклов с PL / SQL и курсоров вместо использования Oracle SQL в любом случае. Однако для людей, привыкших к процедурному языку, это может быть гораздо легче понять.
Если вы хотите проверить, существует ли запись, а затем делать разные вещи в зависимости от того, существует ли запись или нет, тогда имеет смысл использовать операторы MERGE
в чистых запросах ORACLE SQL вместо использования курсоров. (Обратите внимание, что MERGE
доступен только в версиях Oracle> = 9i).
Параметрированный курсор «FOR loop»
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;
/
Неявный курсор «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;
/
- Первое преимущество заключается в том, что нет утомительной декларации (подумайте об этом ужасном «КУРСОРЕ», которое у вас было в предыдущих версиях)
- второе преимущество заключается в том, что вы сначала создаете свой запрос выбора, а затем, когда у вас есть то, что вы хотите, вы сразу можете получить доступ к полям вашего запроса (
x.<myfield>
) в вашем цикле PL / SQL - Цикл открывает курсор и выбирает по одной записи за каждый цикл. В конце цикла курсор закрывается.
- Неявные курсоры быстрее, потому что работа интерпретатора возрастает по мере увеличения кода. Чем меньше кода, тем меньше работает интерпретатор.
Работа с SYS_REFCURSOR
SYS_REFCURSOR
можно использовать как возвращаемый тип, когда вам нужно легко обрабатывать список, возвращенный не из таблицы, а, более конкретно, из функции:
функция, возвращающая курсор
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;
/
и как его использовать:
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;
/
Обработка КУРСОРА
- Объявить курсор для сканирования списка записей
- Открой это
- Получить текущую запись в переменные (это увеличивает положение)
- Использовать
%notfound
для обнаружения конца списка - Не забудьте закрыть курсор, чтобы ограничить потребление ресурсов в текущем контексте
-
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;
/