PL/SQL文においてオブジェクト型の変数を使用する方法と注意点

このQ&Aのポイント
  • PL/SQL文において、CREATE TYPEでオブジェクト型の変数を定義することができます。
  • オブジェクト型の変数を使用する際には、適切な格納方法や初期化、配列への格納方法に注意が必要です。
  • オブジェクト型の変数をカーソルから取得して格納する場合、正しく表示されないことがあるため注意が必要です。
回答を見る
  • ベストアンサー

PL/SQL文についてです。

PL/SQL文において、CREATE TYPEでオブジェクト型のものを用意しました。そこにはnumber型の変数が10個あります。 そしてパッケージ内のプロシージャでそのオブジェクトを使用したいんです。 CREATE OR REPLAECE PACKAGE BODY BIG(○○ IN NUMBER、answer OUT NOCPY HAIRETSU) IS・・・・・・・・・・・・・・ BEGIN answer := HAIRETSU(); answer.extend(8); obj := temp_answer(0,0,0,0,0,0,0,0,0,0); 1.このあとにカーソルからいろいろ計算をしてtemp_income_personをもとめたとします。これをオブジェクト型の変数income_personにいれるときにobj.income_person := temp_income_personで格納されますか??dbms_output.put_line(obj.income_person)と入力しておいても表示されません。 2.このようにオブジェクトの10個の変数をすべてうめたあとでこのオブジェクトをまるまるanswer配列に格納します。 answer(i) := obj; これで配列に格納されたことになりますか? 3.次にobj := temp_answer(0,0,0,0,0,0,0,0,0,0); で初期化し、ループを用いて配列をうめていきます。可能ですか?

  • Oracle
  • 回答数4
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.4

>となるとそこのnvl関数はどこに書いたらいいのか・・・ カーソルに割り当てられているSELECT文でもいいですし、 obj.income_person := obj.income_person + NVL(○○,0) でもいいです。

haveagolde
質問者

お礼

なるほどどちらでもいいんですね!とても勉強になりました。今度実行してみます!ありがとうございました。

その他の回答 (3)

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.3

もしその方法で表示されないのであれば、足しこんでいるフィールドにNULLが含まれているということではないですか?NVLはかけていますか? なお、CREATE OR REPLACE TYPE HAIRETSU IS VARRAY(10) OF temp_number;でも格納できるはずです。

haveagolde
質問者

お礼

obj.income_person := obj.income_person + ○○ ○○にnullの場合も入り込んでます!!というこはそこを0に置き換えればいいんですね!?となるとそこのnvl関数はどこに書いたらいいのか・・・

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.2

内容が理解できました。 1.格納されます。もしかしてSET SERVEROUT ONしていないだけでは。。? 2.ここでいうHAIRETSUは、 CREATE OR REPLACE TYPE HAIRETSU IS TABLE OF temp_number; ですよね? answer(i) := obj;でanswerに格納できます。 3.可能です。

haveagolde
質問者

お礼

>>もしかしてSET SERVEROUT ONしていないだけでは。。? 私が行っていたのは1に書いた内容とは違って、カーソルからフェッチしたきたデータを使ってオブジェクト型の変数income_personにたしていきました。 obj.income_person := obj.income_person + ○○ これでフェッチするデータがなくなったときにループを抜けて、 dbms_output.put_line(obj.income_person)と出力させようと思ってやりましたが、表示されませんでした。(ただの文字列をその行の前後に出力させたものは出力されていました。)この足しかたがまずかったと思ったんではじめからオブジェクト変数にたしていくのではなくtemp_income_person合計値をもとめておいて、ループを抜けてからオブジェクト変数にいれればうまくいくのではないかと思い書いてみました。今実行環境がないんで試せませんが・・最初のやり方でもいけるなら表示されなかった原因はつかまめせんが・・・ HAIRETSUはVARRAY型でcreate typeしています。それでもanswer(i) := obj;でanswerに格納できますか?

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.1

Package Bodyに引数がついているし、内容もかなり混乱しているようです。おそらくobjの型が非常に都合よく理解されている気がします。 まずobjに割り当てられているオブジェクト型のCREATE TYPE文と、temp_answerの定義を示してもらえませんか。

haveagolde
質問者

お礼

create or replace type temp_answer is object( income_person NUMBER, ○○     NUMBER, ○○     NUMBER, ・・・・・・・・・・)です。 あと >>Package Bodyに引数がついているし、内容もかなり混乱しているようです。 すいません誤植です。 CREATE OR REPLAECE PACKAGE BODY PCG IS PROCEDURE プロシージャ1(○○ IN NUMBER、answer OUT NOCPY HAIRETSU) IS・・・・・です。

関連するQ&A

  • PL/SQLでの配列についてetc

    PL/SQLについて、何点か質問があります。 どれかひとつでも構わないので、皆さんのお知恵をお貸しください。 (1)ある配列変数に格納されている要素を全てDBMS_OUTPUT.PUT_LINE();で表示することってできますか? (PHPのecho var_dump();のような感じで) (2)ある配列変数に使用されている添え字(もしくは添え字の数)を取得することってできますか? (3)ORA-01403エラーはカーソルのデータが存在しない場合に、発生するケースはありますか? よろしくおねがいします。

  • 動的な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.?????はないでしょうか? いろいろ調べたのですが手に負えず。 どなたか教えてください。

  • ActionScriptで配列をクリアする方法を教えてください。

    ActionScriptで、オブジェクトを格納した配列をクリアする正しい方法を教えてください。 具体的には、 ・new Array() で配列を生成する。 ・new Object() で生成したオブジェクトを配列に格納する。 ・配列の中身を処理したあと、配列を一度クリアする。 ・配列に別のオブジェクトを格納する。 ような処理をしたいのですが、メモリリークを起こさずに配列をクリアするにはどうしたらいいでしょうか? 例えば、イメージはこんな感じです。(意味のないコードですが) // 配列の生成 var arr = new Array(); // 配列にオブジェクトを格納 for (var i = 0; i < 5; i++) { var obj = new Object(); obj.num = i; } // 配列のクリア arr.length = 0; // クリアした配列に別のオブジェクトを格納 for (var i = 0; i < 5; i++) { var obj = new Object(); obj.num = i * 2; } 上記のコードで、arr.length = 0; で配列をクリアしていますが、これで配列に格納されたオブジェクトが確保したメモリがすべて解放されるでしょうか? あるいは、配列の内容がなくなるまで pop() 等で取り出す等の処理をする必要があるでしょうか? 以上よろしくお願いします。

    • ベストアンサー
    • Flash
  • PL/SQLのパフォーマンスについて

    PL/SQLで、元のプログラムから、部品プログラム(以下のTEST_BUHIN)を呼ぶ際の、 パフォーマンスについてお聞きしたいことがあります。 Oracle8i環境を使っています。 以下の2つをコンパイルすると考えてください。 -------------------------------------------------- CREATE OR REPLACE TYPE test_type as object (  COL1 NUMBER(11),  COL2 VARCHAR2(20),    (実際には、40項目くらいあります)   ); / -------------------------------------------------- CREATE OR REPLACE PACKAGE BODY TEST_BUHIN AS  PROCEDURE TESTINSERT(TESTDATA IN test_type)  AS  BEGIN   INSERT INTO TESTTABLE VALUES(    TESTDATA.COL1,TESTDATA.COL2, ・・・    (以下略) -------------------------------------------------- 今、TESTTABLEにINSERTするプログラムを作成したいのですが、 パフォーマンスを最優先に考えたいと思っています。 その場合、元のプログラム内にINSERT文を作るべきか、 部品(TEST_BUHIN)を使用すべきか迷っています。 パフォーマンスがほぼ同じであれば、部品(TEST_BUHIN)を使用したいと思っています。 部品を使うとパフォーマンスが極端に落ちるということであれば、 部品はコンパイルせずに、元のプログラム内にINSERT文を作成しようと思います。 オブジェクトタイプ型変数を引数として渡した場合、 パフォーマンスへの影響はあるのでしょうか? 自分でも調べてみたのですが、いまいち分かりませんでした。 あと、大きな引数を渡した場合に、メモリをたくさん使ってしまうのかどうかも気になります。 文章が分かりづらいと思いますので、みなさんのご意見などを見て補足させていただきます。 Oracle、PL/SQLに詳しい方、よろしくお願いいたします。

  • 【PL/SQL】LOOPした動的SQLにてFETCHができない

    OracleのPL/SQLで FOR .. LOOP内にて動的SQLを使い SELECTしてきた値を順次FETCHして配列に格納していきたいのですが、 LOOPの1件目のみFETCHがされて2件目以降は全てNULLになってしまいます。SQL文は間違っていません。DBMS_SQL.LAST_ROW_COUNTで1件以上の検索結果があることも確認済みです。 なぜでしょう?教えて下さい! EXECUTE IMMEDIATEをLOOP内で使うことに問題あり? 簡略化した例です。p_noにはすでに文字列格納済みと見てください。 txtsql VARCHAR2(1000); -- 動的SQL mkin INTEGER; fornum1 INTEGER; max_count INTEGER; -- ループされる最大件数 TYPE type_mkin IS TABLE OF NUMBER(10) INDEX BY BINARY_INTEGER; TYPE type_pno IS TABLE OF CHAR(10) INDEX BY BINARY_INTEGER; mkin type_mkin; p_no type_pno; BEGIN FOR fornum1 IN 1 .. max_count LOOP txtsql := 'SELECT SUM(TPSV_NO) ' || ' FROM ACTV || ' WHERE PRI_NO= ' || p_no(fornum1); EXECUTE IMMEDIATE txtsql INTO mkin(fornum1); DBMS_OUTPUT.PUT_LINE(mkin(fornum1)); END LOOP; END;

  • [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についての質問です。

    PL/SQLについての質問です。 カーソルデータ(emp_rec(i))を、TABLE変数(emp_ins(i))に代入して、代入されたTABLE変数を使用して、DML処理を行うことは可能ですか? エラーを解読し対処を行っても、エラーが発生してしまいます。 どうか、ご教授お願いします。 下記を実行すると、下記エラーが発生します。 -実行結果------------------------------------ DECLARE * 行1でエラーが発生しました。: ORA-06502: PL/SQL: 数値または値のエラーが発生しました ORA-06512: 行127 -エラー番号解読----------------------------------------- ●エラー名: PL/ SQL: 数値または値のエラーstring が発生しました ●原因: 算術、数値、文字列、変換または制約エラーが発生しました。たとえば、NULL 値をNOT NULL で宣言した変数に割り当てようとした場合、または100 以上の整数をNUMBER( 2) で宣言した変数に割り当てようとした場合にこのエラーが発生します ●処置:値が制約違反をしないように、データ、操作方法または宣言方法を変更してください。 -ソース------------------------------------ DECLARE --カーソル定義 CURSOR emp_cur IS SELECT a,b,c FROM emp TYPE emptabtype IS TABLE OF emp%ROWTYPE INDEX BY PLS_INTEGER; emp_rec emptabtype; /* 処理対象データ格納変数 */ -- insert作業用 emp_ins emptabtype; ins_count NUMBER := 1; BEGIN /* empカーソルオープン・フェッチ・クローズ */ OPEN emp_cur; FETCH emp_cur BULK COLLECT INTO emp_rec; CLOSE emp_cur; /* (挿入)処理対象のデータを、処理対象データ格納変数に格納する。 */ FOR i IN emp_rec.FIRST..emp_rec.LAST LOOP --挿入するレコードを格納 emp_ins(ins_count) := emp_rec(i); ins_count := ins_count + 1; END LOOP; /* DML処理 */ -- 挿入する FOR count_ins IN emp_ins.FIRST..emp_ins.LAST LOOP INSERT INTO temp VALUES(emp_ins(count_ins).a ,emp_ins(count_ins).b ,emp_ins(count_ins).c); END LOOP; COMMIT; END; /

  • Object.definePropertyの簡略化

    下記に、Object.definePropertyの簡略化が掲載されているのですが、 「ReferenceError: config is not defined」になります。 http://qiita.com/tak0303/items/6c5cd59827e5398bcc22 ・config.valueって何ですか? ・どうやって動かすのでしょうか? var defineProp = function(obj, key, value){   config.value = value;   Object.defineProperty(obj, key, config); } var person = Object.create(null); defineProp(person, "car", "Delorean");

  • PL/SQL パッケージでのプロンプト使用

    こんにちは。 独学でPL/SQLを学んでいるのですが、パッケージの使用でうまく処理が走らないので、 アドバイスを頂けたらと思い書き込みさせて頂くことにしました。 パッケージtestは、オーバーロードプロシージャSHOW_BIZDAYS(日付, 数値)とSHOW_BIZDAYS(日付)を含んでいます。パッケージコードは質問の下に書いております。 ■質問1 オーバーロードプロシージャSHOW_BIZDAYSの日付のみパラメータとする2つ目のプロシージャを EXECUTE test.SHOW_BIZDAYS('20-NOV-13') コマンドで実行したところ、『PLS-00307: このコールに一致する'string'が複数宣言されています。』というエラーが表示されてしまいます。 2つのオーバーロードプロシージャのパラメータ数が異なるよう指定しているので、このエラーに関する原因を見つけれておりません。 ■質問2: SHOW_BIZDAYS(日付)において、ユーザーに数値を入力するようプロンプトをしたいのですが、 PROCEDURE SHOW_BIZDAYS( v_start_date IN DATE := sysdate) IS ACCEPT tdays PROMPT 'Enter how many days are needed: ' v_bus_days NUMBER := &tdays; と記載するとACCEPT文が無効とのエラーが検出されます。パッケージ内ではACCEPTが使用できないということでしょうか。 ■パッケージ create or replace PACKAGE test IS PROCEDURE SHOW_BIZDAYS( v_start_date IN DATE := sysdate, v_bus_days IN NUMBER := 30); PROCEDURE SHOW_BIZDAYS( v_start_date IN DATE := sysdate); END test; ■パッケージ本体 create or replace PACKAGE BODY test IS PROCEDURE SHOW_BIZDAYS( v_start_date IN DATE := sysdate, v_bus_days IN NUMBER := 30) IS v_counter NUMBER(3) := 1; v_date DATE := v_start_date; BEGIN WHILE v_counter <= v_bus_days LOOP IF UPPER(TO_CHAR(v_date, 'D')) NOT IN (1, 7) THEN DBMS_OUTPUT.PUT_LINE('The index is : ' || v_counter || ' and the table value is: ' || v_date); v_counter := v_counter + 1; END IF; v_date := v_date + 1; END LOOP; END SHOW_BIZDAYS; PROCEDURE SHOW_BIZDAYS( v_start_date IN DATE := sysdate) IS ACCEPT tdays PROMPT 'Enter how many days are needed : '; v_bus_days NUMBER := &tdays; v_counter NUMBER(3) := 1; v_date DATE := v_start_date; BEGIN WHILE v_counter <= v_bus_days LOOP IF UPPER(TO_CHAR(v_date, 'D')) NOT IN (1, 7) THEN DBMS_OUTPUT.PUT_LINE('The index is : ' || v_counter || ' and the table value is: ' || v_date); v_counter := v_counter + 1; END IF; v_date := v_date + 1; END LOOP; END SHOW_BIZDAYS; END test; 初歩的な質問で申し訳ありませんが、下記につきアドバイスをお願いします。

  • C#で、引数における一次元と二次元配列の取り扱い

    C#について質問させていただきます。 以下のようにすればそれぞれ一次元配列と二次元配列を格納出来ますが 同時に一つの引数に収めることは無理なのでしょうか?    public static void Join(string[] Ary_str){ 本文 }    public static void Join(string[ , ] Ary_str){ 本文 } そのために、例えば以下のようにしたとします。    public static void Join(object Ary_obj){ 本文 } こうすれば一次元でも二次元でも格納出来ますが 格納された値が何次元配列なのか確認するために    Ary_obj.Rank としてもエラーになってしまいます。 (1)Objectに格納した値が何次元配列なのか確認する方法か (2)一次元でも二次元でも格納できる引数の指定方法 をご存じの方、ぜひお教え願います。><