サーチ…
構文
- カーソルcursor_nameはyour_select_statementです。
- Cursor cursor_name (param TYPE) your_select_statement_using_paramですか?
- FOR x in( your_select_statement )LOOP ...
備考
宣言されたカーソルは使用するのが難しく、ほとんどの場合FOR
ループを優先するべきです。シンプルなFOR
ループと比較して、カーソルで非常に興味深いのは、パラメータ化できるということです。
とにかくOracle SQLを使用するのではなく、PL / SQLおよびカーソルを使用してループを実行しない方がよいでしょう。しかし、手続き型言語に慣れている人にとっては、はるかに理解しやすくなります。
レコードが存在するかどうかを確認し、レコードが存在するかどうかに応じて異なるものを実行する場合は、カーソルループを使用するのではなく、純粋なORACLE SQLクエリでMERGE
ステートメントを使用することが理にかなっています。 ( MERGE
は、Oracleリリースでは9i以上でのみ使用可能です)。
パラメータ化された "FORループ"カーソル
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ループ」カーソル
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;
/
- 最初の利点は、退屈な宣言がないことです(あなたが以前のバージョンで持っていたこの恐ろしい "CURSOR"事を考えてください)
- 2番目の利点は、最初に選択したクエリを作成してから、必要なものがあればすぐにPL / SQLループ内のクエリのフィールド(
x.<myfield>
)にアクセスできることです - ループはカーソルを開き、ループごとに一度に1レコードをフェッチします。ループの最後にカーソルが閉じられます。
- 暗黙的なカーソルは、コードが長くなるにつれてインタープリタの仕事が増えるため、高速です。コードが少なくて済むので、通訳者の仕事が少なくて済みます。
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;
/
Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow