• 締切済み

PL/SQLのOPEN cursor_name FOR文でCLOSEは必要?

MarrowGの回答

  • MarrowG
  • ベストアンサー率53% (41/76)
回答No.1

カーソルは有限な資源なので、必ずクローズが必要です。 またこの中ではカーソルをOpenしかしていませんが、FetchしないでVBからどうやってデータを取っているのでしょう? 他にFetchする為のストアードプロシージャがあるのであれば、さらに処理を終了するためのストアードプロシージャを作成してその中でカーソルをクローズしてください。

takataka111
質問者

お礼

これは複数のレコードを一度に取得できるCURSORでFETCHはいりません、本を読んだ限りこのCURSOR(OPEN FOR)カーソルはCLOSEがいらないカーソルだとのことです。 ありがとうございました。

関連するQ&A

  • 動的なSQLからカーソルを返す。

    下記のようなカーソルを返すパッケージがあったとします。 CREATE OR REPLACE PACKAGE TEST AS CURSOR C1 IS SELECT * FROM テーブル; TYPE TC1 IS REF CURSOR RETURN C1%ROWTYPE; PROCEDURE P_TEST(in条件 IN CHAR, CU OUT TC1); END; CREATE OR REPLACE PACKAGE BODY TEST IS PROCEDURE P_TEST(in条件 IN CHAR, CU OUT TC1) AS sqlStr VARCHAR2(1000); cur NUMBER; r NUMBER; BEGIN cur := DBMS_SQL.OPEN_CURSOR; sqlStr := 'OPEN CU FOR SELECT * FROM テーブル WHERE 条件 = ' || in条件; DBMS_SQL.PARSE(cur, sqlStr, DBMS_SQL.NATIVE); DBMS_SQL.DEFINE_COLUMN(cur, 1, CU); r := DBMS_SQL.EXECUTE(cur); DBMS_SQL.CLOSE_CURSOR(cur); END; SELECTした結果のカーソル(CU)をクライアントで取得したいのですけど 技術的に可能でしょうか? ストアドのコンパイル時に→DBMS_SQL.DEFINE_COLUMN(cur, 1, CU);が エラーとなります。 DBMS_SQL.DEFINE_COLUMNではカーソルタイプは取得できないとわっかたの ですがカーソルを取得する為のDBMS_SQL.DEFINE_COLUMNにかわる DBMS_SQL.?????はないでしょうか? いろいろ調べたのですが手に負えず。 どなたか教えてください。

  • [PL/SQL]REFCURSORが戻り値のプロシージャについて

    [PL/SQL]REFCURSORが戻り値のプロシージャについて お世話になってます タイトルの内容について、親プロシージャより引数を受け取り 子プロシージャでカーソルをオープンして、そのカーソルを親に戻す。 というプロシージャなのですが、親から実行した場合には問題ないのですが 子をSI ObjectBrowserから実行すると[実行][デバッグ]共に 押した瞬間に止まってしまいます。 下記にソースを記述します --カーソル変数の定義 CREATE OR REPLACE PACKAGE LC7BDEV.PKG_TEST_CURSOR IS  TYPE TEST_TYPE IS RECORD  (COL1 TABLE1.COL1%TYPE ,   COL2 TABLE1.COL2%TYPE ); TYPE CUR_TEST IS REF CURSOR RETURN TEST_TYPE; END; --親プロシージャ CREATE OR REPLACE PROCEDURE PD_TEST  (   in_COL_KEY IN TABLE1.COL_KEY%TYPE  ) IS  TEST_REC  PKG_TEST_CURSOR.CUR_TEST;  TEMP_COL1 TABLE1.COL1%TYPE;  TEMP_COL2  TABLE1.COL1%TYPE; BEGIN  PD_TEST_KO(in_COL_KEY,TEST_REC);  loop   fetch TEST_REC into TEMP_COL1,TEMP_COL2;   exit when TEST_REC%notfound;   dbms_output.put_line(TEMP_COL1 || ',' || TEMP_COL2);  end loop;    close TEST_REC; END; --子プロシージャ CREATE OR REPLACE PROCEDURE PD_TEST_KO  (   in_COL_KEY  IN  TABLE1.COL_KEY%TYPE ,   in_TEST_REC OUT PKG_TEST_CURSOR.CUR_TEST ,  ) IS BEGIN  OPEN in_TEST_REC FOR   SELECT COL1,COL2   FROM TABLE1   WHERE COL_KEY = in_COL_KEY END;

  • PL/SQLでカーソルを指定する方法

    以下のSQL文で、 あるストアドプロシージャを作成し、その引数の値を WHERE句の検索条件に取ってカーソルを宣言したいので すが、どうやってもエラーが出ます。結果として カーソルで格納したデータを呼び出し元に返したいの ですが…。下記の文は間違ってますか? CREATE OR REPLACE PROCEDURE ss( quote IN NUMBER result OUT CHAR ) IS CURSOR cur IS SELECT empname FROM emp WHERE empno = quote; result cur%rowtype; BEGIN OPEN cur; LOOP FETCH cur INTO result; ~ END; どうかよろしくお願いします。

  • PL/SQLのカーソルについて

    PL/SQLのカーソルについて お世話になります。 Oracle11gで開発しています。 初心者です。 下記ストアドプロシージャの「zokuseisyutoku」で取得した 値(入数、重量、才数、ロケーション)を受けて、別のストアドプロシージャ 「Hyouji」の変数(irisuu、jyuryou、saisuu、lokesyon)に代入して得られた 内容をGridviewに表示させたいと思っています。 現在は、別々のストアドプロシージャなのですが、 一つに出来るものなら一つのストアドプロシージャにまとめたいの ですが、どなたかご親切な方、ご教授頂きたく宜しくお願い致します。        記 (1)ストアドプロシージャ1つ目 create or replace procedure zokuseisyutoku ( sItemClass in コード表.品番%type, out_val out pls_integer, out_cursor out sys_refcursor ) as begin if sItemClass is null then open out_cursor for select 入数, 重量, 才数, ロケーション from コード表 ; else open out_cursor for select 入数, 重量, 才数, ロケーション from コード表 where 品番 = sItemClass ; end if; out_val := 1; (2)ストアドプロシージャ2つ目 create or replace procedure Hyouji ( irisuu in 部材表.入数%type, jyuryou in 部材表.重量%type, saisuu in 部材表.才数%type, lokesyon in 部材表.ロケーション%type, out_val out pls_integer, out_cursor out sys_refcursor ) as begin open out_cursor for select b.資材名,b.色,b.種類,b.サイズ,b.棚番号 FROM 部材表 a,資材項目 b WHERE a.ID = b.資材ID AND a.入数 = irisuu AND a.重量 = jyuryou AND a.才数 = saisuu AND ロケーション = lokesyon ; out_val := 1; end; end;

  • PL/SQL-プロシージャ

    プロシージャBはテスト実行のため、プロシージャAを真似て作成しています。 --最後のIF文で、プロシージャAかBのどちらかに走らせたいと思っています。 DECLARE --プロシージャA--------------------------------------- PROCEDURE A IS fno1 utl_file.file_type; dnm1 varchar(200) :='XXX'; fnm1 varchar2(200) :='BBB.txt'; CURSOR cu1 is select XYZ as ABC from CCC; BEGIN fno1 := utl_file.fopen(dnm1,fnm1,'w'); FOR CU1_REC1 in CU1 loop utl_file_put_line(fno1,' '|| CU1_REC1.XYZ END LOOP; utl_file.fclose(fno1); end; --プロシージャB------------------------------------- プロシージャAと似たような処理 --プロシージャAかBかを判定するIF文------------------------------ BEGIN IF CCC.ABC = '0'; THEN A; ELSE B; ENDIF; END; /

  • PL/SQLでエラー

    PL/SQLの使用方法を検討しており、下記のようにサンプルを作成しました。 //1. 宣言部 create or replace package Pac is procedure Pro1(p1 in varchar2); end; / パッケージが作成されました //2. 本体 create or replace package body Pac is procedure Pro1(p1 in varchar2) is tempdate DATE; begin select to_char(sysdate, 'yyyy/mm/dd') INTO tempdate from dual; DBMS_OUTPUT.PUT_LINE('引数は' || p1 || 'です。'); DBMS_OUTPUT.PUT_LINE('日付は' || tempdate || 'です。'); end; end; / パッケージ本体が作成されました //3. 実行 execute Pac.Pro1('a'); // エラー内容 行1でエラーが発生しました。: ORA-00900: invalid SQL statement SQLPlusより、上記の[1. 宣言部]でパッケージを作成し、[2. 本体]で本体部分を作成しました。 その後、[3. 実行]を実施しましたが、 エラーが出力されて実行されません。 何がいけないのかお気づきの点がございましたら、 よろしくお願いします。

  • ストアド実行時のエラー「参照しているコレクションは初期化されていません」

    以下のようなパッケージを作っています。 CREATE OR REPLACE PACKAGE "TEST"."TEST_P" as type test_type1 is table of TEST.TEST_TABLE%ROWTYPE; procedure test2 (ret OUT test_type1 ) ; end; ----------------------------------- 本体 ----------------------------------- CREATE OR REPLACE PACKAGE BODY "TEST"."TEST_P" as procedure test2( ret OUT test_type1 ) is cursor basic_cusor is select * from TEST.TEST_TABLE; BEGIN open basic_cusor; loop fetch basic_cusor into ret(0); exit when basic_cusor%notfound; END loop; END TEST3; end; ---------------------------------------- これをSQL Pluseから set serveroutput on; declare  arg1 TEST.TEST_P.test_type1; begin TEST.TEST_P.test2(arg1); dbms_output.put(arg1(0).coulm1); end; のように実行するとエラーが出ます。 初期化処理とはどのように行えばいいのでしょうか? 最終的にはSQLServerのストアドようにテーブル のような構造で値を返えせればいいです。

  • VBからoo4o接続でストアドを呼ぶ方法

    お世話になります、 VBからoo4o接続でストアドを呼ぶ方法を探しています。 <現在の状況> ■ストアドパッケージ ・次のように値を返すストアドパッケージがあるとします。これを CreatePLSQLDynaset で実行して、レコードセットを取得します。(OraDynaset) create or replace package testp is procedure GetTestm(key in number, cu out CHAR); end; / create or replace package body testp is procedure GetTestm(key in number,cu out CHAR) is begin select NAME into cu from TEMP where STATUS=key; end; end; / ■VBのボタンイベント Private Sub Command1_Click() Dim dbname Dim cnuser '** サービス、ユーザ設定 dbname = "aaa" cnuser = "bb/bb" '** oo4o 接続 Set GoORASESSION = CreateObject("OracleInProcServer.XOraSession")  Set GoORADATABASE = GoORASESSION.OpenDatabase(dbname, cnuser, &H0) '** リクエリレコードセットオープン Set Recordset = GoORADATABASE.CreatePLSQLDynaset("Begin testp.GetTestm (1,:cu); end;", "cu", &H0) End Sub これを実行したところ以下のようなエラーが出ました <エラー> ____________________________ 実行時エラー '440' SQL実行エラー,ORA-06550:行:1、列:7 PLS-00306:'GETTESTM'の呼び出しで、引数の数または型が正しくありません ORA-06550:行:1、列:7 PL/SQL:Statement ignored _______________________________ というエラーが出てしまいます、引数の数は合っていると思うのですが、どこがお菓子のでしょうか? よろしくお願いします。

  • VBからストアドの動的SQLを呼んで値をレコードセットで取得する方法

    お世話になります。 VBからストアドの動的SQLを呼んで、VB側で値をレコードセットで取得する方法を探しています。 ■ストアド CREATE OR REPLACE PACKAGE SAMPLE as CURSOR c2 IS select A from TBL; TYPE TANTOYOSANDATA IS REF CURSOR RETURN c2%ROWTYPE; PROCEDURE GetNUMBER(C IN NUMBER,           CU OUT TANTOYOSANDATA); end; / -- CREATE OR REPLACE PACKAGE BODY SAMPLE IS PROCEDURE GetNUMBER(C IN NUMBER,             CU OUT TANTOYOSANDATA) IS CUR INTEGER; STATUS INTEGER; ROW_PROCESSED INTEGER; A NUMBER; BEGIN --カーソルをOPENする CUR :=DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(CUR,'SELECT A FROM TBL ',DBMS_SQL.V7); DBMS_SQL.DEFINE_COLUMN(CUR,1,A); ROW_PROCESSED :=DBMS_SQL.EXECUTE(CUR); STATUS :=DBMS_SQL.FETCH_ROWS(CUR); WHILE (STATUS <> 0) LOOP DBMS_SQL.COLUMN_VALUE(CUR,1,A); STATUS :=DBMS_SQL.FETCH_ROWS(CUR); END LOOP; END; END SAMPLE; / ■VB側 Set GoORASESSION = CreateObject("OracleInProcServer.XOraSession") Set GoORADATABASE = GoORASESSION.OpenDatabase(dbname, cnuser, ORADB_DEFAULT) Set Recordset = GoORADATABASE.CreatePLSQLDynaset("Begin SAMPLE.GetTANTOINFO(1,:CU)); end;", "CU", ORADYN_DEFAULT) ' If Recordset.EOF Then Do While Not Recordset.EOF Label11.Caption = Recordset(0) Recordset.movenext  Loop 復帰値をRecordSetで受けて それをまわしながら1レコードずつ取得する方法を探しています よろしくお願いします。

  • SQL文でどこが悪いのか教えて下さい

    初心者ですが教えて下さい。 表Aと表Bで表Aに含まれていないものを表Cに入れたいのですが、下記のやり方では表Aのものしか入れることができません。 どこが悪いのか教えて下さい。 ・コードは複雑なため、簡略化しています。UNIONは使わない方向で。 CREATE OR REPLACE PROCEDURE SAMPLE IS CURSOR SELLINE1 IS SELECT * FROM A ORDER BY KEY1,KEY2; CURSOR SELLINE2 IS SELECT * FROM B ORDER BY KEY1,KEY2; CNT1 NUMBER; CNT2 NUMBER; BEGIN SELECT COUNT(*) INTO CNT1 FROM C; IF CNT1 = 0 THEN FOR SELREC IN SELLINE1 LOOP INSERT INTO C VALUES (KEY1,KEY2,値);COMMIT; END LOOP; FOR SELREC IN SELLINE2 LOOP SELECT COUNT(*) INTO CNT2 FROM C WHERE (KEY1 = SELREC.KEY1) AND (KEY2 = SELREC.KEY2); IF CHK_CNT2 = 0 THEN INSERT INTO C VALUES (KEY1,KEY2,値);COMMIT; END IF; END LOOP; END IF; END; /