Oracleエンジニアを目指す
ORACLE MASTER Gold ポイント解説
第3回 PL/SQLの実行部を学ぶ

小野寺智子
2002/5/24

 前回(「第2回 PL/SQLの基本を学ぶ」)に引き続き、PL/SQLによる「Oracle Serverの操作」、「制御構造」、「複合データ型の処理(コレクション)」のポイントを解説します。今回は前回解説した「実行部」の中核に迫ります。

■Oracle Serverの操作

 Oracle Serverの操作とは、PL/SQLブロック内にSQL文を記述し、データベースを操作する方法などを指します。ここでは使用できるSQL文やトランザクション制御を解説します。

 ただし、その前にORACLE MASTER Silverで学習した内容を思い出してください。PL/SQLの試験範囲にはSilverで学習した内容もたびたび出るので、次のことは忘れないようにしましょう。

ORACLE MASTER Silverの復習
種類
コマンド
説明
データ検索文 SELECT文 データを検索する
DML(データ操作文) INSERT、UPDATE、DELETE文 挿入・更新・削除を行う
DDL(データ定義文) CREATE、ALTER、DROPなどの文 表の作成、変更などを行う
DCL(トランザクション制御) COMMIT、ROLLBACK、SAVEPOINT 更新の確定や取り消しなどを行う

 これらをPL/SQLブロック内で使用するときには、さらに次のような規則・注意点があります。

(1)SELECT文では1件のデータしか取り出せない
 PL/SQLブロック内でSELECT文を使用する際には、1件のデータしか返しません。0件や複数行の場合はエラーを返します。また、SELECT文を使用するときはINTO句が必須です。INTO句は、SELECTとFROMの間に指定します。

(2)DMLを使用するに当たってはPL/SQLブロック内での制限はない
 PL/SQLブロック内ではINSERTやUPDATEといったDMLを使用することができます。対象行が0件や複数行であってもエラーを返しません。また、データの挿入(INSERT)では、SQL関数(USER、SYSDATEなど)を使用することができます。

(3)DDLの使用は原則できない(例外あり)
 PL/SQLブロック内でCREATE、ALTERなどのDDLは原則として使用できません。ただし、DBMS_SQLパッケージを利用すると実行できるようになります。DBMS_SQLパッケージの内容については、試験で問われることはありませんが、このような機能があることは、試験で出題される可能性があるので、言葉自体は覚えておくといいでしょう。

(4)トランザクション制御の埋め込みが可能
 PL/SQLブロック内では、トランザクション単位でデータベースを確定したり、取り消したりすることができます。ここで間違えやすいのがトランザクション単位です。トランザクション単位とは、COMMITやROLLBACKといったコマンドを使用したトランザクション制御のことで、ブロック内の「BEGIN〜END」間の処理のことはトランザクション処理とはいいません。

■「カーソル」とは?

 SQL文を解析して実行するために「コンテキスト領域」というメモリ領域が割り当てられます。このコンテキスト領域には、処理に必要な情報が格納されます。カーソルとは、このコンテキスト領域に対するポインタのことを指します。カーソルには以下の2つのタイプがあります。

  • 暗黙カーソル
  • 明示カーソル

 PL/SQLブロック内でSQL文を発行すると暗黙カーソルが作成され、SQL文の解析と実行を行い、PL/SQLによって自動的に管理されます。暗黙カーソルは、DMLやSELECT文で使用されます。明示カーソルは、明示的に宣言した名前付きのカーソルで複数行を返すSELECT文で使用されます。なお、明示カーソルの詳細は、次回で詳しく説明する予定です。

 暗黙カーソルが使用された場合、その評価を行うためにSQLカーソル属性はSQL文の結果のテスト(検証)をすることができます。使用できる属性を次に示します。

SQL%ROWCOUNT SQL文による現在までの処理 対象行の数
(整数値)を返す
SQL%FOUND SQL文で1行以上のデータを処理した場合、
結果が「TRUE」になる
SQL%NOTFOUND SQL文でデータが処理されなかった場合、
結果が「TRUE」になる
SQL%ISOPEN Oracle Serverの制御によって暗黙 カーソ
ル実行直後にクローズされるため、結果は
常に「FALSE」になる
カーソルの属性。SQL%ROWCOUNT、SQL%FOUNDはDMLの実行に関する情報を収集する。また、SQL%NOTFOUND、SQL%ISOPENはブロックの実行部か例外処理部に指定する

■制御構造の作成

 ここでは、PL/SQLブロック内で処理順序を制御する方法を解説します。ほかのプログラミング言語同様に、「順次構造」「分岐制御」「反復制御」といった制御構造の記述ができます(図1)。

図2 「順次構造」「分岐制御」「反復制御」の基本的な流れ

 順次構造は一連の文を順番に実行します。分岐制御はIF文を使用して文の条件を判断し処理を分岐します。反復制御はループ文を使用して一連の文を反復して文の条件を処理します。なお、順次構造、分岐制御、反復制御という用語には、さまざまな呼び方がありますが、すべて同じ意味と考えて間違いありません。

順次構造 IF−THEN文、順次制御
分岐構造 条件分岐、分岐構造
反復制御 反復構造、ループ文
よく見かける時制御構造の呼び方

IF文:分岐制御
 分岐制御ではIF文を使用します。IF文には次の3つの形式があります。

IF-THEN-END IF;

IF 条件A THEN
条件Aであれば行う処理;
END IF;

IF-THEN-ELSE-END IF;

IF 条件A THEN
条件Aであれば行う処理;
ELSE
 条件Aを満たしていない場合の処理;
END IF;

IF-THEN-ELSIF-END IF;

IF 条件A THEN
 条件Aであれば行う処理;
ELSIF 条件B THEN
 条件Bであれば行う処理;
ELSIF 条件C THEN
 条件Cであれば行う処理;
 ……
 ……  ←(複数指定可)
 ……
ELSE 
  処理 N;
END IF;

 IF文で注意したいことの1つはスペルです。ELSIFは1語ですが、END IFは2語になります。試験で緊張すると、こうしたところでミスをすることもあり、気を付けてほしい点です。また、IF文はネストにして、条件を絞り込むことができます。ただし、ネストが深くなるとプログラムは読みづらく、メンテナンスにも手間がかかるので、あまり勧められません。

ループ(LOOP)文:反復制御
 反復制御では3つの形式のループ文があります。

基本ループ

WHILEループ FORループ
LOOP
処理;
EXIT (WHEN 条件);
END LOOP;
WHILE 条件 LOOP END LOOP; FOR カウンタ名 IN 下限値..上限値 LOOP
処理;
END LOOP;

 基本ループが最も単純な形式で、LOOPとEND LOOPキーワードで一連の実行文を囲んだものです。ここでEXITを含めないと無限ループになります。EXITはループ内に指定します。また、WHEN句を使用することによってループを抜ける条件を設定できます。

 WHILEループは、ループを行う前に条件を評価します。条件が「TRUE」であればループは反復処理を行いますが、条件が「FALSE」になるとループは終了します。ただし、1度もループを通らずに終了することもあります。

 FORループは、あからじめ明示的に反復回数が分かる場合に使用します。宣言部でカウンタ名を宣言する必要はありません。なお、REVERSEキーワードを使用する場合は、次のように値の設定を「最小値..最大値」と設定します。

FORループ文でREVERSEキーワードを利用する場合の構文

論理条件の作成
 IF文の条件を比較するには比較演算子を用います。結果はブール属性の論理値になります。この中で特に注意したいのは、「NULL」値の扱いです。一般的にNULL値を扱うにはIS NULL演算子を使用します。この場合、NULL値が含まれている式の評価はすべてNULLと評価されます。ただし、文字の連結を使用した場合は例外で、NULLは空と評価されます。

 ここで、論理値表と比較演算子表を示します。この表は覚えてください。比較演算子表はSilverで学習したものとほぼ同じものです(図2)。

図2 論理値表と比較演算子表

■複合データ型(コレクション)とは?

 PL/SQLでは一度に多数の変数をまとめて宣言することができます。このようなデータ型のことを「コレクション」と呼びます。複合データ型には、次のようなデータ型があります。

  • RECORD
  • TABLE
  • NESTED TABLE
  • VARRAY

 ここではこの中から、「RECORD」と「TABLE」について説明します。なお、RECORDとTABLE以外はほとんど出題されません。

RECORD
 RECORD(レコード)は、フィールドに格納されるいくつかの関連したデータ項目のグループで、データ項目が独自の名前とデータ型を持ちます。スカラー、RECORD、コレクションのいずれかのデータ型を持ち、フィールドと呼ばれるコンポーネントが1つ以上含まれます(図3)。

図3 RECORD(レコード)の構造。ここではフィールド(DEPTNO,DNAME,LOC)が集まって1つのレコードを形成している。各フィールドにはデータ型も格納する

 RECORDを作成するにはRECORD型を宣言部で定義し、変数の宣言を行います。

RECORD型の構文

TABLE(索引付き表)
 TABLE型のオブジェクトを指します。TABLEはデータ型の主キーとスカラー、またはRECORDデータ型の列と2つのコンポーネントから構成されます。データ型の主キーは、BINARY_INTEGERでPLS_INTEGERは使用できません。索引付きの表は宣言時に初期化ができません。なお、テーブル型の構文は次のとおりです。

TABLE型の構文

 表のサイズと同じく、索引付きの表のサイズも無制限です。索引付き表には1つの列と添え字を入れることができますが、いずれも名前の指定はできません。添え字は必ずしも連続した数値でなくても構いませんが、存在しない添え字を参照するとエラーを返します。

RECORDの索引付き表
 RECORD型と索引付き表を合わせた表のことを指します。RECORDの索引付き表はRECORD型の列に構成されます。この表を使用すると表のすべてのフィールドに関する情報を保持できます。そのため、変数の宣言を簡単にでき、パフォーマンスを大幅に向上させることができます。RECORDの索引付き表の構文は、次のとおりです。

レコードの索引付き表の構文

%ROWTYPE
 さて、最後に前回(「第2回 PL/SQLの基本を学ぶ」)に解説した「%TYPE」を思い出してください。%TYPEは、データベース表内の列や以前に宣言された別の変数に合わせて変数を宣言できました。これに対して「%ROWTYPE」は、表やビュー内の列のコレクションに基づいて宣言することができます。その書式は次のとおりです。

%ROWTYPEを利用した構文

 それでは、この%ROWTYPEを使用するとどんな利点があるのでしょうか? %ROWTYPEを利用すれば、元のデータベース表の列の数やデータ型を知らなくても構わないというメリットがあるのです。ですから、元の表のデータ型を参照しなくとも、%ROWTYPE属性を使用することで、元の表と同じものを定義できます。さらに、元の表に変更が生じても変更する必要はありません。また、SELECT文を使用して行を取り出す場合にも便利です。

 ただし、データ型は継承しますが制約に関しては継承しません。また列の制約には関係なくNOT NULLを追加できますが、その場合は宣言したフィールドに初期値の設定が必要になります。

コラム:CASE文

 2月からOracle 9iに対応する試験が開始されました。これから9i対応で受ける人、ORACLE MASTER Platinum 8iを受けて移行試験を考える人など、さまざまな選択肢が考えられます。

 しかし、ここで問題が生じました。バージョンに関係のないSQL入門、Oracle入門、PL/SQLはこれまでどおりで、バージョンに対応する教材がなくとも問題はないと考えていたのですが、これまでは出たことがなかったキーワード(範囲)が試験に出題されたというのです。取りあえず今回は、新しく加わったキーワード、CASE文の説明を少しだけしておきたいと思います。

 CASE文はIF文と同じように実行できますが、結果を選択して返します。ブール属性を使用しないため選択子を使用します。選択子とは、複数の選択肢から1つを選択するために値が使用される式です。「IF-THEN-ELSIF」文の後継ともいえる文ですが、CASE文の方がスマートなプログラムで効率的です。実践的な話になりますが、これからはなるべくCASE文を使用した方がいいかもしれません。その理由は、分かりやすく、メンテナンスも楽だからです。そして記述する文字量が少ないため、パフォーマンスの向上にも役立ちます。

 CASE文は、これまで聞いたことのない言葉だと思いますが、少しでも分かれば試験で動揺することはないと思います。今後CASE文などの新しい範囲については、次回にさらに詳しく解説する予定です。


「連載 ORACE MASTER Goldポイント解説」

自分戦略研究所、フォーラム化のお知らせ

@IT自分戦略研究所は2014年2月、@ITのフォーラムになりました。

現在ご覧いただいている記事は、既掲載記事をアーカイブ化したものです。新着記事は、 新しくなったトップページよりご覧ください。

これからも、@IT自分戦略研究所をよろしくお願いいたします。