ここから本文です

超入門「PL/SQL」:宣言部と変数の定義 「%TYPE」「%ROWTYPE」

7/7(金) 8:10配信

@IT

 本記事は、Oracle Database向けにデータベース言語 SQL(Structured Query Language)を拡張したプログラミング言語である「PL/SQL(Procedure Language/Structured Query Language)」を理解し、活用していくための実践講座です。SQLは知っているけれど、OracleでのPL/SQLは初めてという人向けに、機能の概要と具体的な書き方を解説していきます。

「%ROWTYPE」属性で定義した変数の構造

 今回は、「%TYPE」「%ROWTYPE」属性を使用した変数の定義方法を解説します。

●「%TYPE」「%ROWTYPE」属性とは何か

 「%TYPE」「%ROWTYPE」属性では、表の列や行、または既に宣言された変数のデータ型を参照する「変数」を定義できます。

 PL/SQLでは、Oracle Database内の表から取り出したデータを「変数に代入」して処理することがよくあります。このような場合には、変数のデータ型を直接指定するのではなく、「%TYPE」や「%ROWTYPE」属性を使うと効率が上がります。例えば以下のような記述になります。

・%TYPE属性で定義した変数のサンプルプログラム
――――――
DECLARE
 e_deptno dept.deptno%TYPE;
BEGIN
 NULL;
END;
/
――――――


 このサンプルプログラムでは、変数「e_deptno」を「dept.deptno%TYPE」で定義したものです。これで、「“DEPT”表の“DEPTNO”列のデータ型を参照する」という記述になります。

 「%TYPE」「%ROWTYPE」属性を使う利点は次の通りです。


1. 列の定義が変更になってもプログラムの修正が必要ない
2. 列の正確な定義が分からなくても変数を定義できる

 もう少し具体的な例で考えてみましょう。

 “DEPT”表の“DEPTNO”列が「NUMBER型」で、その最大サイズが「2」だとします。この列のデータを格納する変数を「直接データ型で定義する」場合には、列の定義に合わせて「NUMBER(2)」と指定します。

 しかしその後、DEPT表のDEPTNO列の最大サイズが「4」に拡大されたとしたらどうすれば良いのでしょう。直接定義している場合には、「関係する変数の定義」も同時に変更しなければエラーが発生する可能性があります。

 この課題は、データ型に「%TYPE」「%ROWTYPE」属性を定義することで回避できます。「%TYPE」「%ROWTYPE」属性は列のデータ型や、既に定義されている変数のデータ型を参照すると前述しました。ですから、対応する列定義の変更に合わせて変数のデータ型も自動的に変更されるのです。「プログラムの修正が必要ない」のはこのためです。

 また、列定義を参照することから、列の正確なデータ型や最大サイズを知らないとしても変数を簡単に定義できます。

 続いて、各属性の書式を確認しましょう。

●「%TYPE」属性

 「%TYPE」属性は、特定の表の列、または、事前に定義されている変数のデータ型およびサイズを参照します。通常の変数と同様に、代入演算子(:=)または「DEFAULTキーワード」による初期値や「NOT NULL制約」の指定も可能です。

 変数を定義する書式は以下の通りです。

・変数を定義する書式
――――――
<変数名> <表名>.<列名>%TYPE;
――――――

 サンプルプログラムは以下の通りです。

・「%TYPE」属性を使ったサンプルプログラム
――――――
DECLARE
 e_deptno dept.deptno%TYPE := 50;
 v_deptno e_deptno%TYPE;
BEGIN
 NULL;
END;
/
――――――

 このサンプルプログラムでは、変数「e_deptno」を「dept.deptno%TYPE」と定義し、“DEPT”表の“DEPTNO”列のデータ型を参照しています。さらに代入演算子「:=」によって初期値「50」を代入しています。

 続く変数「v_deptno」は「e_deptno%TYPE」と定義しています。つまり、変数「e_deptno」と同じデータ型を参照しています。

●「%ROWTYPE」属性

 「%ROWTYPE」属性は、「表(またはビュー)の行構造」を参照します。行全体のデータを扱う場合は、「%TYPE」属性で1列ずつ変数を定義するよりも効率的です。

 ただし「%ROWTYPE」属性は、「%TYPE」属性とは異なり、「初期値」や「NOT NULL制約」は指定できません。

 変数を定義する書式は以下の通りです。

・変数を定義する書式
――――――
<変数名> <表名>%ROWTYPE;
――――――

 サンプルプログラムは以下の通りです。

・「%ROWTYPE」属性を使ったサンプルプログラム
――――――
DECLARE
 d_row dept%ROWTYPE;
BEGIN
 NULL;
END;
/
――――――

 このサンプルプログラムでは、変数「d_row」を「dept%ROWTYPE」とし、“DEPT”表の「行の構造」を参照しています。

 「%ROWTYPE」属性で定義した変数は、次の特徴があります。

・行構造と同じ数の領域(フィールド)が確保される
・各フィールドの名前やデータ型は、参照する列の名前とデータ型をそのまま踏襲する

 「%ROWTYPE」属性で定義した変数は、以下のような構造になっています。

 サンプルプログラムの変数「d_row」は、参照している“DEPT”表と同様に3つのフィールドで構成されています。各フィールドの名前「DEPTNO」「DNAME」「LOC」やデータ型「NUMBER(2)」「VARCHAR2(14)」「VARCHAR2(13)」もDEPT表と同じになります。

 ちなみに値の参照や代入などで各フィールドにアクセスしたい場合には、「.」の書式で指定します。サンプルプログラムは以下の通りです。

・「%ROWTYPE」属性を使い、値の参照や代入などで各フィールドにアクセスする場合のサンプルプログラム
――――――
DECLARE
 d_row dept%ROWTYPE;
BEGIN
 d_row.deptno := 10; /* 変数d_rowのDEPTNOフィールドに10を代入 */
 DBMS_OUTPUT.PUT_LINE(d_row.deptno); /* 変数d_rowのDEPTNOフィールドに代入されている値を表示 */
END;
/
――――――

 このサンプルプログラムで「%ROWTYPE」属性で定義した変数は、本来はカーソルなどを使って表から取り出したデータを処理するような場合に使います。こちらの詳細は今後の連載で解説する予定です。

□□□□
●定義時の注意点

 変数の定義においては、「%TYPE」「%ROWTYPE」属性を指定して別の変数のデータ型を参照することもできます。ただしPL/SQLでは、ソースコードの上から順にプログラムを処理していく仕様のため、「前方参照(ソースコードの現在地よりも後方に定義されているものを参照すること)」はできないことに注意しましょう。

 例えば以下の記述では、変数「v_deptno」のデータ型が変数「e_deptno」を参照するように書かれています。しかしこの時点では変数「e_deptno」はまだ定義されていません。従って、エラーとなってしまいます。

・【NG記述の例】変数の「前方参照」はできない
――――――
DECLARE
v_deptno e_deptno%TYPE;
e_deptno dept.deptno%TYPE := 50;

――――――
□□□□


●「定数」の使い方

 PL/SQLブロックでデータを扱う場合、多くは「変数」を用います。しかし場合によっては「定数」を使う方が良いシーンもあります。

 定数も変数と同じようにデータを保存しておく場所を定義するものです。しかしその名前の通り「定められた値」として、いったん格納された値は上書きできず、PL/SQLブロックの終了まで固定値を保持します。例えば「税率」など、プログラム内で常に同じ値を使い続けたい場合に適しています。

・定数を定義する書式
――――――
<定数名> CONSTANT <データ型> [ NOT NULL ] { := | DEFAULT } <初期値> ;
――――――

 サンプルプログラムは以下の通りです。

・「定数」を定義するサンプルプログラム
――――――
DECLARE
 v_no_cons CONSTANT NUMBER(8) := 1; /* 定数v_no_consをNUMBER型で定義し、初期値「1」を代入 */
BEGIN
 NULL; /* 何もせずに次に制御を移す */
END;
/
――――――

 定数の記述では、定数名の後に「CONSTANTキーワード」を指定するのが変数定義時と異なります。また、定数の定義時には必ず代入演算子「:=」、または「DEFAULTキーワード」で初期値を指定する必要があります。前述したように、定数の定義後に値は代入できません。


 今回は「%TYPEおよび%ROWTYPE属性の変数を定義する記述方法」の基礎を紹介しました。次回から、「定義した変数に値を代入する」「値を評価した上で処理を分岐する」など、実行部に記述する実際の処理内容の詳細を解説していきます。

●筆者紹介

小笠原宏幸(おがさわら ひろゆき)

株式会社アシスト データベース技術本部所属。普段はOracle、PostgreSQL、JP1などの分野で研修講師を担当。また、書籍「SQL逆引き大全363の極意」(株式会社秀和システム)をはじめ、「これならわかるOracle超入門教室」(株式会社翔泳社)、「プロとしてのPL/SQL入門」(SBクリエイティブ株式会社)の共著も担当。

最終更新:7/7(金) 8:10
@IT