e-learning、オラクル研修、LMS(学習管理システム)のiStudy

e-learning、オラクル研修、LMS(学習管理システム)のiStudy

第12回 「レコード変数について」

2012.03.12

今回はレコード変数について詳しく解説します。

前回までは、6回ほど明示カーソル処理を詳しく解説してきました。そのなかで変数というと、以下の回で触れてきました。

・第3回 変数について(その1)  ※⇒ 基本的な変数の宣言
・第4回 変数について(その2)  ※⇒ %TYPEを用いた変数宣言
・第8回 明示カーソル処理(詳細) ※⇒ %ROWTYPEを用いたレコード変数の宣言

上述の通り第8回で、%ROWTYPEを用いたレコード変数の宣言方法について解説しましたが、今回はもう少し詳しくレコード変数を解説します。すなわち%ROWTYPEを使わずに自分でレコード型を宣言してからレコード変数を宣言する方法です。

%ROWTYPEは、明示カーソルや表の定義をもとに、その行と同じレコード型であることを宣言するときに用いるものでした。すなわちその行の列と同じ名前、同じデータ型のフィールドをもつレコード型変数を定義をするときに使える非常に簡単な宣言方法です。
以下の構文でしたね。

<宣言部で>
 レコード変数名   表名%ROWTYPE;
 レコード変数名   明示カーソル名%ROWTYPE;

とても簡単な構文です。
特に 表名%ROWTYPE型の変数は、 SELECT * INTO ~ の代入先に使えるのでとても気楽に使えそうです。
しかし、そこで取得した行レコードのフィールドの大部分を実際にプログラムで使用すれのであればそれでいいのですが、実際に使用するフィールドはごくわずかという状況だとすると、%ROWTYPEによる宣言はメモリの無駄遣いになりかねません。
たとえば良くない例として以下のような記述をご覧ください。

<改善前>
SQL> CONNECT scott/tiger
接続されました。
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
 2    REC  EMP%ROWTYPE;
 3 BEGIN
 4    SELECT * INTO REC FROM EMP WHERE EMPNO=7934;
 5    DBMS_OUTPUT.PUT_LINE(REC.ENAME || ' は ' || REC.JOB || ' です');
 6 END;
 7 /
MILLER は CLERK です

PL/SQLプロシージャが正常に完了しました。

ここでは、2行目(行番号2のところ)で、EMP表の行と同じ構造のレコード変数RECを宣言し、4行目で SELECT INTO文により、社員番号 7934の社員の行レコードを取得し、5行目で ENAMEフィールとJOBフィールドを使って、「MILLER は CLERK です」という結果をSQL*Plusの画面に表示しているわけです。
せっかくEMP表の1行をレコード変数RECに格納したのに、実際に使っているフィールドはENAMEとJOBだけであれば他のフィールドは意味なくメモリを浪費しているだけですね。
実際にはEMP表の行はそれほどサイズが大きくないので問題ではありませんが、これが非常に1行のサイズの大きな表でこのような処理を頻繁に行っているとすると、やはり看過できないメモリの無駄遣いと言えます。
そういった場合、実際に使用するフィールドだけでレコード変数を宣言し、実際に使用する列のみを問合せの対象にすべきです。
以下はそのように改善した例です。

<改善後>
SQL> DECLARE
 2   TYPE  REC_TYPE IS RECORD
 3         (ENAME  VARCHAR2(10),
 4          JOB    VARCHAR2(9)  );
 5   REC   REC_TYPE;
 6 BEGIN
 7   SELECT ENAME, JOB INTO REC FROM EMP WHERE EMPNO=7934;
 8   DBMS_OUTPUT.PUT_LINE(REC.ENAME || ' は ' || REC.JOB || ' です');
 9 END;
 10 /
MILLER は CLERK です

PL/SQLプロシージャが正常に完了しました。

ここで注目していただきたいのは、2~4行目でENAME, JOBという二つのフィールドを持つレコード型を宣言します(その型の名前はREC_TYPEです)。そして5行目でそのREC_TYPE型を使ってレコード変数RECを宣言しているわけです。
このように記述するとレコード変数RECは ENAMEとJOBの二つのフィールドしか持たないのでサイズも小さくなります。
これにより、7行目のSELECT INTOによるレコード変数への代入ではENAME列とJOB列だけを問合せの対象とするわけです。
以降の処理は改善前と同じです。

このように、%ROWTYPEを使って既存の表の定義を利用するのではなく、ユーザが使用したい型を自分で宣言して、その型を使ってレコード変数を宣言するわけです。
したがって、2段階の宣言となります(型の宣言、その型を使った変数の宣言)。
構文としてまとめると以下のようになります。

<型の宣言>
  TYPE 型名 IS RECORD (フィールド名1  データ型, フィールド名2 データ型, ・・・);
<変数の宣言>
  変数名  上記の型名;

変数は値を格納する箱といえますが、型の宣言だけでは「箱」は用意されておらず、その型を使った変数宣言をして初めて、値を入れることのできる「箱」がメモリ上に用意されます。

表名%ROWTYPEを使えば、レコード変数の宣言は1回の宣言で済みますが、場合によってはメモリを無駄にします。
そのような場合、面倒でも実際に使用するフィールドでレコード型を宣言し、その型での変数宣言を心がけてください。

それでは今回はここまでです。

先頭へ戻る