...

PL/SQL ユーザーズ・ガイドおよびリファレンス

by user

on
Category: Documents
1109

views

Report

Comments

Transcript

PL/SQL ユーザーズ・ガイドおよびリファレンス
Oracle® Database
PL/SQL ユーザーズ・ガイドおよびリファレンス
10g リリース 2(10.2)
部品番号 : B19257-01
2005 年 7 月
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス , 10g リリース 2(10.2)
部品番号 : B19257-01
原本名 : Oracle Database PL/SQL User’s Guide and Reference 10g Release 2 (10.2)
原本部品番号 : B14261-01
原本著者 : Shashaanka Agrawal、Cailein Barclay、Eric Belden、Dmitri Bronnikov、Sharon Castledine、
Thomas Chang、Ravindra Dani、Chandrasekharan Iyer、Susan Kotsovolos、Neil Le、Warren Li、
Bryn Llewellyn、Valarie Moore、Chris Racicot、Murali Vemulapati、John Russell、Guhan Viswanathan、
Minghui Yang
Copyright © 1996, 2005, Oracle. All rights reserved.
制限付権利の説明
このプログラム(ソフトウェアおよびドキュメントを含む)には、オラクル社およびその関連会社に所有権
のある情報が含まれています。このプログラムの使用または開示は、オラクル社およびその関連会社との契
約に記された制約条件に従うものとします。著作権、特許権およびその他の知的財産権と工業所有権に関す
る法律により保護されています。
独立して作成された他のソフトウェアとの互換性を得るために必要な場合、もしくは法律によって規定され
る場合を除き、このプログラムのリバース・エンジニアリング、逆アセンブル、逆コンパイル等は禁止され
ています。
このドキュメントの情報は、予告なしに変更される場合があります。オラクル社およびその関連会社は、こ
のドキュメントに誤りが無いことの保証は致し兼ねます。これらのプログラムのライセンス契約で許諾され
ている場合を除き、プログラムを形式、手段(電子的または機械的)
、目的に関係なく、複製または転用す
ることはできません。
このプログラムが米国政府機関、もしくは米国政府機関に代わってこのプログラムをライセンスまたは使用
する者に提供される場合は、次の注意が適用されます。
U.S. GOVERNMENT RIGHTS
Programs, software, databases, and related documentation and technical data delivered to U.S. Government
customers are "commercial computer software" or "commercial technical data" pursuant to the applicable
Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication,
disclosure, modification, and adaptation of the Programs, including documentation and technical data, shall
be subject to the licensing restrictions set forth in the applicable Oracle license agreement, and, to the extent
applicable, the additional rights set forth in FAR 52.227-19, Commercial Computer Software--Restricted
Rights (June 1987). Oracle Corporation, 500 Oracle Parkway, Redwood City, CA 94065.
このプログラムは、核、航空産業、大量輸送、医療あるいはその他の危険が伴うアプリケーションへの用途
を目的としておりません。このプログラムをかかる目的で使用する際、上述のアプリケーションを安全に使
用するために、適切な安全装置、バックアップ、冗長性(redundancy)、その他の対策を講じることは使用
者の責任となります。万一かかるプログラムの使用に起因して損害が発生いたしましても、オラクル社およ
びその関連会社は一切責任を負いかねます。
Oracle、JD Edwards、PeopleSoft、Retek は米国 Oracle Corporation およびその子会社、関連会社の登録商
標です。その他の名称は、他社の商標の可能性があります。
このプログラムは、第三者の Web サイトへリンクし、第三者のコンテンツ、製品、サービスへアクセスす
ることがあります。オラクル社およびその関連会社は第三者の Web サイトで提供されるコンテンツについ
ては、一切の責任を負いかねます。当該コンテンツの利用は、お客様の責任になります。第三者の製品また
はサービスを購入する場合は、第三者と直接の取引となります。オラクル社およびその関連会社は、第三者
の製品およびサービスの品質、契約の履行(製品またはサービスの提供、保証義務を含む)に関しては責任
を負いかねます。また、第三者との取引により損失や損害が発生いたしましても、オラクル社およびその関
連会社は一切の責任を負いかねます。
目次
はじめに ...............................................................................................................................................................................
xv
対象読者 ........................................................................................................................................................................
ドキュメントのアクセシビリティについて ............................................................................................................
このマニュアルの構成 ................................................................................................................................................
PL/SQL のサンプル・プログラム ...........................................................................................................................
関連ドキュメント .......................................................................................................................................................
表記規則 ........................................................................................................................................................................
サポートおよびサービス .............................................................................................................................................
xvi
xvi
xvi
xviii
xviii
xix
xx
PL/SQL の新機能
........................................................................................................................................................ xxiii
Oracle Database 10g リリース 2(10.2)の PL/SQL の新機能 ..........................................................................
Oracle Database 10g リリース 1(10.1)の PL/SQL の新機能 ..........................................................................
1
xxiv
xxiv
PL/SQL の概要
PL/SQL のメリット .................................................................................................................................................... 1-2
SQL との緊密な統合 ........................................................................................................................................... 1-2
高いパフォーマンス ............................................................................................................................................ 1-3
高い生産性 ............................................................................................................................................................ 1-3
完全な移植性 ........................................................................................................................................................ 1-4
優れたセキュリティ ............................................................................................................................................ 1-4
事前定義パッケージへのアクセス .................................................................................................................... 1-4
オブジェクト指向プログラミングのサポート ................................................................................................ 1-4
Web アプリケーションおよび Web ページ開発のサポート ........................................................................ 1-4
PL/SQL の主な特長 .................................................................................................................................................... 1-5
PL/SQL ブロック構造 ........................................................................................................................................ 1-5
PL/SQL の変数および定数 ................................................................................................................................
変数の宣言 ....................................................................................................................................................
変数への値の代入 ........................................................................................................................................
バインド変数 ................................................................................................................................................
定数の宣言 ....................................................................................................................................................
1-5
1-5
1-6
1-7
1-7
PL/SQL を使用した問合せの処理 .................................................................................................................... 1-8
PL/SQL サブプログラムの宣言 ........................................................................................................................ 1-8
PL/SQL 変数のデータ型の宣言 ........................................................................................................................ 1-8
%TYPE .......................................................................................................................................................... 1-8
%ROWTYPE ................................................................................................................................................. 1-9
PL/SQL の制御構造 ............................................................................................................................................ 1-9
i
条件制御 ........................................................................................................................................................ 1-9
反復制御 ...................................................................................................................................................... 1-10
順次制御 ...................................................................................................................................................... 1-12
条件付きコンパイル .......................................................................................................................................... 1-12
再利用可能な PL/SQL コードの作成 ............................................................................................................. 1-12
サブプログラム : プロシージャおよび機能 ........................................................................................... 1-12
パッケージ : PL/SQL で記述された API ............................................................................................... 1-13
PL/SQL を使用したデータの入出力 .............................................................................................................. 1-15
PL/SQL のデータの抽象化 ..............................................................................................................................
カーソル ......................................................................................................................................................
コレクション ..............................................................................................................................................
レコード ......................................................................................................................................................
オブジェクト型 ..........................................................................................................................................
1-15
1-15
1-15
1-16
1-16
PL/SQL エラーの処理 ...................................................................................................................................... 1-17
PL/SQL アーキテクチャ ........................................................................................................................................... 1-18
Oracle データベース・サーバー .....................................................................................................................
無名ブロック ..............................................................................................................................................
ストアド・サブプログラム ......................................................................................................................
データベース・トリガー ..........................................................................................................................
1-18
1-18
1-18
1-19
Oracle のツール製品 ......................................................................................................................................... 1-20
2
PL/SQL 言語の基礎
キャラクタ・セットおよび字句単位 ........................................................................................................................ 2-2
デリミタ ................................................................................................................................................................ 2-2
識別子 ....................................................................................................................................................................
予約語 ............................................................................................................................................................
事前定義の識別子 ........................................................................................................................................
二重引用符で囲んだ識別子 ........................................................................................................................
2-3
2-4
2-4
2-5
リテラル ................................................................................................................................................................
数値リテラル ................................................................................................................................................
文字リテラル ................................................................................................................................................
文字列リテラル ............................................................................................................................................
ブール・リテラル ........................................................................................................................................
日時リテラル ................................................................................................................................................
2-5
2-5
2-6
2-6
2-7
2-7
コメント ................................................................................................................................................................
単一行コメント ............................................................................................................................................
複数行コメント ............................................................................................................................................
コメントの制限 ............................................................................................................................................
宣言 ................................................................................................................................................................................
2-7
2-8
2-8
2-8
2-9
定数 ........................................................................................................................................................................ 2-9
DEFAULT の使用 ................................................................................................................................................ 2-9
NOT NULL の使用 ............................................................................................................................................ 2-10
%TYPE 属性の使用 ............................................................................................................................................ 2-10
%ROWTYPE 属性の使用 .................................................................................................................................. 2-11
集計代入 ...................................................................................................................................................... 2-12
エイリアシングの使用 .............................................................................................................................. 2-12
宣言の制限 .......................................................................................................................................................... 2-13
PL/SQL のネーミング規則 ....................................................................................................................................... 2-13
PL/SQL の識別子の有効範囲と可視性 ................................................................................................................... 2-15
ii
変数への値の代入 ...................................................................................................................................................... 2-18
ブール値の代入 .................................................................................................................................................. 2-18
SQL 問合せ結果の PL/SQL 変数への代入 .................................................................................................... 2-18
PL/SQL の式および比較 .......................................................................................................................................... 2-19
論理演算子 ..........................................................................................................................................................
評価の順序 ..................................................................................................................................................
短絡評価 ......................................................................................................................................................
比較演算子 ..................................................................................................................................................
関係演算子 ..................................................................................................................................................
IS NULL 演算子 .........................................................................................................................................
LIKE 演算子 ................................................................................................................................................
BETWEEN 演算子 .....................................................................................................................................
IN 演算子 ....................................................................................................................................................
連結演算子 ..................................................................................................................................................
2-20
2-20
2-21
2-21
2-22
2-22
2-22
2-22
2-22
2-23
ブール式 ..............................................................................................................................................................
ブール算術式 ..............................................................................................................................................
ブール文字式 ..............................................................................................................................................
ブール日付式 ..............................................................................................................................................
PL/SQL ブール式のガイドライン ..........................................................................................................
2-23
2-23
2-23
2-24
2-24
CASE 式 .............................................................................................................................................................. 2-25
単純な CASE 式 ......................................................................................................................................... 2-25
検索 CASE 式 ............................................................................................................................................. 2-26
比較文と条件文での NULL の扱い ................................................................................................................ 2-26
NULL と NOT 演算子 .............................................................................................................................. 2-27
条件付きコンパイル .................................................................................................................................................. 2-29
条件付きコンパイルの動作方法 ......................................................................................................................
条件付きコンパイルの制御トークン ......................................................................................................
条件付きコンパイルの選択ディレクティブの使用 ..............................................................................
条件付きコンパイルのエラー・ディレクティブの使用 ......................................................................
条件付きコンパイルの問合せディレクティブの使用 ..........................................................................
条件付きコンパイルでの事前定義問合せディレクティブの使用 ......................................................
条件付きコンパイルでの静的な式の使用 ..............................................................................................
PLSQL_CCFLAGS 初期化パラメータの設定 ........................................................................................
DBMS_DB_VERSION パッケージ定数の使用 ......................................................................................
2-29
2-30
2-30
2-30
2-30
2-31
2-31
2-33
2-33
条件付きコンパイルの例 .................................................................................................................................. 2-34
条件付きコンパイルを使用してデータベースのバージョンのコードを指定する方法 .................. 2-34
DBMS_PREPROCESSOR プロシージャを使用してソース・テキストの印刷または
取出しを行う方法 .............................................................................................................................. 2-35
条件付きコンパイルの制限 .............................................................................................................................. 2-35
PL/SQL を使用して Web アプリケーションおよび Server Pages を作成する方法 ....................................... 2-36
PL/SQL Web アプリケーション ..................................................................................................................... 2-36
PL/SQL Server Pages ....................................................................................................................................... 2-37
PL/SQL の組込みファンクションのまとめ .......................................................................................................... 2-37
3
PL/SQL のデータ型
事前定義された PL/SQL データ型の概要 ............................................................................................................... 3-2
PL/SQL の数値型 ................................................................................................................................................ 3-2
BINARY_INTEGER データ型 ................................................................................................................... 3-2
BINARY_FLOAT および BINARY_DOUBLE データ型 ........................................................................ 3-3
iii
NUMBER データ型 ..................................................................................................................................... 3-3
PLS_INTEGER データ型 ............................................................................................................................ 3-4
PL/SQL の文字型と文字列型 ............................................................................................................................
CHAR データ型 ..........................................................................................................................................
LONG および LONG RAW データ型 ......................................................................................................
RAW データ型 .............................................................................................................................................
ROWID および UROWID データ型 .........................................................................................................
VARCHAR2 データ型 ................................................................................................................................
3-5
3-5
3-6
3-6
3-7
3-8
PL/SQL の各国語キャラクタ・タイプ ............................................................................................................
UTF8 および AL16UTF16 エンコーディング ..........................................................................................
NCHAR データ型 ........................................................................................................................................
NVARCHAR2 データ型 ...........................................................................................................................
3-9
3-9
3-9
3-10
PL/SQL LOB 型 .................................................................................................................................................
BFILE データ型 ..........................................................................................................................................
BLOB データ型 ...........................................................................................................................................
CLOB データ型 ..........................................................................................................................................
NCLOB データ型 .......................................................................................................................................
3-10
3-11
3-11
3-11
3-12
PL/SQL のブール型 .......................................................................................................................................... 3-12
BOOLEAN データ型 ................................................................................................................................. 3-12
PL/SQL の日付型、時刻型および時間隔型 ..................................................................................................
DATE データ型 ..........................................................................................................................................
TIMESTAMP データ型 .............................................................................................................................
TIMESTAMP WITH TIME ZONE データ型 .........................................................................................
TIMESTAMP WITH LOCAL TIME ZONE データ型 ..........................................................................
INTERVAL YEAR TO MONTH データ型 .............................................................................................
INTERVAL DAY TO SECOND データ型 ..............................................................................................
3-12
3-13
3-13
3-14
3-15
3-15
3-16
日時および時間隔の演算 .................................................................................................................................. 3-16
日付および時刻のサブタイプを使用する場合の切捨て問題の回避 .......................................................... 3-17
PL/SQL サブタイプの概要 ....................................................................................................................................... 3-17
サブタイプの定義 .............................................................................................................................................. 3-17
サブタイプの使用 ..............................................................................................................................................
サブタイプのデータ型の互換性 ..............................................................................................................
サブタイプの制約およびデフォルト値 ..................................................................................................
PL/SQL データ型の変換 ...........................................................................................................................................
3-18
3-18
3-19
3-20
明示的な変換 ...................................................................................................................................................... 3-20
暗黙的な変換 ...................................................................................................................................................... 3-20
暗黙的変換と明示的変換の選択 ...................................................................................................................... 3-22
DATE の値 .......................................................................................................................................................... 3-22
RAW および LONG RAW の値 ....................................................................................................................... 3-22
CHAR と VARCHAR2 のデータ型の違い ............................................................................................................ 3-22
文字値の代入 ...................................................................................................................................................... 3-22
文字値の比較 ...................................................................................................................................................... 3-23
文字値の挿入 ...................................................................................................................................................... 3-24
文字値の選択 ...................................................................................................................................................... 3-25
4
PL/SQL の制御構造の使用
PL/SQL の制御構造の概要 ......................................................................................................................................... 4-2
条件テスト : IF 文および CASE 文 ........................................................................................................................... 4-2
IF-THEN 文の使用 ............................................................................................................................................... 4-2
iv
IF-THEN-ELSE 文の使用 .................................................................................................................................... 4-3
IF-THEN-ELSEIF 文の使用 ................................................................................................................................ 4-3
CASE 文の使用 .................................................................................................................................................... 4-4
検索 CASE 文 ............................................................................................................................................... 4-5
PL/SQL 条件文のガイドライン ........................................................................................................................ 4-6
ループの反復の制御 : LOOP 文と EXIT 文 ............................................................................................................. 4-7
LOOP 文の使用 .................................................................................................................................................... 4-7
EXIT 文の使用 ...................................................................................................................................................... 4-7
EXIT-WHEN 文の使用 ....................................................................................................................................... 4-8
PL/SQL ループのラベル付け ............................................................................................................................ 4-8
WHILE-LOOP 文の使用 ..................................................................................................................................... 4-9
FOR-LOOP 文の使用 ..........................................................................................................................................
PL/SQL ループの反復方法 ......................................................................................................................
ループの動的な範囲 ..................................................................................................................................
ループ・カウンタ変数の有効範囲 ..........................................................................................................
FOR ループでの EXIT 文の使用 ..............................................................................................................
順次制御 : GOTO 文と NULL 文 ............................................................................................................................
4-9
4-10
4-11
4-11
4-12
4-13
GOTO 文の使用 ................................................................................................................................................. 4-13
GOTO 文の制限 ......................................................................................................................................... 4-14
NULL 文の使用 ................................................................................................................................................. 4-15
5
PL/SQL のコレクションおよびレコードの使用
PL/SQL のコレクションおよびレコード ................................................................................................................ 5-2
PL/SQL のコレクション ....................................................................................................................................
ネストした表 ................................................................................................................................................
VARRAY .......................................................................................................................................................
結合配列(索引付き表)..............................................................................................................................
グローバリゼーション設定が結合配列の VARCHAR2 キーに与える影響 .......................................
5-2
5-2
5-3
5-3
5-4
PL/SQL レコード ................................................................................................................................................ 5-5
使用する PL/SQL コレクション型の選択 ............................................................................................................... 5-5
ネストした表と結合配列の選択 ........................................................................................................................ 5-5
ネストした表と VARRAY との使い分け ......................................................................................................... 5-5
コレクション型の定義とコレクション変数の宣言 ................................................................................................ 5-6
PL/SQL のコレクション変数の宣言 ................................................................................................................ 5-7
コレクションの初期化および参照 ............................................................................................................................ 5-9
コレクション要素の参照 ..................................................................................................................................
コレクションの代入 ..................................................................................................................................................
コレクションの比較 ..................................................................................................................................................
マルチレベル・コレクションの使用 ......................................................................................................................
コレクション・メソッドの使用 ..............................................................................................................................
5-11
5-12
5-15
5-17
5-18
コレクション要素の存在のチェック(EXISTS メソッド).......................................................................... 5-19
コレクション内の要素数のカウント(COUNT メソッド)........................................................................ 5-19
コレクションの最大サイズのチェック(LIMIT メソッド)....................................................................... 5-20
最初または最後のコレクション要素の検索(FIRST メソッドと LAST メソッド)................................ 5-20
コレクションの各要素のループ(PRIOR メソッドと NEXT メソッド)................................................. 5-21
コレクションのサイズの拡大(EXTEND メソッド).................................................................................. 5-22
コレクションのサイズの縮小(TRIM メソッド)........................................................................................ 5-23
コレクション要素の削除(DELETE メソッド)........................................................................................... 5-24
v
コレクション・パラメータへのメソッドの適用 .......................................................................................... 5-25
コレクション例外の回避 .......................................................................................................................................... 5-26
レコードの定義と宣言 .............................................................................................................................................. 5-28
プロシージャのパラメータおよびファンクションの戻り値としてのレコードの使用 .......................... 5-30
レコードへの値の代入 .............................................................................................................................................. 5-31
レコードの比較 .................................................................................................................................................. 5-32
PL/SQL レコードのデータベースへの挿入 .................................................................................................. 5-32
PL/SQL レコード値を使用したデータベースの更新 .................................................................................. 5-33
レコードの挿入 / 更新に関する制約 .............................................................................................................. 5-34
レコードのコレクションへのデータの問合せ .............................................................................................. 5-34
6
PL/SQL での SQL 操作の実行
PL/SQL における SQL サポートの概要 ................................................................................................................... 6-2
データ操作 ............................................................................................................................................................ 6-2
トランザクション制御 ........................................................................................................................................ 6-3
SQL ファンクション ........................................................................................................................................... 6-3
SQL 疑似列 ........................................................................................................................................................... 6-4
SQL 演算子 ........................................................................................................................................................... 6-5
PL/SQL でのカーソルの管理 ..................................................................................................................................... 6-6
暗黙カーソル ........................................................................................................................................................ 6-6
暗黙カーソルの属性 .................................................................................................................................... 6-6
暗黙カーソルの属性を使用する場合のガイドライン ............................................................................ 6-8
明示カーソル ........................................................................................................................................................
カーソルの宣言 ............................................................................................................................................
カーソルのオープン ....................................................................................................................................
カーソルを使用したフェッチ ....................................................................................................................
カーソルを使用したバルク・データのフェッチ ..................................................................................
カーソルのクローズ ..................................................................................................................................
明示カーソルの属性 ..................................................................................................................................
PL/SQL を使用したデータの問合せ .......................................................................................................................
6-8
6-8
6-9
6-9
6-11
6-11
6-11
6-14
1 行のみの選択 : SELECT INTO 文 ................................................................................................................. 6-14
複数行の選択 : BULK COLLECT 句 ................................................................................................................ 6-14
複数行のループ : カーソル FOR ループ ......................................................................................................... 6-15
複雑な問合せの処理の実行 : 明示カーソル ................................................................................................... 6-15
PL/SQL を使用したデータの問合せ : 暗黙カーソルの FOR ループ ......................................................... 6-15
PL/SQL を使用したデータの問合せ : 明示カーソルの FOR ループ ......................................................... 6-16
カーソル FOR ループ内の式の別名の定義 .................................................................................................... 6-16
副問合せの使用 .......................................................................................................................................................... 6-16
相関副問合せの使用 .......................................................................................................................................... 6-17
メンテナンス可能な PL/SQL 問合せの作成 ................................................................................................. 6-18
カーソル変数(REF CURSOR)の使用
)の使用 ................................................................................................................ 6-19
カーソル変数(
カーソル変数(REF CURSOR)....................................................................................................................... 6-19
変数を使用する理由 .......................................................................................................................................... 6-19
REF CURSOR 型およびカーソル変数の宣言 ................................................................................................ 6-20
パラメータとしてのカーソル変数の引渡し .......................................................................................... 6-21
カーソル変数の制御 : OPEN-FOR、FETCH および CLOSE ...................................................................... 6-21
カーソル変数のオープン .......................................................................................................................... 6-21
ホスト変数としてのカーソル変数の使用 .............................................................................................. 6-23
vi
カーソル変数からのフェッチ .................................................................................................................. 6-24
カーソル変数のクローズ .......................................................................................................................... 6-25
ホスト・カーソル変数を PL/SQL に渡すときのネットワークの通信量の削減 ..................................... 6-25
カーソル変数でのエラーの回避 ...................................................................................................................... 6-26
カーソル変数の制限 .......................................................................................................................................... 6-26
カーソル式の使用 ...................................................................................................................................................... 6-27
カーソル式の制限 .............................................................................................................................................. 6-27
カーソル式の例 .................................................................................................................................................. 6-28
カーソル副問合せを使用した REF CURSOR の構成 ................................................................................... 6-28
PL/SQL におけるトランザクション処理の概要 .................................................................................................. 6-28
PL/SQL での COMMIT の使用 ...................................................................................................................... 6-29
PL/SQL での ROLLBACK の使用 .................................................................................................................. 6-29
PL/SQL での SAVEPOINT の使用 ................................................................................................................. 6-30
Oracle による暗黙的なロールバックの実行方法 ......................................................................................... 6-31
トランザクションの終了 .................................................................................................................................. 6-32
SET TRANSACTION を使用したトランザクション・プロパティの設定 ............................................... 6-32
SET TRANSACTION の制限 ................................................................................................................... 6-32
デフォルトのロックの上書き .......................................................................................................................... 6-33
自律型トランザクションによる独立した作業単位の実行 .................................................................................. 6-35
自律型トランザクションのメリット .............................................................................................................. 6-36
自律型トランザクションの定義 ......................................................................................................................
自律型トランザクションとネストしたトランザクションの比較 ......................................................
トランザクション・コンテキスト ..........................................................................................................
トランザクションの可視性 ......................................................................................................................
6-36
6-37
6-38
6-38
自律型トランザクションの制御 ...................................................................................................................... 6-38
自律型トリガーの使用 ...................................................................................................................................... 6-39
SQL からの自律型ファンクションのコール ................................................................................................. 6-40
7
システム固有の動的 SQL を使用した SQL 操作の実行
PL/SQL で動的 SQL を使用する場合 ...................................................................................................................... 7-2
PL/SQL での EXECUTE IMMEDIATE 文の使用 .................................................................................................. 7-2
動的 SQL 文字列におけるバインド変数のパラメータ・モードの指定 ...................................................... 7-4
PL/SQL でのバルク動的 SQL の使用 ...................................................................................................................... 7-5
動的 SQL とバルク SQL の使用 ........................................................................................................................ 7-5
バルク動的バインドの例 .................................................................................................................................... 7-6
PL/SQL での動的 SQL 使用のガイドライン .......................................................................................................... 7-7
動的 SQL を使用した動的問合せの構築 .......................................................................................................... 7-7
動的 SQL でのセミコロンの使用または省略 .................................................................................................. 7-7
バインド変数を使用した動的 SQL のパフォーマンスの向上 ...................................................................... 7-8
パラメータとしてのスキーマ・オブジェクト名の引渡し ............................................................................ 7-8
動的 SQL での重複するプレースホルダの使用 .............................................................................................. 7-9
動的 SQL でのカーソル属性の使用 .................................................................................................................. 7-9
動的 SQL への NULL の引渡し ....................................................................................................................... 7-10
動的 SQL でのデータベース・リンクの使用 ................................................................................................ 7-10
動的 SQL での実行者権限の使用 .................................................................................................................... 7-11
動的 SQL での RESTRICT_REFERENCES プラグマの使用 ....................................................................... 7-11
動的 SQL でのデッドロックの回避 ................................................................................................................ 7-11
vii
USING 句の下位互換性 .................................................................................................................................... 7-11
PL/SQL のレコードおよびコレクションでの動的 SQL の使用 ................................................................ 7-12
8
PL/SQL のサブプログラムの使用
サブプログラム ............................................................................................................................................................
PL/SQL サブプログラムのメリット .........................................................................................................................
PL/SQL プロシージャ .................................................................................................................................................
PL/SQL ファンクション .............................................................................................................................................
8-2
8-3
8-3
8-4
RETURN 文の使用 .............................................................................................................................................. 8-5
ネストした PL/SQL サブプログラムの宣言 ............................................................................................................ 8-5
PL/SQL サブプログラムへのパラメータの引渡し ................................................................................................. 8-6
サブプログラムの実パラメータと仮パラメータ ............................................................................................ 8-6
サブプログラムのパラメータの位置表記法、名前表記法または混合表記法 ............................................ 8-7
サブプログラムのパラメータのモードの指定 ................................................................................................
IN モードの使用 ..........................................................................................................................................
OUT モードの使用 ......................................................................................................................................
IN OUT モードの使用 .................................................................................................................................
サブプログラムのパラメータのモードの概要 ........................................................................................
8-8
8-8
8-8
8-9
8-9
サブプログラムのパラメータのデフォルト値の使用 .................................................................................... 8-9
サブプログラム名のオーバーロード ...................................................................................................................... 8-10
数値型のオーバーロードのガイドライン ...................................................................................................... 8-10
オーバーロードの制限 ...................................................................................................................................... 8-11
サブプログラムのコールの解決方法 ...................................................................................................................... 8-12
オーバーロードと継承の相互作用 .................................................................................................................. 8-14
実行者権限と定義者権限の使用(AUTHID
実行者権限と定義者権限の使用(
句).................................................................................................. 8-15
実行者権限のメリット ...................................................................................................................................... 8-16
AUTHID 句によるサブプログラムの権限の指定 ......................................................................................... 8-16
サブプログラム実行中の現行ユーザー .......................................................................................................... 8-16
実行者権限サブプログラムでの外部参照の解決 .......................................................................................... 8-17
実行者権限サブプログラムでのテンプレート・オブジェクトの必要性 .......................................... 8-17
実行者権限サブプログラムでのデフォルトの名前解決のオーバーライド .............................................. 8-17
実行者権限サブプログラムに対する権限の付与 .......................................................................................... 8-18
実行者権限サブプログラムに対する権限の付与 : 例 ........................................................................... 8-18
実行者権限サブプログラムでのロールの使用 .............................................................................................. 8-19
実行者権限サブプログラムでのビューおよびデータベース・トリガーの使用 ...................................... 8-19
実行者権限サブプログラムでのデータベース・リンクの使用 .................................................................. 8-19
実行者権限サブプログラムでのオブジェクト型の使用 .............................................................................. 8-19
実行者権限のインスタンス・メソッドのコール .................................................................................. 8-20
PL/SQL での再帰の使用 ........................................................................................................................................... 8-21
再帰的サブプログラム ......................................................................................................................................
外部サブプログラムのコール ..................................................................................................................................
PL/SQL サブプログラムの副作用の制御 ...............................................................................................................
サブプログラムのパラメータのエイリアシングの理解 ......................................................................................
9
8-21
8-21
8-23
8-23
PL/SQL パッケージの使用
PL/SQL パッケージ ..................................................................................................................................................... 9-2
PL/SQL パッケージの内容 ................................................................................................................................ 9-2
PL/SQL パッケージのメリット ................................................................................................................................. 9-3
viii
パッケージ仕様部の理解 ............................................................................................................................................ 9-4
パッケージの内容の参照 ....................................................................................................................................
制限 ................................................................................................................................................................
パッケージ本体の理解 ................................................................................................................................................
パッケージ機能の例 ....................................................................................................................................................
9-5
9-5
9-5
9-6
パッケージのプライベート項目とパブリック項目 ........................................................................................ 9-8
パッケージ STANDARD による PL/SQL 環境の定義 .......................................................................................... 9-8
製品固有のパッケージの概要 .................................................................................................................................... 9-9
DBMS_ALERT パッケージ ................................................................................................................................ 9-9
DBMS_OUTPUT パッケージ ............................................................................................................................. 9-9
DBMS_PIPE パッケージ ................................................................................................................................... 9-10
HTF パッケージおよび HTP パッケージ ...................................................................................................... 9-10
UTL_FILE パッケージ ...................................................................................................................................... 9-10
UTL_HTTP パッケージ .................................................................................................................................... 9-10
UTL_SMTP パッケージ .................................................................................................................................... 9-10
パッケージ作成のガイドライン .............................................................................................................................. 9-10
パッケージでのカーソル仕様部と本体の分離 ...................................................................................................... 9-11
10
PL/SQL エラーの処理
PL/SQL のランタイム・エラー処理の概要 .......................................................................................................... 10-2
PL/SQL エラーと例外の回避および処理のガイドライン ..........................................................................
PL/SQL 例外のメリット ..........................................................................................................................................
事前定義の PL/SQL 例外のまとめ .........................................................................................................................
独自の PL/SQL 例外の定義 .....................................................................................................................................
10-3
10-3
10-4
10-6
PL/SQL 例外の宣言 .......................................................................................................................................... 10-6
PL/SQL 例外の有効範囲規則 .......................................................................................................................... 10-6
PL/SQL 例外と番号の関連付け : EXCEPTION_INIT プラグマ ................................................................ 10-7
独自のエラー・メッセージの定義 : RAISE_APPLICATION_ERROR プロシージャ ............................ 10-7
事前定義の例外の再宣言 .................................................................................................................................. 10-8
PL/SQL 例外の呼出し .............................................................................................................................................. 10-9
RAISE 文を使用した例外の呼出し .................................................................................................................
PL/SQL 例外の伝播 ..................................................................................................................................................
PL/SQL 例外の再呼出し ........................................................................................................................................
呼び出された PL/SQL 例外の処理 .......................................................................................................................
10-9
10-9
10-11
10-12
宣言の中で呼び出された例外 ........................................................................................................................ 10-13
ハンドラの中で呼び出された例外の処理 .................................................................................................... 10-13
例外ハンドラへの分岐と例外ハンドラからの分岐 .................................................................................... 10-13
エラー・コードとエラー・メッセージの取得 : SQLCODE および SQLERRM .................................... 10-13
未処理例外の捕捉 ............................................................................................................................................ 10-14
PL/SQL エラーの処理のヒント ....................................................................................................................
例外が呼び出された後に実行を続ける方法 ........................................................................................
トランザクションの再試行 ....................................................................................................................
ロケータ変数を使用した例外の位置の識別 ........................................................................................
PL/SQL のコンパイル時の警告の概要 ................................................................................................................
10-15
10-15
10-16
10-16
10-17
PL/SQL の警告カテゴリ ................................................................................................................................ 10-17
PL/SQL 警告メッセージの制御 .................................................................................................................... 10-17
DBMS_WARNING パッケージの使用 ........................................................................................................ 10-18
ix
11
PL/SQL アプリケーションのパフォーマンスのチューニング
PL/SQL コンパイル用の初期化パラメータ ........................................................................................................... 11-2
PL/SQL でプログラムを最適化する方法 ............................................................................................................... 11-2
PL/SQL コードをチューニングする場合 ...................................................................................................... 11-2
PL/SQL のパフォーマンス問題を回避するためのガイドライン ....................................................................... 11-3
PL/SQL コードでの CPU オーバーヘッドの回避 ........................................................................................
SQL 文の最大限の効率化 .........................................................................................................................
ファンクション・コールの最大限の効率化 ..........................................................................................
ループの最大限の効率化 ..........................................................................................................................
組込み文字列ファンクションの使用 ......................................................................................................
条件テストにおける最低コストの条件の先頭への配置 ......................................................................
データ型変換の回数の最少化 ..................................................................................................................
整数の算術計算での PLS_INTEGER の使用 .........................................................................................
浮動小数点の算術計算での BINARY_FLOAT および BINARY_DOUBLE の使用 .........................
11-3
11-3
11-4
11-4
11-5
11-5
11-5
11-6
11-6
PL/SQL コードでのメモリー・オーバーヘッドの回避 ..............................................................................
VARCHAR2 変数宣言時の大きいサイズの指定 ..................................................................................
関連するサブプログラムのパッケージへのグループ化 ......................................................................
共有メモリー・プールでのパッケージの確保 ......................................................................................
コンパイラの警告を回避するためのコードの改善 ..............................................................................
PL/SQL プログラムのプロファイルおよびトレース ...........................................................................................
11-6
11-6
11-6
11-6
11-7
11-7
プロファイラ API の使用 : DBMS_PROFILER パッケージ ........................................................................ 11-7
トレース API の使用 : DBMS_TRACE パッケージ ...................................................................................... 11-7
トレースの制御 .......................................................................................................................................... 11-8
バルク SQL による、DML
による、
文および問合せのループ・オーバーヘッドの削減 ............................................. 11-8
FORALL 文の使用 ............................................................................................................................................. 11-8
FORALL がロールバックに与える影響 ............................................................................................... 11-11
%BULK_ROWCOUNT 属性を持つ FORALL による影響を受ける行カウント ............................ 11-12
%BULK_EXCEPTIONS 属性を持つ FORALL 例外の処理 ................................................................ 11-13
BULK COLLECT 句を使用した、問合せ結果のコレクションへの取出し ............................................
カーソルからのバルク・フェッチの例 ................................................................................................
LIMIT 句を使用したバルク・フェッチ操作の対象行の制限 ............................................................
RETURNING INTO 句を使用したコレクションへの DML 結果の取出し ....................................
FORALL と BULK COLLECT の併用 ...................................................................................................
バルク・バインドとホスト配列の併用 ................................................................................................
PL/SQL での計算集中型プログラムの記述 .........................................................................................................
EXECUTE IMMEDIATE およびカーソル変数を使用した動的 SQL のチューニング ................................
NOCOPY コンパイラ・ヒントを使用した PL/SQL プロシージャ・コールのチューニング .....................
11-15
11-16
11-17
11-18
11-18
11-19
11-19
11-20
11-20
NOCOPY の制限 .............................................................................................................................................. 11-21
システム固有の実行のための PL/SQL コードのコンパイル ............................................................................ 11-22
はじめに ............................................................................................................................................................ 11-22
PL/SQL のネイティブ・コンパイルを使用するかどうかの判断 ............................................................ 11-22
PL/SQL のネイティブ・コンパイルの動作 ................................................................................................
依存性、無効化および再評価 ................................................................................................................
Real Application Clusters および PL/SQL のネイティブ・コンパイル .........................................
ネイティブ・コンパイルの制限 ............................................................................................................
11-23
11-23
11-24
11-24
spnc_commands ファイル ............................................................................................................................. 11-24
PL/SQL ネイティブ・コンパイルの初期化パラメータの設定 ................................................................ 11-25
PLSQL_NATIVE_LIBRARY_DIR 初期化パラメータ ........................................................................ 11-25
PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT 初期化パラメータ ................................................ 11-25
x
PLSQL_CODE_TYPE 初期化パラメータ ............................................................................................. 11-25
PL/SQL のシステム固有のライブラリ用のサブディレクトリの設定 .................................................... 11-26
PL/SQL ネイティブ・コンパイルの設定方法およびテスト方法 ............................................................ 11-27
PL/SQL のネイティブ・コンパイルで使用する新しいデータベースの設定 ........................................ 11-28
PL/SQL ネイティブ・コンパイルまたは解釈コンパイルで使用するデータベース全体の変更 ........ 11-28
パイプライン・ファンクションによる変換の設定 ............................................................................................ 11-31
パイプライン・テーブル・ファンクションの概要 .................................................................................... 11-31
パイプライン・テーブル・ファンクションの記述 .................................................................................... 11-32
変換へのパイプライン・テーブル・ファンクションの使用 .................................................................... 11-32
パイプライン・テーブル・ファンクションからの結果の戻し ................................................................ 11-33
PL/SQL テーブル・ファンクション間のデータのパイプライン ............................................................ 11-34
パイプライン・テーブル・ファンクションに対する複数コールの最適化 ............................................ 11-34
パイプライン・テーブル・ファンクションの結果からのフェッチ ........................................................ 11-34
カーソル変数によるデータの引渡し ............................................................................................................ 11-35
パイプライン・テーブル・ファンクション内での DML 操作の実行 .................................................... 11-37
パイプライン・テーブル・ファンクションへの DML 操作の実行 ........................................................ 11-37
パイプライン・テーブル・ファンクションの例外処理 ............................................................................ 11-38
12
PL/SQL のオブジェクト型の使用
PL/SQL でのオブジェクトの宣言と初期化 .......................................................................................................... 12-2
PL/SQL ブロックでのオブジェクトの宣言 .................................................................................................. 12-3
PL/SQL による未初期化オブジェクトの処理 .............................................................................................. 12-3
PL/SQL を使用したオブジェクトの操作 .............................................................................................................. 12-4
ドット表記法を使用したオブジェクト属性へのアクセス .......................................................................... 12-4
オブジェクトコンストラクタおよびメソッドのコール .............................................................................. 12-5
オブジェクトの更新および削除 ...................................................................................................................... 12-6
Ref 修飾子を使用したオブジェクトの操作 ................................................................................................... 12-6
PL/SQL コレクション型に相当する SQL の型の定義 ........................................................................................ 12-7
SQL での個々のコレクション要素の操作 ..................................................................................................... 12-8
SQL のオブジェクト型での PL/SQL コレクションの使用 ................................................................................ 12-9
オブジェクトでの動的 SQL の使用 ..................................................................................................................... 12-11
13
PL/SQL の言語要素
代入文 ..........................................................................................................................................................................
AUTONOMOUS_TRANSACTION プラグマ ....................................................................................................
ブロック宣言 ..............................................................................................................................................................
CASE 文 ....................................................................................................................................................................
CLOSE 文 .................................................................................................................................................................
コレクション定義 ....................................................................................................................................................
コレクション・メソッド ........................................................................................................................................
コメント ....................................................................................................................................................................
COMMIT 文 ............................................................................................................................................................
定数と変数の宣言 ....................................................................................................................................................
カーソル属性 ............................................................................................................................................................
カーソル変数 ............................................................................................................................................................
カーソル宣言 ............................................................................................................................................................
DELETE 文 ...............................................................................................................................................................
13-3
13-6
13-8
13-13
13-15
13-16
13-19
13-22
13-23
13-24
13-27
13-29
13-32
13-35
xi
EXCEPTION_INIT プラグマ ................................................................................................................................ 13-37
例外定義 .................................................................................................................................................................... 13-38
EXECUTE IMMEDIATE 文 ................................................................................................................................... 13-40
EXIT 文 ...................................................................................................................................................................... 13-43
式定義 ........................................................................................................................................................................ 13-44
FETCH 文 .................................................................................................................................................................. 13-52
FORALL 文 ............................................................................................................................................................... 13-55
ファンクション宣言 ................................................................................................................................................ 13-58
GOTO 文 .................................................................................................................................................................. 13-62
IF 文 ........................................................................................................................................................................... 13-63
INSERT 文 ................................................................................................................................................................ 13-65
リテラル宣言 ............................................................................................................................................................ 13-67
LOCK TABLE 文 ..................................................................................................................................................... 13-70
LOOP 文 .................................................................................................................................................................... 13-71
MERGE 文 ................................................................................................................................................................ 13-75
NULL 文 .................................................................................................................................................................... 13-76
オブジェクト型宣言 ................................................................................................................................................ 13-77
OPEN 文 .................................................................................................................................................................... 13-79
OPEN-FOR 文 .......................................................................................................................................................... 13-81
パッケージ宣言 ........................................................................................................................................................ 13-84
プロシージャ宣言 .................................................................................................................................................... 13-89
RAISE 文 ................................................................................................................................................................... 13-92
レコード定義 ............................................................................................................................................................ 13-93
RESTRICT_REFERENCES プラグマ .................................................................................................................. 13-96
RETURN 文 .............................................................................................................................................................. 13-98
RETURNING INTO 句 .......................................................................................................................................... 13-99
ROLLBACK 文 ..................................................................................................................................................... 13-101
%ROWTYPE 属性 ................................................................................................................................................ 13-102
SAVEPOINT 文 .................................................................................................................................................... 13-104
SELECT INTO 文 ................................................................................................................................................. 13-105
SERIALLY_REUSABLE プラグマ ..................................................................................................................... 13-109
SET TRANSACTION 文 .................................................................................................................................... 13-111
SQL カーソル ........................................................................................................................................................ 13-113
SQLCODE ファンクション ................................................................................................................................ 13-115
SQLERRM ファンクション ................................................................................................................................ 13-116
%TYPE 属性 .......................................................................................................................................................... 13-117
UPDATE 文 ........................................................................................................................................................... 13-119
A
PL/SQL のソース・コードの不明瞭化
不明瞭化 ........................................................................................................................................................................ A-2
PL/SQL ユニットの不明瞭化のヒント ............................................................................................................ A-2
不明瞭化の制限 ....................................................................................................................................................
wrap ユーティリティの制限 ......................................................................................................................
DBMS_DDL の wrap ファンクションの制限 ..........................................................................................
wrap ユーティリティを使用した PL/SQL コードの不明瞭化 .............................................................................
A-2
A-3
A-3
A-3
PL/SQL の wrap ユーティリティの入力ファイルと出力ファイル ............................................................. A-3
wrap ユーティリティの実行 .............................................................................................................................. A-4
DBMS_DDL サブプログラムを使用した PL/SQL コードの不明瞭化 ............................................................... A-5
DBMS_DDL の create_wrapped プロシージャの使用 .................................................................................. A-5
xii
B
PL/SQL での識別子名の解決
名前解決 ........................................................................................................................................................................ B-2
修飾名およびドット表記法の例 ................................................................................................................................ B-2
ドット表記法を使用して名前を指定する方法の追加例 ................................................................................ B-3
PL/SQL と SQL の名前解決の相違点 ...................................................................................................................... B-4
取得の理解 .................................................................................................................................................................... B-4
内部取得 ................................................................................................................................................................ B-4
同一有効範囲の取得 ............................................................................................................................................ B-5
外部取得 ................................................................................................................................................................ B-5
DML 文の内部取得の回避 ......................................................................................................................................... B-6
オブジェクト属性およびメソッドへの参照の修飾 ................................................................................................ B-6
属性およびメソッドへの参照 ............................................................................................................................ B-6
行の式への参照 .................................................................................................................................................... B-7
C
PL/SQL のプログラム上の制限
D
PL/SQL の予約語およびキーワード
索引
xiii
xiv
はじめに
このマニュアルでは、PL/SQL 言語の概念を説明し、PL/SQL 言語の様々な機能を使用する方
法を、例を示して説明します。
ここでは、次の項目について説明します。
■
対象読者
■
ドキュメントのアクセシビリティについて
■
このマニュアルの構成
■
PL/SQL のサンプル・プログラム
■
関連ドキュメント
■
表記規則
■
サポートおよびサービス
xv
対象読者
オラクル社の PL/SQL は、SQL を手続き型言語として機能拡張した、上級の第 4 世代プログラ
ミング言語です。PL/SQL は、データのカプセル化、オーバーロード、コレクション型、例外
処理、情報隠ぺいなどのソフトウェア・エンジニアリング機能を提供します。また PL/SQL
は、SQL および Oracle データベースと緊密に統合され、短期間でのプロトタイプ作成およびプ
ログラム開発をサポートします。
このマニュアルは、Oracle の PL/SQL ベースのアプリケーション開発者を対象としています。
また、プログラマ、システム・アナリスト、プロジェクト・マネージャ、データベース管理者
およびデータベース操作を自動化する必要があるユーザーも対象にしています。他の言語でア
プリケーションを開発する開発者も、一部を PL/SQL で記述した混合言語アプリケーションを
開発できます。
このマニュアルを効果的に使用するには、Oracle データベース、SQL 言語、および IF-THEN
比較、ループ、プロシージャ、ファンクションなどの基本的なプログラム構造体の実用的な知
識が必要です。
ドキュメントのアクセシビリティについて
オラクル社は、障害のあるお客様にもオラクル社の製品、サービスおよびサポート・ドキュメ
ントを簡単にご利用いただけることを目標としています。オラクル社のドキュメントには、
ユーザーが障害支援技術を使用して情報を利用できる機能が組み込まれています。HTML 形式
のドキュメントで用意されており、障害のあるお客様が簡単にアクセスできるようにマーク
アップされています。標準規格は改善されつつあります。オラクル社はドキュメントをすべて
のお客様がご利用できるように、市場をリードする他の技術ベンダーと積極的に連携して技術
的な問題に対応しています。オラクル社のアクセシビリティについての詳細情報は、Oracle
Accessibility Program の Web サイト http://www.oracle.com/accessibility/ を参照してくださ
い。
ドキュメント内のサンプル・コードのアクセシビリティについて
JAWS(Windows のスクリーン・リーダー)は、ドキュメント内のサンプル・コードを正確に
読めない場合があります。コード表記規則では閉じ括弧だけを行に記述する必要があります。
しかし JAWS は括弧だけの行を読まない場合があります。
外部 Web サイトのドキュメントのアクセシビリティについて
このドキュメントにはオラクル社およびその関連会社が所有または管理しない Web サイトへの
リンクが含まれている場合があります。オラクル社およびその関連会社は、それらの Web サイ
トのアクセシビリティに関しての評価や言及は行っておりません。
このマニュアルの構成
このマニュアルの構成は、次のとおりです。
第 1 章「PL/SQL の概要」
この章では、PL/SQL の主な機能およびメリットについて説明します。PL/SQL の基本概念を
説明し、代表的な PL/SQL プログラムの形式を示します。
第 2 章「PL/SQL 言語の基礎」
この章では、PL/SQL の詳細(字句単位、スカラー・データ型、ユーザー定義のサブタイプ、
データ変換、式、代入、ブロック構造、宣言および有効範囲)について説明します。
第 3 章「PL/SQL のデータ型」
この章では、整数、浮動小数点、文字、ブール、日付、コレクション、参照、LOB など、
PL/SQL の事前定義のデータ型について説明します。また、ユーザー定義のサブタイプおよび
データ変換についても説明します。
xvi
第 4 章「PL/SQL の制御構造の使用」
この章では、PL/SQL プログラムの実行フローを制御する方法を示します。IF-THEN-ELSE、
CASE、WHILE-LOOP などの制御構造を使用した条件制御、反復制御および順次制御について説
明します。
第 5 章「PL/SQL のコレクションおよびレコードの使用」
この章では、コンポジット・データ型である TABLE、VARRAY および RECORD について説明し
ます。データのコレクション全体および様々な型のグループ・データを参照および操作する方
法を説明します。
第 6 章「PL/SQL での SQL 操作の実行」
この章では、Oracle データを操作する SQL コマンド、ファンクションおよび演算子が PL/SQL
でどのようにサポートされているのかを示します。また、問合せおよびトランザクションを処
理する方法も示します。
第 7 章「システム固有の動的 SQL を使用した SQL 操作の実行」
この章では、実行時に SQL 文および SQL 問合せを構築する方法を示します。
第 8 章「PL/SQL のサブプログラムの使用」
この章では、プロシージャまたはファンクションを記述およびコールする方法を示します。パ
ラメータ、オーバーロード、サブプログラムの様々な権限モデルなどの関連トピックについて
説明します。
第 9 章「PL/SQL パッケージの使用」
この章では、関連する PL/SQL の型、項目およびサブプログラムを 1 つのパッケージにまとめ
る方法を示します。パッケージでは、多くのアプリケーションで再利用できる Application
Program Interface(API)が定義されます。
第 10 章「PL/SQL エラーの処理」
この章では、例外およびハンドラを使用して PL/SQL エラーを検出および処理する方法を示し
ます。
第 11 章「PL/SQL アプリケーションのパフォーマンスのチューニング」
この章では、PL/SQL ベースのアプリケーションのパフォーマンスを向上させる方法を示しま
す。
第 12 章「PL/SQL のオブジェクト型の使用」
この章では、PL/SQL を使用してオブジェクトを操作する方法を示します。
第 13 章「PL/SQL の言語要素」
この章では、文の構文、パラメータおよび他の PL/SQL 言語要素を示します。また、使用上の
注意および例へのリンクも示します。
付録 A「PL/SQL のソース・コードの不明瞭化」
この付録では、スタンドアロンの wrap ユーティリティおよび DBMS_DDL パッケージのサブプ
ログラムを使用して、PL/SQL のソース・コードを不明瞭化し、ソース・コードを隠したまま
PL/SQL アプリケーションを配布できるようにする方法を示します。
付録 B「PL/SQL での識別子名の解決」
この付録では、潜在的に意味の曖昧なプロシージャ文および SQL 文で、名前への参照を
PL/SQL がどのように解決するかについて説明します。
付録 C「PL/SQL のプログラム上の制限」
この付録では、PL/SQL によって課されるコンパイル時および実行時の制限について説明しま
す。
付録 D「PL/SQL の予約語およびキーワード」
この付録では、PL/SQL で使用するために予約されている予約語のリストを示します。
xvii
PL/SQL のサンプル・プログラム
PL/SQL のサンプル・プログラムは、Oracle Database Companion CD からインストールできま
す。デモは、ORACLE_HOME/plsql/demo などの PL/SQL のデモ・ディレクトリにあります。
デモ・ディレクトリの場所については、使用しているシステム用の Oracle のインストレーショ
ン・ガイドを参照してください。一般に、これらのサンプルは、表 EMP および表 DEPT を含む
SCOTT スキーマに基づく古いプログラムです。
このマニュアルに掲載されたほとんどの例は、表 EMPLOYEES および表 DEPARTMENTS を含む
HR サンプル・スキーマで実行できる、完全なプログラムとして構成されています。
Oracle Technology Network の Web サイトの PL/SQL セクション
(http://www.oracle.com/technology/tech/pl_sql/)では、多くのサンプル・プログ
ラムをダウンロードできます。これらのプログラムでは、多くの言語機能、特に最新の言語機
能のデモを行います。一部のプログラムを使用して、データベースの複数のリリース間で
PL/SQL のパフォーマンスを比較することもできます。
他の言語から PL/SQL をコールする例については、
『Oracle Database Java 開発者ガイド』およ
び『Pro*C/C++ プログラマーズ・ガイド』を参照してください。
関連ドキュメント
詳細は、次の Oracle ドキュメントを参照してください。
■
■
PL/SQL に関する追加情報は、
http://www.oracle.com/technology/tech/pl_sql/ で Oracle Technology
Network(OTN)を参照してください。
「Best Practice PL/SQL」などの、OTN の特定の項目の情報にアクセスするには、OTN メ
イン・ページ(http://www.oracle.com/technology/)の検索フィールドに適切な
語句を入力してください。
技術的な内容については、OTN
(http://www.oracle.com/technology/pub/articles/index.html)の
「Technical Articles Index」を参照してください。
■
■
■
■
PL/SQL プログラミングの様々な側面、特にトリガーとストアド・プロシージャの詳細は、
『Oracle Database アプリケーション開発者ガイド - 基礎編』を参照してください。
Oracle データベースに付属している PL/SQL パッケージの詳細は、『Oracle Database
PL/SQL パッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
PL/SQL 機能と SQL 機能の両方を使用するオブジェクト指向のプログラミングの詳細は、
『Oracle Database アプリケーション開発者ガイド - オブジェクト・リレーショナル機能』
を参照してください。ラージ・オブジェクト(LOB)を使用したプログラミングについて
は、
『Oracle Database アプリケーション開発者ガイド - ラージ・オブジェクト』を参照し
てください。
SQL については、
『Oracle Database SQL リファレンス』および『Oracle Database 管理者ガ
イド』を参照してください。Oracle の基本概念については、『Oracle Database 概要』を参
照してください。
このマニュアルに示す多くの例で、Oracle Database のインストールで基本インストール・オプ
ションを選択した場合にデフォルトでインストールされるサンプル・スキーマを使用します。
これらのスキーマの作成方法および使用方法については、
『Oracle Database サンプル・スキー
マ』を参照してください。
リリース・ノート、インストール関連ドキュメント、ホワイト・ペーパーまたはその他の関連
ドキュメントは、OTN-J(Oracle Technology Network Japan)から、無償でダウンロードでき
ます。OTN-J を使用するには、オンラインでの登録が必要です。登録は、次の Web サイトから
無償で行えます。
http://otn.oracle.co.jp/membership/
xviii
すでに OTN-J のユーザー名およびパスワードを取得している場合は、次の URL で OTN-J Web
サイトのドキュメントのセクションに直接接続できます。
http://otn.oracle.co.jp/document/
他のマニュアルの詳細は、次の URL を参照してください。
http://www.oracle.com/technology/books/10g_books.html
表記規則
この項では、このマニュアルの本文およびコード例で使用される表記規則について説明します。
この項の内容は次のとおりです。
■
本文の表記規則
■
コード例の表記規則
本文の表記規則
本文では、特定の項目が一目でわかるように、次の表記規則を使用します。次の表に、その規
則と使用例を示します。
規則
意味
例
太字
太字は、本文中で定義されている用語および
用語集に記載されている用語を示します。
この句を指定すると、索引構成表
索引構成表が作成されます。
索引構成表
固定幅フォントの
大文字
固定幅フォントの大文字は、システム指定の
要素を示します。このような要素には、パラ
メータ、権限、データ型、Recovery
Manager キーワード、SQL キーワード、
SQL*Plus またはユーティリティ・コマンド、
パッケージおよびメソッドがあります。ま
た、システム指定の列名、データベース・オ
ブジェクト、データベース構造、ユーザー名
およびロールも含まれます。
NUMBER 列に対してのみ、この句を指定できます。
固定幅フォントの小文字は、実行可能ファイ
ル、ファイル名、ディレクトリ名およびユー
ザーが指定する要素のサンプルを示します。
このような要素には、コンピュータ名および
データベース名、ネット・サービス名および
接続識別子があります。また、ユーザーが指
定するデータベース・オブジェクトとデータ
ベース構造、列名、パッケージとクラス、
ユーザー名とロール、プログラム・ユニット
およびパラメータ値も含まれます。
sqlplus と入力して、SQL*Plus をオープンしま
す。
固定幅フォントの
小文字
BACKUP コマンドを使用して、データベースのバッ
クアップを作成できます。
USER_TABLES データ・ディクショナリ・ビュー内
の TABLE_NAME 列を問い合せます。
DBMS_STATS.GENERATE_STATS プロシージャを使
用します。
パスワードは、orapwd ファイルで指定します。
/disk1/oracle/dbs ディレクトリ内のデータ・
ファイルおよび制御ファイルのバックアップを作成
します。
hr.departments 表には、department_id、
department_name および location_id 列があ
ります。
QUERY_REWRITE_ENABLED 初期化パラメータを
true に設定します。
oe ユーザーとして接続します。
固定幅フォントの
小文字の
イタリック
注意 : プログラム要素には、大文字と小文字
を組み合せて使用するものもあります。これ
らの要素は、記載されているとおりに入力し
てください。
JRepUtil クラスが次のメソッドを実装します。
固定幅フォントの小文字のイタリックは、プ
レースホルダまたは変数を示します。
parallel_clause を指定できます。
old_release.SQL を実行します。ここで、
old_release とはアップグレード前にインストー
ルしたリリースを示します。
xix
コード例の表記規則
コード例は、SQL、PL/SQL、SQL*Plus または他のコマンドライン文の例です。次のように固
定幅フォントで表示され、通常のテキストと区別されます。
SELECT USERNAME FROM DBA_USERS WHERE USERNAME = 'MIGRATE';
次の表に、コード例で使用される表記規則とその使用例を示します。
規則
意味
例
[ ]
大カッコは、カッコ内の項目を任意に選択す
ることを表します。
DECIMAL (digits [ , precision ])
{ }
中カッコは、カッコ内の項目がグループ化さ
れた項目であることを表します。
{ENABLE | DISABLE}
|
縦線は、複数の選択項目の区切りに使用しま
す。
{ENABLE | DISABLE}
[COMPRESS | NOCOMPRESS]
...
省略記号は、構文の説明での繰返しを表しま
す。
CREATE TABLE ... AS subquery;
コード例またはテキストでは、省略記号は項
目が省略されていることを表します。
SELECT col1, col2, ... , coln FROM
employees;
その他の記号
大カッコ([ ])、中カッコ({ })、縦線(|)
および省略記号(...)以外の記号は、記載さ
れているとおりに入力する必要があります。
acctbal NUMBER(11,2);
acct
CONSTANT NUMBER(4) := 3;
イタリック体
イタリック体は、特定の値を指定する必要が
あるプレースホルダや変数を示します。
CONNECT SYSTEM/system_password
DB_NAME = database_name
大文字
大文字は、システム指定の要素を示します。
これらの要素は、ユーザー定義の要素と区別
するために大文字で示されます。大カッコ内
にないかぎり、表示されているとおりの順序
および綴りで入力します。ただし、大 / 小文
字が区別されないため、大文字または小文字
のいずれでも入力できます。
SELECT last_name, employee_id FROM
employees;
SELECT * FROM USER_TABLES;
DROP TABLE hr.employees;
小文字
小文字は、表名、列名、ファイル名などの
ユーザー指定のプログラム要素を示します。
SELECT last_name, employee_id FROM
employees;
sqlplus hr/hr
CREATE USER mjones IDENTIFIED BY ty3MU9;
注意 : プログラム要素には、大文字と小文字
を組み合せて使用するものもあります。これ
らの要素は、記載されているとおりに入力し
てください。
サポートおよびサービス
次の各項に、各サービスに接続するための URL を記載します。
オラクル社カスタマ・サポート・センター
オラクル製品サポートの購入方法、およびオラクル社カスタマ・サポート・センターへの連絡
方法の詳細は、次の URL を参照してください。
http://www.oracle.co.jp/support/
製品マニュアル
製品のマニュアルは、次の URL にあります。
http://otn.oracle.co.jp/document/
xx
研修およびトレーニング
研修に関する情報とスケジュールは、次の URL で入手できます。
http://www.oracle.co.jp/education/
その他の情報
オラクル製品やサービスに関するその他の情報については、次の URL から参照してください。
http://www.oracle.co.jp
http://otn.oracle.co.jp
注意 : ドキュメント内に記載されている URL や参照ドキュメントには、
Oracle Corporation が提供する英語の情報も含まれています。日本語版の
情報については、前述の URL を参照してください。
xxi
xxii
PL/SQL の新機能
ここでは、PL/SQL 10g リリース 1(10.1)の新機能について説明し、追加情報の参照先を示し
ます。
次の PL/SQL の新機能について説明します。
■
Oracle Database 10g リリース 2(10.2)の PL/SQL の新機能
■
Oracle Database 10g リリース 1(10.1)の PL/SQL の新機能
参照 :
■
PL/SQL の新機能の詳細および例については、次の URL で Oracle
Technology Network(OTN)の PL/SQL ホーム・ページを参照して
ください。
http://www.oracle.com/technology/tech/pl_sql/
■
次の URL で Oracle Technology Network(OTN)の「Oracle By
Example - Using Oracle Database 10g PL/SQL New Features」を参照
してください。バルク・バインド拡張機能と JDeveloper による
PL/SQL のデバッグなどを扱っています。
http://www.oracle.com/technology/obe/obe10gdb/develop
/plsql/plsql.htm
xxiii
Oracle Database 10g リリース 2(
(10.2)の
)の PL/SQL の新機能
Oracle Database 10g リリース 2(10.2)の新機能は、次のとおりです。
条件付きコンパイル
この機能を使用すると、コンパイル時に評価される条件の値に応じて、特定のコードをインク
ルードできます。たとえば、条件付きコンパイルを使用すると、特定のデータベース・リリー
スに対して、PL/SQL アプリケーションのどの PL/SQL 機能を使用するかを指定できます。ア
プリケーションの最新の PL/SQL の機能は、新しいデータベース・リリースで実行できると同
時に、その同じアプリケーションが以前のデータベース・リリースと互換性を持つように、こ
れらの機能に条件を付けることができます。また、条件付きコンパイルは、本番環境でデバッ
グ作業を行わずに、開発環境でデバッグを行う時に役立ちます。2-29 ページの「条件付きコン
パイル」を参照してください。
動的なラップ
DBMS_DDL の wrap サブプログラムは、実装の細部をユーザーから隠ぺいするために、Oracle
データベースに生成した PL/SQL コード・ユニットを動的に不明瞭化(非表示)にします。付
録 A「PL/SQL のソース・コードの不明瞭化」を参照してください。
PLS_INTEGER データ型の更新
PLS_INTEGER データ型の範囲は、32 ビットで表すと、-2147483648 ~ 2147483647 です。3-4
ページの「PLS_INTEGER データ型」を参照してください。
Oracle Database 10g リリース 1(
(10.1)の
)の PL/SQL の新機能
Oracle Database 10g リリース 1(10.1)の PL/SQL の新機能は、次のとおりです。
パフォーマンスの向上
PL/SQL のパフォーマンスは全体的に向上しています。ほとんどのパフォーマンスは自動的に
向上し、何もする必要はありません。PL/SQL コードのグローバル最適化は、
PLSQL_OPTIMIZE_LEVEL 初期化パラメータで制御されます。デフォルトの最適化レベルを使
用すると、様々な PL/SQL 操作のパフォーマンスが向上します。ほとんどのユーザーは、デ
フォルトの最適化レベルを変更する必要がありません。
具体的には、整数パフォーマンスの向上、式値の再利用、コードの分岐の単純化、一部のライ
ブラリ・コールのパフォーマンスの向上および到達不能コードの排除が実現されています。
新しいデータ型 BINARY_FLOAT および BINARY_DOUBLE を使用すると、科学的データの処理
など、大量の演算を行うアプリケーションのパフォーマンスが向上します。
設定する初期化パラメータ数の減少、必要なコンパイラ構成の削減、データベースに格納され
たオブジェクト・コード、および Oracle Real Application Clusters 環境との互換性によって、
PL/SQL のネイティブ・コンパイルがより統合され、簡単になっています。
FORALL 文を使用すると、削除された要素を含む結合配列およびネストした表を処理できます。
このパフォーマンス構成を以前より多くの場面で使用でき、これによって 1 つのコレクション
から別のコレクションに要素をコピーする必要がなくなります。
PL/SQL のネイティブ・コンパイルの拡張
ネイティブ・コンパイル用の初期化パラメータの構成およびコマンドの設定が簡略化されてい
ます。必要なパラメータは PLSQL_NATIVE_LIBRARY_DIR のみです。コンパイラ、リンカー
および make ユーティリティに関連するパラメータは廃止されています。ネイティブ・コンパ
イルは、PLSQL_COMPILER_FLAGS パラメータの 1 つのオプション(廃止)ではなく、専用の
PLSQL_CODE_TYPE 初期化パラメータで有効または無効にできます。
xxiv
コンパイルおよびリンク用のコマンドとオプションが含まれているのは、make ファイルではな
く、$ORACLE_HOME/plsql/spnc_commands ファイルです。新しいスクリプト
dbmsupgnv.sql は、データベース内のすべての PL/SQL モジュールを NATIVE として再コン
パイルします。dbmsupgin.sql スクリプトは、データベース内のすべての PL/SQL モジュー
ルを INTERPRETED として再コンパイルします。
パッケージ本体とその仕様部は、同じネイティブ・コンパイル設定でコンパイルする必要があ
りません。たとえば、パッケージ本体をネイティブにコンパイルしてパッケージ仕様部を解釈
したり、逆に本体を解釈して仕様部をネイティブにコンパイルできます。
ネイティブにコンパイルされたサブプログラムはデータベースに格納され、対応する共有ライ
ブラリは必要に応じて自動的に抽出されます。共有ライブラリのバックアップ、古い共有ライ
ブラリのクリーンアップ、または共有ライブラリが誤って削除された場合に発生する状況を考
慮する必要はありません。
ネイティブ・コンパイル中に発生したエラーは、SQL*Plus コマンド SHOW ERRORS を使用し
て、USER_ERRORS ディレクトリ・ビューに表示できます。
11-22 ページの「システム固有の実行のための PL/SQL コードのコンパイル」を参照してくだ
さい。
非連続索引の FORALL サポート
FORALL 文に INDICES OF および VALUES OF 句を指定して、非連続索引値を反復できます。
たとえば、ネストした表から要素を削除した後でも、FORALL 文でそのネストした表を使用で
きます。11-8 ページの「FORALL 文の使用」を参照してください。
新しい IEEE 浮動小数点型
新しいデータ型 BINARY_FLOAT および BINARY_DOUBLE は、IEEE 754 形式で浮動小数点数を
表します。これらの型は、浮動小数点に IEEE 754 標準が使用される他のプログラムおよび言語
とデータを交換する、科学的な計算に役立ちます。多くのコンピュータ・システムがシステム
固有のプロセッサ命令を介して IEEE 754 浮動小数点の操作をサポートするため、これらの型は
浮動小数点データを伴う集中的な計算に効果的です。
これらの型は、1.0f や 3.141d などの数値リテラル、平方根や剰余などの算術演算、例外処
理、および非数値(NaN)や無限大などの特殊な値をサポートします。
サブプログラムのオーバーロードの規則が拡張されており、PLS_INTEGER、NUMBER、
BINARY_FLOAT および BINARY_DOUBLE パラメータを操作する 1 つのファンクションの様々
なバージョンを使用して数学ライブラリを記述できます。3-2 ページの「PL/SQL の数値型」を
参照してください。
BINARY_INTEGER データ型への変更
Oracle 10g リリース 1(10.1)以降では、BINARY_INTEGER データ型が変更され、
PLS_INTEGER と同じになりました。そのため、これらのデータ型を同じように使用できます。
3-2 ページの「BINARY_INTEGER データ型」を参照してください。
注意 : Oracle 10g リリース 1(10.1)より前では、PLS_INTEGER の方が
BINARY_INTEGER よりも効率的なため、古いデータベース・リリースで
コードを実行するときには、PLS_INTEGER データ型を使用することをお
薦めします。ただし、Oracle 10g リリース 1(10.1)より前のリリースで
は、PLS_INTEGER データ型と BINARY_INTEGER データ型でのオーバー
フローの動作が異なります。Oracle 10g リリース 1(10.1)より前では、2
つの BINARY_INTEGER のデータ型で計算を実行して BINARY_INTEGER
の範囲値をオーバーフローした場合、結果を NUMBER データ型に代入し、
オーバーフロー例外は発生しませんでした。3-4 ページの「PLS_INTEGER
データ型」を参照してください。
xxv
オーバーロードの改善
様々な数値引数を受け入れるサブプログラムをオーバーロードして、様々なデータ型に特化し
た各サブプログラムのバージョンを使用して、数学ライブラリを記述できます。8-10 ページの
「数値型のオーバーロードのガイドライン」を参照してください。
ネストした表の拡張
PL/SQL に定義されたネストした表には、以前より多くの操作を実行できます。ネストした表
が同じかどうかの比較、要素がネストした表のメンバーであるかどうかのテスト、1 つのネス
トした表が別のネストした表のサブセットであるかどうかのテスト、和集合や共通集合などの
集合操作の実行など、様々な操作を行うことができます。5-12 ページの「コレクションの代入」
および 5-15 ページの「コレクションの比較」を参照してください。
コンパイル時の警告
サブプログラムのコンパイルで曖昧な結果が生成されたり、非効率な構造体が使用された場合、
Oracle では警告を発行できます。これらの警告は、PLSQL_WARNINGS 初期化パラメータおよ
び DBMS_WARNING パッケージを介して選択的に有効または無効にできます。10-17 ページの
「PL/SQL のコンパイル時の警告の概要」を参照してください。
文字列リテラルの引用符付けメカニズム
文字列リテラル内の一重引用符を二重にするかわりに、リテラル用に独自のデリミタ文字を指
定して、文字列内に一重引用符を使用することができます。2-6 ページの「文字列リテラル」を
参照してください。
CLOB と NCLOB 間での暗黙的変換
CLOB から NCLOB、または NCLOB から CLOB に暗黙的変換を実行できます。この操作はコスト
がかかる可能性があるため、TO_CLOB および TO_NCLOB ファンクションを使用して保全性を
継続することが有効である場合があります。
正規表現
UNIX 形式の正規表現に精通しているユーザーは、問合せおよび文字列操作の実行に正規表現
を使用できます。SQL 問合せに REGEXP_LIKE 演算子を使用し、通常 INSTR、REPLACE およ
び SUBSTR を使用する場所に REGEXP_INSTR、REGEXP_REPLACE および REGEXP_SUBSTR
ファンクションを使用します。2-37 ページの「PL/SQL の組込みファンクションのまとめ」お
よび 11-5 ページの「組込み文字列ファンクションの使用」を参照してください。
フラッシュバック問合せのファンクション
SCN_TO_TIMESTAMP および TIMESTAMP_TO_SCN ファンクションを使用すると、ある時点で
のデータベース状態を表すシステム変更番号と日時の間の変換を実行できます。3-13 ページの
例 3-2「SCN_TO_TIMESTAMP および TIMESTAMP_TO_SCN ファンクションの使用」を参照
してください。2-37 ページの「PL/SQL の組込みファンクションのまとめ」を参照してくださ
い。
xxvi
1
PL/SQL の概要
この章では、PL/SQL 言語の主な機能について説明します。データベース・プログラミングに
対する PL/SQL の機能、および他のプログラミング言語で習得した手法を再利用する方法を示
します。
この章の項目は、次のとおりです。
■
PL/SQL のメリット
■
PL/SQL の主な特長
■
PL/SQL アーキテクチャ
参照 :
■
PL/SQL の詳細とサンプル・コードについては、次の URL で Oracle
Technology Network(OTN)を参照してください。
http://www.oracle.com/technology/tech/pl_sql/
■
「Best Practice PL/SQL」などの、OTN の特定の項目の情報にアクセ
スするには、次の URL で OTN メイン・ページの検索フィールドに適
切な語句を入力してください。
http://www.oracle.com/technology/
PL/SQL の概要
1-1
PL/SQL のメリット
PL/SQL のメリット
PL/SQL は完全な移植性を持つ高性能のトランザクション処理言語で、次のようなメリットが
あります。
■
SQL との緊密な統合
■
高いパフォーマンス
■
高い生産性
■
完全な移植性
■
優れたセキュリティ
■
事前定義パッケージへのアクセス
■
オブジェクト指向プログラミングのサポート
■
Web アプリケーションおよび Web ページ開発のサポート
SQL との緊密な統合
SQL は、柔軟かつ強力で、しかも覚えやすいという特長のために、標準データベース言語にな
りました。SELECT、INSERT、UPDATE、DELETE などの、いくつかの英語に似たコマンドを使
用して、リレーショナル・データベースに格納されているデータを簡単に操作できます。
PL/SQL では、SQL のすべてのファンクション、演算子および疑似列と同様に、SQL のデータ
操作、カーソル制御およびトランザクション制御のすべてのコマンドを使用できます。SQL の
この拡張サポートによって、Oracle データを柔軟かつ安全に操作できます。また、PL/SQL で
SQL のデータ型が完全にサポートされているため、アプリケーションとデータベースの間で
データをやり取りする際、データを変換する必要が少なくなります。
PL/SQL 言語と SQL は緊密に統合されています。SQL データ型と PL/SQL データ型の変換を
行う必要はありません。データベースの NUMBER または VARCHAR2 列は、PL/SQL の NUMBER
または VARCHAR2 変数に格納されます。この統合によって、学習および処理に必要な時間が短
縮されます。PL/SQL 言語の特別な機能によって、データ型を指定せずに表の列や行を操作で
きるため、表の定義が変更された場合のメンテナンス作業が簡略化されます。
PL/SQL における SQL 問合せの実行および結果セットの処理は、一般的なスクリプト言語でテ
キスト・ファイルを開いて各行を処理する場合と同様に簡単です。データベース・オブジェク
トのメタデータへのアクセスおよびデータベースのエラー条件の処理に PL/SQL を使用して、
データベース管理用のユーティリティ・プログラムを作成できます。このプログラムは信頼性
が高く、各操作が正常に終了したかどうかの出力を読みやすい形式で生成します。PL/SQL は、
トリガーやオブジェクト型など、データベースの多くの機能で使用されます。トリガー本体お
よびオブジェクト型のメソッドを PL/SQL で作成できます。
PL/SQL は静的 SQL および動的 SQL の両方をサポートしています。静的 SQL 文の構文はプリ
コンパイル時にわかり、その準備は実行前に行われます。一方、動的 SQL 文の構文は実行時ま
でわかりません。動的 SQL は、アプリケーションをより柔軟で多目的に使用できるプログラミ
ング技術です。プログラムでは、表名や WHERE 句などの詳細情報が事前にわからない場合で
も、SQL データ定義文、データ制御文、セッション制御文を実行時に作成して処理できます。
PL/SQL での静的 SQL の使用の詳細は、第 6 章「PL/SQL での SQL 操作の実行」を参照して
ください。動的 SQL の使用の詳細は、第 7 章「システム固有の動的 SQL を使用した SQL 操作
の実行」を参照してください。動的 SQL の詳細は、『Oracle Database アプリケーション開発者
ガイド - 基礎編』を参照してください。
1-2
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL のメリット
高いパフォーマンス
PL/SQL がなければ、Oracle は SQL 文を 1 文ずつ処理する必要があります。多くの SQL 文を
発行するプログラムでは、データベースに対して複数回のコールを行う必要があるため、ネッ
トワークおよびパフォーマンスのオーバーヘッドが非常に大きくなります。
PL/SQL があれば、複数文のブロック全体を Oracle に一度に送信できます。そのため、データ
ベースとアプリケーションの間のネットワークの通信量を大幅に削減できます。図 1-1 に示す
ように、PL/SQL ブロックおよびサブプログラムを使用して SQL 文をグループ化してから、
データベースに送信して実行することができます。PL/SQL 言語には、ループの中で発行され
た SQL 文をさらにスピードアップする機能も備わっています。
PL/SQL ストアド・プロシージャは一度コンパイルされてから実行可能なフォームで格納され
るため、プロシージャ・コールは効果的です。ストアド・プロシージャはデータベース・サー
バー内で実行されるため、ネットワーク上で一度コールすると大規模なジョブを開始できます。
この作業の分割によってネットワークの通信量が軽減され、応答時間が改善されます。ストア
ド・プロシージャはキャッシュされ、ユーザー間で共有されます。これによって、必要なメモ
リー量と起動オーバーヘッドが減少します。
図 1-1 PL/SQL によるパフォーマンスの向上
高い生産性
PL/SQL では、データを操作するコードを非常にコンパクトにすることができます。Perl のよ
うなスクリプト言語が、ファイルからデータを読み込み、変換して、書き込むのと同じように、
PL/SQL は、データベースのデータを問い合せ、変換して、更新することができます。
PL/SQL では、例外処理、カプセル化、データ隠ぺいおよびオブジェクト指向のデータ型など、
あらゆるソフトウェア・エンジニアリング機能が提供されているため、設計およびデバック時
間を節約できます。
PL/SQL は、Oracle Forms などのツールを拡張します。これらのツールで PL/SQL を使用する
と、使い慣れた言語の構造体を使用してアプリケーションを構築できます。たとえば、複数の
トリガー・ステップ、マクロまたはユーザー・イグジットを使用するかわりに、Oracle Forms
トリガーの中で PL/SQL ブロック全体を使用できます。また、PL/SQL はどの環境でも同じで
す。ある 1 つの Oracle ツールで習得した PL/SQL の知識は他のツールにも利用できます。
PL/SQL の概要
1-3
PL/SQL のメリット
完全な移植性
PL/SQL で作成されたアプリケーションは、Oracle データベースが動作する任意のオペレー
ティング・システムおよびプラットフォームで実行できます。したがって、PL/SQL を使用す
ると、様々な環境で再利用できる、移植性の高いプログラム・ライブラリを作成できます。
優れたセキュリティ
PL/SQL ストアド・プロシージャは、クライアントからサーバーへアプリケーション・コード
を移動します。サーバーでは、コードの改ざんの防止、コード内の細部の隠ぺいおよびアクセ
スの制限が可能になります。たとえば、表を更新するプロシージャへのアクセス権をユーザー
に付与して、表自体または UPDATE 文のテキストへのアクセス権は付与しないようにできます。
PL/SQL で作成されたトリガーは、データへの変更を制御および記録して、すべての変更がビ
ジネス・ルールに従っていることを確認します。
PL/SQL のソース・ユニットのラップまたは隠ぺいの詳細は、付録 A「PL/SQL のソース・
コードの不明瞭化」を参照してください。
事前定義パッケージへのアクセス
Oracle では、様々な実用的な作業を実行するために PL/SQL からコールできる API を定義した
製品固有のパッケージを提供しています。これらのパッケージには、データベースのトリガー
を使用するための DBMS_ALERT、オペレーティング・システム(OS)のテキスト・ファイルを
読み書きするための DBMS_FILE、Hypertext Transfer Protocol(HTTP)のコールアウトを実行
するための DBMS_HTTP、PL/SQL ブロックおよびサブプログラムの出力を表示するための
DBMS_OUTPUT、名前付きパイプを介して通信するための DBMS_PIPE などがあります。これら
のパッケージの詳細は、9-9 ページの「製品固有のパッケージの概要」を参照してください。
Oracle が提供するパッケージの詳細は、『Oracle Database PL/SQL パッケージ・プロシージャ
およびタイプ・リファレンス』を参照してください。
オブジェクト指向プログラミングのサポート
オブジェクト型は理想的なオブジェクト指向のモデル・ツールであり、それによって複雑なア
プリケーションの構築に必要な費用と時間を節約できます。オブジェクト型を使用すると、モ
ジュール構造で維持および再利用が可能なソフトウェア構成要素を作成できるのみでなく、複
数の異なるチームのプログラマが同時にソフトウェア構成要素を開発できます。
データに対する操作をカプセル化すると、オブジェクト型を使用してデータ・メンテナンスの
ためのコードを SQL スクリプトや PL/SQL ブロックではなく、メソッドに入れることができま
す。また、オブジェクト型を使用すれば、実装の細部が隠されるため、クライアント・プログ
ラムに影響することなく細部を変更できます。第 12 章「PL/SQL のオブジェクト型の使用」を
参照してください。
さらに、オブジェクト型を使用することで、現実のデータをモデル化できます。複雑な実世界
のエンティティと関連は、オブジェクト型に直接対応付けることができます。この直接マッピ
ングは、プログラムがシミュレートしている世界をより適切に反映するために役立ちます。オ
ブジェクト型の情報は、
『Oracle Database アプリケーション開発者ガイド - オブジェクト・リ
レーショナル機能』を参照してください。
Web アプリケーションおよび Web ページ開発のサポート
PL/SQL を使用すると、Web アプリケーションおよび Server Pages(PSP)を開発できます。
Web での PL/SQL の使用の概要は、2-36 ページの「PL/SQL を使用して Web アプリケーショ
ンおよび Server Pages を作成する方法」を参照してください。
1-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の主な特長
PL/SQL の主な特長
PL/SQL では、SQL のデータ操作機能と手続き型言語の処理機能の両方が利用できます。IF 文
や LOOP 文を使用すると、プログラム・フローを制御できます。その他の手続き型プログラム
言語と同様に、変数の宣言、プロシージャとファンクションの定義、およびランタイム・エ
ラーのトラップを行うこともできます。
PL/SQL を使用すると、複雑な問題を容易に理解できるプロシージャ・コードに分割し、複数
のアプリケーション間でそのコードを再利用できます。単純な SQL で問題が解決できる場合、
PL/SQL プログラム内で SQL コマンドを直接発行できます。新しい API を学習する必要はあり
ません。PL/SQL のデータ型は、SQL の列型と対応しているため、PL/SQL の変数と表内の
データを容易に交換できます。
PL/SQL ブロック構造
PL/SQL プログラムを構成する基本単位(プロシージャ、ファンクションおよび無名ブロック)
は、内部で相互にネストできる論理ブロックです。ブロックは、関連する宣言および文をグ
ループ化します。宣言は、それを使用する場所に近い場所に置くことができます。大規模なサ
ブプログラムの内部でも可能です。宣言はブロックの中で局所的に有効で、そのブロックが終
了すると消滅します。これによって、変数およびプロシージャの名前空間が一杯になることを
回避できます。ブロック構造の構文の詳細は、13-8 ページの「ブロック宣言」を参照してくだ
さい。
図 1-2 に示すとおり、PL/SQL ブロックは宣言部(DECLARE)
、実行部(BEGIN ..END)およ
びエラー条件を処理する例外処理(EXCEPTION)部の 3 つの基本部分で構成されます。この
うち必ず存在する必要があるのは実行部のみです。最初に記述されるのはオプションの宣言部
で、ここでは型や変数などの項目を定義できます。宣言した項目は、実行部で操作できます。
実行の間に起動された例外は、例外処理部で処理されます。PL/SQL ブロック構造の例は、1-6
ページの例 1-3 を参照してください。
図 1-2 ブロック構造
[DECLARE
-- declarations]
BEGIN
-- statements
[EXCEPTION
-- handlers]
END;
PL/SQL のブロックまたはサブプログラムの実行部と例外処理部では、ブロックをネストでき
ます。宣言部ではネストできません。また、どのブロックの宣言部でも、ローカル・サブプロ
グラムを定義できます。ローカル・サブプログラムは、それが定義されているブロックからの
みコールできます。
PL/SQL の変数および定数
PL/SQL では変数と定数を宣言し、SQL 文とプロシージャ文の中で、式を使用可能な任意の場
所で使用できます。このため、他の文で変数と定数を参照するときは、事前に宣言する必要が
あります。詳細は、2-9 ページの「宣言」を参照してください。
変数の宣言
変数は、CHAR、DATE、NUMBER などの任意の SQL データ型や、BOOLEAN、PLS_INTEGER な
どの PL/SQL 固有のデータ型を持つことができます。たとえば、6 桁の数字が入る part_no、
ブール値 TRUE または FALSE が入る in_stock など、部のデータの変数を宣言します。これ
らの変数および前述の部の変数は、例 1-1 で示すように宣言します。宣言部の各行の最後には、
セミコロン(;)を付けます。
PL/SQL の概要
1-5
PL/SQL の主な特長
例 1-1 PL/SQL 変数の宣言
DECLARE
part_no
part_name
in_stock
part_price
part_desc
NUMBER(6);
VARCHAR2(20);
BOOLEAN;
NUMBER(6,2);
VARCHAR2(50);
コンポジット・データ型 TABLE、VARRAY、RECORD を使用して、ネストした表、可変サイズ
の配列(VARRAY)およびレコードも宣言できます。第 5 章「PL/SQL のコレクションおよび
レコードの使用」を参照してください。
変数への値の代入
変数に値を代入する方法は 3 つあります。1 つ目は、例 1-2 で示すように、コロンに等号を付け
た代入演算子(:=)を使用する方法です。変数は演算子の左に、ファンクション・コールを含
む式は演算子の右に置きます。変数を宣言するときに、変数に値を代入できます。
例 1-2 代入演算子を使用した変数への値の代入
DECLARE
wages
NUMBER;
hours_worked
NUMBER := 40;
hourly_salary NUMBER := 22.50;
bonus
NUMBER := 150;
country
VARCHAR2(128);
counter
NUMBER := 0;
done
BOOLEAN;
valid_id
BOOLEAN;
emp_rec1
employees%ROWTYPE;
emp_rec2
employees%ROWTYPE;
TYPE commissions IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
comm_tab
commissions;
BEGIN
wages := (hours_worked * hourly_salary) + bonus;
country := 'France';
country := UPPER('Canada');
done := (counter > 100);
valid_id := TRUE;
emp_rec1.first_name := 'Antonio';
emp_rec1.last_name := 'Ortiz';
emp_rec1 := emp_rec2;
comm_tab(5) := 20000 * 0.15;
END;
/
変数に値を代入する 2 つ目の方法は、データベース値を選択またはフェッチして代入する方法
です。例 1-3 では、従業員の給料の 10% が選択され、bonus 変数に代入されます。変数 bonus
を別の計算に使用したり、変数の値をデータベース表に挿入することができます。
例 1-3 SELECT INTO を使用した変数への値の代入
DECLARE
bonus NUMBER(8,2);
emp_id NUMBER(6) := 100;
BEGIN
SELECT salary * 0.10 INTO bonus FROM employees
WHERE employee_id = emp_id;
END;
/
1-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の主な特長
変数を値に代入する 3 つ目の方法は、値を OUT パラメータまたは IN OUT パラメータとしてサ
ブプログラムに渡し、サブプログラム内で代入する方法です。例 1-4 では、サブプログラムに
変数 sal を渡し、そのサブプログラムで変数を更新しています。
この例では、DBMS_OUTPUT.PUT_LINE を使用して PL/SQL プログラムの出力を表示していま
す。詳細は、1-15 ページの「PL/SQL を使用したデータの入出力」を参照してください。
DBMS_OUTPUT パッケージの詳細は、9-9 ページの「DBMS_OUTPUT パッケージ」を参照して
ください。
例 1-4 サブプログラムのパラメータとしての変数への値の代入
REM SERVEROUTPUT must be set to ON to display output with DBMS_OUTPUT
SET SERVEROUTPUT ON FORMAT WRAPPED
DECLARE
new_sal NUMBER(8,2);
emp_id NUMBER(6) := 126;
PROCEDURE adjust_salary(emp_id NUMBER, sal IN OUT NUMBER) IS
emp_job VARCHAR2(10);
avg_sal NUMBER(8,2);
BEGIN
SELECT job_id INTO emp_job FROM employees WHERE employee_id = emp_id;
SELECT AVG(salary) INTO avg_sal FROM employees WHERE job_id = emp_job;
DBMS_OUTPUT.PUT_LINE ('The average salary for ' || emp_job
|| ' employees: ' || TO_CHAR(avg_sal));
sal := (sal + avg_sal)/2; -- adjust sal value which is returned
END;
BEGIN
SELECT AVG(salary) INTO new_sal FROM employees;
DBMS_OUTPUT.PUT_LINE ('The average salary for all employees: '
|| TO_CHAR(new_sal));
adjust_salary(emp_id, new_sal); -- assigns a new value to new_sal
DBMS_OUTPUT.PUT_LINE ('The adjusted salary for employee ' || TO_CHAR(emp_id)
|| ' is ' || TO_CHAR(new_sal)); -- sal has new value
END;
/
バインド変数
PL/SQL コードに SQL の INSERT、UPDATE、DELETE または SELECT 文を直接埋め込むと、
PL/SQL は、WHERE 句および VALUES 句内の変数を自動的にバインド変数に変換します。これ
らの SQL 文は、同じコードが実行されるたびに Oracle によって再利用されます。異なる変数
値を持つ類似する文を実行する場合、パラメータを受け取り、それらのパラメータを文の適切
な部分に代入してその文を発行するストアド・プロシージャをコールすることで、解析による
オーバーヘッドを低減できます。
動的 SQL の場合は、変数を通常使用する部分(WHERE 句や VALUES 句など)にバインド変数
を指定する必要があります。リテラルおよび変数値を連結して単一の文字列にするかわりに、
変数をバインド変数の名前(先頭にコロンを追加したもの)に置き換え、USING 句を使用して
対応する PL/SQL 変数を指定します。変数を連結して文字列にするかわりに USING 句を使用
すると、解析によるオーバーヘッドを低減し、Oracle で SQL 文を再利用することができます。
次に例を示します。
'DELETE FROM employees WHERE employee_id = :id' USING emp_id;
バインド変数の使用例は、7-3 ページの例 7-1 を参照してください。
定数の宣言
定数の宣言は変数の宣言と似ていますが、キーワード CONSTANT を付ける点と、定数に直接値
を代入する必要がある点が異なります。後で定数に値を代入することはできません。定数の宣
言を次の例に示します。
credit_limit CONSTANT NUMBER := 5000.00;
2-9 ページの「定数」を参照してください。
PL/SQL の概要
1-7
PL/SQL の主な特長
PL/SQL を使用した問合せの処理
PL/SQL を使用した SQL 問合せの処理は、他の言語を使用したファイルの処理と似ています。
たとえば、Perl プログラムは、ファイルをオープンして内容を読み取り、各行を処理した後
ファイルをクローズします。同様に、PL/SQL プログラムも、例 1-5 に示すとおり、問合せを
発行し、結果セットから取り出した行を処理します。
例 1-5 LOOP での問合せ結果の処理
BEGIN
FOR someone IN (SELECT * FROM employees WHERE employee_id < 120 )
LOOP
DBMS_OUTPUT.PUT_LINE('First name = ' || someone.first_name ||
', Last name = ' || someone.last_name);
END LOOP;
END;
/
このような単純なループを使用するか、または問合せ、データの取出しおよび処理の終了を行
う個別の文を使用して処理を正確に制御することができます。
PL/SQL サブプログラムの宣言
サブプログラムは、パラメータの組を指定してコールできる、名前の付けられた PL/SQL ブ
ロックです。PL/SQL にはプロシージャとファンクションの 2 種類のサブプログラムがありま
す。次は PL/SQL プロシージャの宣言の例です。
DECLARE
in_string VARCHAR2(100) := 'This is my test string.';
out_string VARCHAR2(200);
PROCEDURE double ( original IN VARCHAR2, new_string OUT VARCHAR2 ) AS
BEGIN
new_string := original || original;
END;
パッケージのサブプログラム宣言の例は、1-13 ページの例 1-13 を参照してください。サブプロ
グラムの詳細は、8-2 ページの「サブプログラム」を参照してください。
データベースに格納された SQL 文を使用してスタンドアロン・サブプログラムを作成できま
す。1-12 ページの「サブプログラム : プロシージャおよび機能」を参照してください。
PL/SQL 変数のデータ型の宣言
各 PL/SQL 変数の宣言の一部として、変数のデータ型を宣言します。通常、このデータ型は、
NUMBER または VARCHAR2 などの、PL/SQL と SQL の間で共有されるデータ型の 1 つです。特
別な修飾子 %TYPE および %ROWTYPE を使用して表の列または表の行を保持する変数を宣言す
ると、データベースと相互作用するコードのメンテナンスがより簡単になります。データ型の
詳細は、第 3 章「PL/SQL のデータ型」を参照してください。
%TYPE
%TYPE 属性は、変数またはデータベース列のデータ型を与えます。これはデータベース値を保
持する変数を宣言する場合に、特に便利です。たとえば、employees という名前の表に
last_name という名前の列があるとします。列 title と同じデータ型の変数 v_last_name
を宣言するには、ドット表記法と %TYPE 属性を次のように使用します。
v_last_name employees.last_name%TYPE;
%TYPE 属性を使用して v_last_name を宣言することには 2 つのメリットがあります。第 1
に、ユーザーは last_name の正確なデータ型を知る必要がありません。第 2 に、last_name
のデータベース定義を変更した場合(文字列の長さを増やすなど)でも、v_last_name の
データ型はそれに応じて実行時に変更されます。
1-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の主な特長
%TYPE の詳細は、2-10 ページの「%TYPE 属性の使用」および 13-117 ページの「%TYPE 属性」
を参照してください。
%ROWTYPE
PL/SQL ではデータのグループ化にレコードを使用します。レコードは、データ値を格納でき
る複数の関連したフィールドから構成されます。%ROWTYPE 属性は、表中の行を表すレコード
型を与えます。レコードには、表から選択された行全体、あるいはカーソルまたはカーソル変
数でフェッチされた行全体のデータを格納できます。1-15 ページの「カーソル」を参照してく
ださい。
行の中の列と、それに対応するレコード中のフィールドは、同じ名前と同じデータ型を持ちま
す。次の例では、dept_rec という名前のレコードを宣言しています。このレコードのフィー
ルドは、departments 表の列と同じ名前で同じデータ型です。
DECLARE
dept_rec departments%ROWTYPE; -- レコード変数の宣言
次の例に示すように、フィールドの値にアクセスするにはドット表記法を使用します。
v_deptid := dept_rec.department_id;
従業員の姓、給与、入社日および役職を取り出すカーソルを宣言する場合は、例 1-6 に示すと
おり、%ROWTYPE を使用して、同じ情報を格納するレコードを宣言できます。FETCH 文を実行
する場合は、employee 表の last_name 列の値は employee_rec の last_name フィールド
に、salary 列の値は salary フィールドに、というように代入されます。
例 1-6 明示カーソルでの %ROWTYPE の使用
DECLARE
CURSOR c1 IS
SELECT last_name, salary, hire_date, job_id FROM employees
WHERE employee_id = 120;
-- declare record variable that represents a row fetched from the employees table
employee_rec c1%ROWTYPE;
BEGIN
-- open the explicit cursor and use it to fetch data into employee_rec
OPEN c1;
FETCH c1 INTO employee_rec;
DBMS_OUTPUT.PUT_LINE('Employee name: ' || employee_rec.last_name);
END;
/
%ROWTYPE の詳細は、2-11 ページの「%ROWTYPE 属性の使用」および 13-102 ページの
「%ROWTYPE 属性」を参照してください。
PL/SQL の制御構造
制御構造は、SQL に対して加えられた PL/SQL の最も重要な機能拡張です。PL/SQL を使用す
ると、Oracle データを操作できるのみでなく、IF-THEN-ELSE、CASE、FOR-LOOP、
WHILE-LOOP、EXIT-WHEN、GOTO などの条件制御文、反復制御文および順次制御文を使用し
てデータを処理できます。詳細は、第 4 章「PL/SQL の制御構造の使用」を参照してください。
条件制御
状況に応じてアクションを選択する必要のある場面はよくあります。IF-THEN-ELSE 文を使用
すると、一連の文を条件に合わせて実行できます。IF 句で条件を検査します。THEN 句で条件
が TRUE の場合のアクションを定義し、ELSE 句では条件が FALSE または NULL の場合のアク
ションを定義します。例 1-7 では、IF-THEN-ELSE を使用して、従業員の現在の給与を基に受
け取る給与の昇給額を決める場合の例を示します。
PL/SQL の概要
1-9
PL/SQL の主な特長
複数の値から、またはアクションの途中で選択するには、CASE 構造体を使用できます。CASE
式では条件が評価され、各ケースの値が戻されます。CASE 文では条件が評価され、ケースご
とにアクションが実行されます。アクションは、PL/SQL ブロック全体の場合もあります。例
1-7 を参照してください。
例 1-7 IF-THEN_ELSE 文および CASE 文を使用した条件制御
DECLARE
jobid
employees.job_id%TYPE;
empid
employees.employee_id%TYPE := 115;
sal
employees.salary%TYPE;
sal_raise NUMBER(3,2);
BEGIN
SELECT job_id, salary INTO jobid, sal from employees WHERE employee_id = empid;
CASE
WHEN jobid = 'PU_CLERK' THEN
IF sal < 3000 THEN sal_raise := .12;
ELSE sal_raise := .09;
END IF;
WHEN jobid = 'SH_CLERK' THEN
IF sal < 4000 THEN sal_raise := .11;
ELSE sal_raise := .08;
END IF;
WHEN jobid = 'ST_CLERK' THEN
IF sal < 3500 THEN sal_raise := .10;
ELSE sal_raise := .07;
END IF;
ELSE
BEGIN
DBMS_OUTPUT.PUT_LINE('No raise for this job: ' || jobid);
END;
END CASE;
UPDATE employees SET salary = salary + salary * sal_raise
WHERE employee_id = empid;
COMMIT;
END;
/
問合せの結果を使用してアクションを選択する一連の文が、データベース・アプリケーション
ではよく使用されます。また、関連するエントリが別の表に見つかった場合にのみ、行の挿入
や削除を実行する一連の文もよく使用されます。このような頻繁に使用される一連の文は、条
件論理を使用して 1 つの PL/SQL ブロックにまとめることができます。
反復制御
LOOP 文を使用すると、一連の文を複数回実行できます。一連の文の最初の文の前にキーワード
LOOP を置き、最後の文の後にキーワード END LOOP を置きます。一連の文を連続的に繰り返す
最も簡単な形式のループを次に示します。
LOOP
-- 一連の文
END LOOP;
FOR-LOOP 文では、整数の範囲を指定し、範囲中のそれぞれの整数に対して一連の文を 1 回実
行できます。例 1-8 では、ループで 100 個の数値を挿入し、平方根、平方および平方和をデー
タベース表に格納します。
例 1-8 FOR-LOOP の使用
CREATE TABLE sqr_root_sum (num NUMBER, sq_root NUMBER(6,2),
sqr NUMBER, sum_sqrs NUMBER);
DECLARE
s PLS_INTEGER;
1-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の主な特長
BEGIN
FOR i in 1..100 LOOP
s := (i * (i + 1) * (2*i +1)) / 6; -- sum of squares
INSERT INTO sqr_root_sum VALUES (i, SQRT(i), i*i, s );
END LOOP;
END;
/
WHILE-LOOP 文は、ある一連の文を条件付きで実行します。ループを反復する前に条件が評価
されます。条件が TRUE ならば、一連の文が実行されてから、ループの先頭で制御が再開しま
す。条件が FALSE または NULL ならば、ループは実行されず、制御は次の文に移ります。
例 1-9 では、従業員 120 よりも指揮系統内で上位にあり、給与が $15000 よりも高い最初の従業
員を探しています。
例 1-9 WHILE-LOOP を使用した制御
CREATE TABLE temp (tempid NUMBER(6), tempsal NUMBER(8,2), tempname VARCHAR2(25));
DECLARE
sal
employees.salary%TYPE := 0;
mgr_id
employees.manager_id%TYPE;
lname
employees.last_name%TYPE;
starting_empid employees.employee_id%TYPE := 120;
BEGIN
SELECT manager_id INTO mgr_id FROM employees
WHERE employee_id = starting_empid;
WHILE sal <= 15000 LOOP -- loop until sal > 15000
SELECT salary, manager_id, last_name INTO sal, mgr_id, lname
FROM employees WHERE employee_id = mgr_id;
END LOOP;
INSERT INTO temp VALUES (NULL, sal, lname); -- insert NULL for tempid
COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO temp VALUES (NULL, NULL, 'Not found'); -- insert NULLs
COMMIT;
END;
/
これ以上の処理を望まない場合、または不可能な場合は、EXIT-WHEN 文でループを終了できま
す。EXIT 文が見つかると、WHEN 句の中の条件が評価されます。条件が TRUE ならば、ループ
は終了し、制御は次の文に移ります。例 1-10 では、total の値が 25,000 を超えたときにルー
プが終了します。
例 1-10 EXIT-WHEN 文の使用
DECLARE
total NUMBER(9) := 0;
counter NUMBER(6) := 0;
BEGIN
LOOP
counter := counter + 1;
total := total + counter * counter;
-- exit loop when condition is true
EXIT WHEN total > 25000;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Counter: ' || TO_CHAR(counter) || ' Total: ' ||
TO_CHAR(total));
END;
/
PL/SQL の概要
1-11
PL/SQL の主な特長
順次制御
GOTO 文を使用すると、無条件にラベルへ分岐します。ラベルは、二重の山カッコで囲まれた未
宣言の識別子で、実行可能文または PL/SQL ブロックの前に置く必要があります。例 1-11 で示
すように、GOTO 文が実行されると、ラベルが付けられた文またはブロックに制御が移ります。
例 1-11 GOTO 文の使用
DECLARE
total NUMBER(9) := 0;
counter NUMBER(6) := 0;
BEGIN
<<calc_total>>
counter := counter + 1;
total := total + counter * counter;
-- branch to print_total label when condition is true
IF total > 25000 THEN GOTO print_total;
ELSE GOTO calc_total;
END IF;
<<print_total>>
DBMS_OUTPUT.PUT_LINE('Counter: ' || TO_CHAR(counter) || ' Total: ' ||
TO_CHAR(total));
END;
/
条件付きコンパイル
条件付きコンパイルを使用すると、ソース・コードを削除せずに機能を条件付けすることに
よって、コンパイルされた PL/SQL アプリケーションの機能をカスタマイズできます。たとえ
ば、条件付きコンパイルを使用すると、特定のデータベース・リリースに対して、PL/SQL ア
プリケーションのどの PL/SQL 機能を使用するかを指定できます。アプリケーションの最新の
PL/SQL の機能は、新しいデータベース・リリースで実行できると同時に、その同じアプリ
ケーションが以前のデータベース・リリースと互換性を持つように、これらの機能に条件を付
けることができます。また、条件付きコンパイルは、本番環境でデバッグ作業を行わずに、開
発環境でデバッグを行う場合に役立ちます。2-29 ページの「条件付きコンパイル」を参照して
ください。
再利用可能な PL/SQL コードの作成
PL/SQL を使用すると、アプリケーションを管理の容易な、正しく定義されたモジュールに分
けることができます。PL/SQL は、このニーズに応えるために、ブロック、サブプログラム、
パッケージなどのプログラム・ユニットを提供しています。これらのプログラム・ユニットは、
トリガー、ストアド・プロシージャおよびストアド・ファンクションとしてデータベースに
ロードして再利用できます。詳細は、第 8 章「PL/SQL のサブプログラムの使用」および第 9
章「PL/SQL パッケージの使用」を参照してください。
サブプログラム : プロシージャおよび機能
PL/SQL にはプロシージャとファンクションの 2 種類のサブプログラムがあり、そのどちらも
パラメータを取り、起動(コール)できます。8-2 ページの「サブプログラム」を参照してくだ
さい。
SQL の CREATE PROCEDURE 文を使用すると、データベースに格納するスタンドアロン・プロ
シージャを作成できます。詳細は、
『Oracle Database SQL リファレンス』の「CREATE
PROCEDURE」を参照してください。SQL の CREATE FUNCTION 文を使用すると、Oracle デー
タベースに格納するスタンドアロン・ファンクションを作成できます。詳細は、
『Oracle
Database SQL リファレンス』の「CREATE FUNCTION」を参照してください。これらの(ス
キーマ・レベルの)ストアド・サブプログラムには、SQL からアクセスできます。
1-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の主な特長
例 1-12 に示すように、サブプログラムはプログラムのミニチュアのようなもので、ヘッダーか
ら始まって宣言部(オプション)
、実行部、例外処理部(オプション)が続きます。
例 1-12 ストアド・サブプログラムの作成
-- including OR REPLACE is more convenient when updating a subprogram
CREATE OR REPLACE PROCEDURE award_bonus (emp_id NUMBER, bonus NUMBER) AS
commission
REAL;
comm_missing EXCEPTION;
BEGIN -- executable part starts here
SELECT commission_pct / 100 INTO commission FROM employees
WHERE employee_id = emp_id;
IF commission IS NULL THEN
RAISE comm_missing;
ELSE
UPDATE employees SET salary = salary + bonus*commission
WHERE employee_id = emp_id;
END IF;
EXCEPTION -- exception-handling part starts here
WHEN comm_missing THEN
DBMS_OUTPUT.PUT_LINE('This employee does not receive a commission.');
commission := 0;
WHEN OTHERS THEN
NULL; -- for other exceptions do nothing
END award_bonus;
/
CALL award_bonus(150, 400);
このプロシージャがコールされると、従業員番号およびボーナス額を受け取ります。この番号
を使用してデータベース表から従業員のコミッション・パーセントを選択し、同時にコミッ
ション・パーセントを小数値に変換します。次に、コミッション金額を検査します。コミッ
ションが NULL の場合は例外が呼び出され、NULL でない場合は従業員の給与台帳レコードが
更新されます。
パッケージ : PL/SQL で記述された API
PL/SQL では、論理的に関連のある型、変数、カーソルおよびサブプログラムを、通常のスト
アド・プロシージャより 1 段階上のデータベース・オブジェクトであるパッケージとしてまと
めることができます。このパッケージは、SQL 文がアクセスする、関連した一連のプロシー
ジャおよび型に対して単純かつ明快なインタフェースを定義します。
通常、パッケージには仕様部と本体の 2 つの部分があります。仕様部は Application Program
Interface を定義し、ここでデータ型、定数、変数、例外、カーソル、サブプログラムなどが宣
言されます。本体には、カーソルの SQL 問合せおよびサブプログラムのコードが含まれます。
パッケージ仕様部を作成するには、SQL の CREATE PACKAGE 文を使用します。CREATE
PACKAGE BODY 文でパッケージ本体を定義します。SQL の CREATE PACKAGE 文の詳細は、
『Oracle Database SQL リファレンス』を参照してください。SQL の CREATE PACKAGE BODY 文
の詳細は、
『Oracle Database SQL リファレンス』を参照してください。
例 1-13 の emp_actions パッケージには、employees 表を更新する 2 つのプロシージャと情
報を提供する 1 つのファンクションが含まれます。
例 1-13 パッケージおよびパッケージ本体の作成
CREATE OR REPLACE PACKAGE emp_actions AS -- package specification
PROCEDURE hire_employee (employee_id NUMBER, last_name VARCHAR2,
first_name VARCHAR2, email VARCHAR2, phone_number VARCHAR2,
hire_date DATE, job_id VARCHAR2, salary NUMBER, commission_pct NUMBER,
manager_id NUMBER, department_id NUMBER);
PROCEDURE fire_employee (emp_id NUMBER);
FUNCTION num_above_salary (emp_id NUMBER) RETURN NUMBER;
END emp_actions;
/
PL/SQL の概要
1-13
PL/SQL の主な特長
CREATE OR REPLACE PACKAGE BODY emp_actions AS -- package body
-- code for procedure hire_employee
PROCEDURE hire_employee (employee_id NUMBER, last_name VARCHAR2,
first_name VARCHAR2, email VARCHAR2, phone_number VARCHAR2, hire_date DATE,
job_id VARCHAR2, salary NUMBER, commission_pct NUMBER,
manager_id NUMBER, department_id NUMBER) IS
BEGIN
INSERT INTO employees VALUES (employee_id, last_name, first_name, email,
phone_number, hire_date, job_id, salary, commission_pct, manager_id,
department_id);
END hire_employee;
-- code for procedure fire_employee
PROCEDURE fire_employee (emp_id NUMBER) IS
BEGIN
DELETE FROM employees WHERE employee_id = emp_id;
END fire_employee;
-- code for function num_above salary
FUNCTION num_above_salary (emp_id NUMBER) RETURN NUMBER IS
emp_sal NUMBER(8,2);
num_count NUMBER;
BEGIN
SELECT salary INTO emp_sal FROM employees WHERE employee_id = emp_id;
SELECT COUNT(*) INTO num_count FROM employees WHERE salary > emp_sal;
RETURN num_count;
END num_above_salary;
END emp_actions;
/
これらのプロシージャをコールするアプリケーションに必要なのは、パッケージの仕様部に記
載されているプロシージャの名前およびパラメータのみです。パッケージ本体内の実装の細部
を変更しても、アプリケーションのコールには影響しません。
例 1-13 で作成された emp_actions パッケージのプロシージャをコールするには、例 1-14 の
文を実行します。このプロシージャは、BEGIN ..END ブロックの中または SQL の CALL 文で実
行できます。プロシージャ名には、接頭辞としてパッケージ名が使用されています。
例 1-14 パッケージのプロシージャのコール
CALL emp_actions.hire_employee(300, 'Belden', 'Enrique', 'EBELDEN',
'555.111.2222', '31-AUG-04', 'AC_MGR', 9000, .1, 101, 110);
BEGIN
DBMS_OUTPUT.PUT_LINE( 'Number of employees with higher salary: ' ||
TO_CHAR(emp_actions.num_above_salary(120)));
emp_actions.fire_employee(300);
END;
/
パッケージはデータベースに格納され、複数のアプリケーションで共有できます。パッケー
ジ・サブプログラムを初めてコールすると、パッケージ全体がロードされてメモリーにキャッ
シュされるため、それ以降のコールではディスク I/O が減少します。このように、パッケージ
によって再利用が促進され、複数のユーザーおよび複数のアプリケーションが存在する環境で
のパフォーマンスが向上します。パッケージの詳細は、第 9 章「PL/SQL パッケージの使用」
を参照してください。
サブプログラムがパラメータを取らない場合、PL/SQL と SQL 問合せからコールされたファン
クションの両方で、空のカッコを含めるか、またはカッコを省略することができます。パラ
メータを取らないメソッドをコールする場合、PL/SQL スコープでは空のカッコはオプション
ですが、SQL スコープでは必須です。
1-14
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の主な特長
PL/SQL を使用したデータの入出力
PL/SQL のほとんどの入出力は、SQL 文によるデータベース表へのデータの格納や、それらの
表の問合せによるものです。PL/SQL のその他のすべての I/O は、他のプログラムと相互作用
する API によるものです。たとえば、DBMS_OUTPUT パッケージには、PUT_LINE などのプロ
シージャが含まれています。PL/SQL 外部の結果を参照するには、DBMS_OUTPUT に渡された
データを読み取って表示するための、SQL*Plus などの別のプログラムが必要です。
SQL*Plus で DBMS_OUTPUT のデータを表示するには、事前に、次の SET SERVEROUTPUT ON
コマンドを発行しておく必要があります。
SET SERVEROUTPUT ON
SEVEROUTPUT 設定の詳細は、
『SQL*Plus ユーザーズ・ガイドおよびリファレンス』の
「SQL*Plus コマンド・リファレンス」の章を参照してください。
I/O 処理のその他の PL/SQL API には、次のものがあります。
■
■
HTF および HTP: Web ページへの出力を表示
DBMS_PIPE: PL/SQL とオペレーティング・システム・コマンドとの間での情報の受け渡
し
■
UTL_FILE: オペレーティング・システム・ファイルの読取りおよび書込み
■
UTL_HTTP: Web サーバーとの通信
■
UTL_SMTP: メール・サーバーとの通信
9-9 ページの「製品固有のパッケージの概要」を参照してください。これらの API の一部は出
力を行うだけでなく入力も受け入れますが、キーボードから入力されたデータを直接受け入れ
る言語機能は組み込まれていません。SQL*Plus の PROMPT および ACCEPT コマンドを使用す
ると、キーボードから入力されたデータを直接受け入れることができます。
PL/SQL のデータの抽象化
データの抽象化によって、詳細な部分を必要以上に意識することなく、データの基本的なプロ
パティを操作できます。データ構造を一度設計した後は、データ構造を操作するアルゴリズム
の設計に集中できます。
カーソル
カーソルとは、特定の文を処理する情報を保存しておく、SQL の特定のプライベート領域の名
前です。PL/SQL では、明示カーソルおよび暗黙カーソルが使用できます。PL/SQL では、1
行のみを返す問合せを含む、一連の行にあるすべての SQL データ操作文に対して、暗黙的に
カーソルが宣言されます。複数行を返す問合せの場合は、カーソルを明示的に宣言し、その行
を個別に処理できます。たとえば、1-9 ページの例 1-6 では、明示カーソルを宣言します。
PL/SQL によるカーソル管理の詳細は、6-6 ページの「PL/SQL でのカーソルの管理」を参照し
てください。
コレクション
PL/SQL のコレクション型を使用すると、他の言語で使用される配列、セットおよびハッシュ
表に類似した高水準のデータ型を宣言できます。PL/SQL では、配列型は VARRAY(可変サイ
ズの配列)
、セット型はネストした表、ハッシュ表は結合配列と呼ばれます。各コレクション
は、すべて同じ型の要素の順序付きグループです。各要素には一意の添字が付いています。そ
の番号によって、集合の中での要素の位置が決まります。コレクションを宣言する場合は、
TYPE 定義を使用します。5-6 ページの「コレクション型の定義とコレクション変数の宣言」を
参照してください。
PL/SQL の概要
1-15
PL/SQL の主な特長
要素を参照するには、例 1-15 で示すように、カッコを使用した添字表記法を使用します。
例 1-15 PL/SQL のコレクション型の使用
DECLARE
TYPE staff_list IS TABLE OF employees.employee_id%TYPE;
staff staff_list;
lname employees.last_name%TYPE;
fname employees.first_name%TYPE;
BEGIN
staff := staff_list(100, 114, 115, 120, 122);
FOR i IN staff.FIRST..staff.LAST LOOP
SELECT last_name, first_name INTO lname, fname FROM employees
WHERE employees.employee_id = staff(i);
DBMS_OUTPUT.PUT_LINE ( TO_CHAR(staff(i)) || ': ' || lname || ', ' || fname );
END LOOP;
END;
/
コレクションはパラメータとして渡すこともできるため、サブプログラムは任意の数の要素を
処理できます。コレクションを使用すると、バルク SQL と呼ばれるパフォーマンスの高い言語
機能を使用して、データベース表からデータを出し入れできます。
コレクションの詳細は、第 5 章「PL/SQL のコレクションおよびレコードの使用」を参照して
ください。
レコード
レコードのデータ構造はコンポジット型で、フィールドには様々なデータ型を含めることがで
きます。レコードを使用すると、関連する項目を保持し、単一のパラメータでサブプログラム
にこれらの項目を渡すことができます。レコードを宣言する場合は、TYPE 定義を使用します。
5-28 ページの「レコードの定義と宣言」を参照してください。
例 1-16 に、レコードの宣言方法を示します。
例 1-16 レコード型の宣言
DECLARE
TYPE timerec IS RECORD (hours SMALLINT, minutes SMALLINT);
TYPE meetin_typ IS RECORD (
date_held DATE,
duration timerec, -- nested record
location VARCHAR2(20),
purpose
VARCHAR2(50));
BEGIN
-- NULL does nothing but allows unit to be compiled and tested
NULL;
END;
/
%ROWTYPE 属性を使用して、表の行または問合せの結果セットの行を表すレコードを宣言でき
ます。フィールドの名前および型を指定する必要はありません。
レコードの詳細は、第 5 章「PL/SQL のコレクションおよびレコードの使用」を参照してくだ
さい。
オブジェクト型
PL/SQL は、オブジェクト型を介したオブジェクト指向のプログラミングをサポートします。
オブジェクト型は、データを操作するために必要なファンクションおよびプロシージャととも
にデータ構造をカプセル化します。データ構造を形成する変数は、属性と呼ばれます。属性を
操作するファンクションおよびプロシージャは、メソッドと呼ばれます。
1-16
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の主な特長
オブジェクト型によって、大規模なシステムが複数の論理エンティティに細分化されるため、
複雑さが軽減されます。これによって、モジュール構造を持ち、保持および再利用が可能なソ
フトウェア・コンポーネントを作成できます。オブジェクト型の定義およびメソッドのコード
は、データベースに格納されます。これらのオブジェクト型のインスタンスは、表に格納する
か、または PL/SQL コード内で変数として使用できます。例 1-17 に、銀行口座のオブジェクト
型の定義を示します。
例 1-17 オブジェクト型の定義
CREATE TYPE bank_account AS OBJECT (
acct_number NUMBER(5),
balance
NUMBER,
status
VARCHAR2(10),
MEMBER PROCEDURE open (SELF IN OUT NOCOPY bank_account, amount IN NUMBER),
MEMBER PROCEDURE close (SELF IN OUT NOCOPY bank_account, num IN NUMBER,
amount OUT NUMBER),
MEMBER PROCEDURE deposit (SELF IN OUT NOCOPY bank_account, num IN NUMBER,
amount IN NUMBER),
MEMBER PROCEDURE withdraw (SELF IN OUT NOCOPY bank_account, num IN NUMBER,
amount IN NUMBER),
MEMBER FUNCTION curr_bal (num IN NUMBER) RETURN NUMBER );
/
オブジェクト型の詳細は、
『Oracle Database アプリケーション開発者ガイド - オブジェクト・
リレーショナル機能』を参照してください。オブジェクトでの PL/SQL の使用の詳細は、第 12
章「PL/SQL のオブジェクト型の使用」を参照してください。
PL/SQL エラーの処理
PL/SQL では、例外と呼ばれるエラー条件を、簡単に検出して処理できます。エラーが発生す
ると、例外が呼び出されます。通常の実行は中止され、制御は任意の PL/SQL ブロックの末尾
に記述されている特別な例外処理部に移ります。例外は、種類ごとにそれぞれ特定の例外ハン
ドラによって処理されます。
PL/SQL の例外処理は、C 言語で使用されるような手動チェックとは異なり、すべての処理が
成功したことを確認するためにチェックを挿入します。そのかわりに、Java 言語の例外処理メ
カニズムと同様、エラー・ルーチンへのチェックおよびコールは自動的に行われます。
変数やデータベース操作などに関連する特定の一般的なエラー条件の場合、事前定義の例外が
自動的に呼び出されます。たとえば、数値を 0(ゼロ)で除算しようとすると、事前定義の例
外 ZERO_DIVIDE が自動的に呼び出されます。
エラーであると定義した条件に対して、または通常は ORA- エラー・メッセージが表示される
データベース・エラーに対応するように、独自の例外を定義できます。ユーザー定義のエラー
条件を検出した場合は、RAISE 文を実行します。1-13 ページの例 1-12 の例外 comm_missing
を参照してください。この例では、コミッションが NULL の場合は例外 comm_missing が呼
び出されます。
通常は、例外ハンドラをサブプログラムの最後に配置して、サブプログラム内のすべての場所
で発生した例外を処理します。例外が発生した部分から実行を継続するには、例外が発生する
可能性があるコードをさらに BEGIN-END ブロック内に入れ、そのコード用の例外ハンドラを
含めます。たとえば、NO_DATA_FOUND が発生する可能性がある SQL 文のグループや、
DIVIDE_BY_ZERO が発生する可能性がある算術演算を、それぞれ個別の BEGIN-END ブロック
に含めます。BEGIN-END ブロックを配置してループ内に例外ハンドラを含めることで、ループ
の反復中に例外が発生しても、そのループの実行を継続できます。5-26 ページの例 5-38 を参照
してください。
PL/SQL エラーの詳細は、10-2 ページの「PL/SQL のランタイム・エラー処理の概要」を参照
してください。PL/SQL の警告の詳細は、10-17 ページの「PL/SQL のコンパイル時の警告の概
要」を参照してください。
PL/SQL の概要
1-17
PL/SQL アーキテクチャ
PL/SQL アーキテクチャ
PL/SQL コンパイルおよび実行時システムは、PL/SQL ブロックとサブプログラムをコンパイ
ルして実行するエンジンです。このエンジンは、Oracle サーバーにインストールすることも、
Oracle Forms のようなアプリケーション開発ツールにインストールすることもできます。
どちらの環境でも、PL/SQL エンジンは任意の適切な PL/SQL ブロックまたはサブプログラム
を入力として受け付けます。図 1-3 は、無名ブロックを処理する PL/SQL エンジンを示します。
PL/SQL エンジンはプロシージャ文のみを実行し、SQL 文を Oracle データベースの SQL エン
ジンに送信します。
図 1-3 PL/SQL エンジン
Oracle データベース・サーバー
通常、Oracle データベース・サーバーは PL/SQL ブロックおよびサブプログラムを処理しま
す。
無名ブロック
無名 PL/SQL ブロックは、SQL*Plus や Enterprise Manager などの対話型ツールに送信するか、
または Oracle プリコンパイラや OCI のプログラムに埋め込むことができます。プログラムは、
実行時にこれらのブロックを Oracle データベースに送信します。Oracle データベースでは、こ
れらのブロックがコンパイルおよび実行されます。
ストアド・サブプログラム
サブプログラムは、いつでも実行できるように、コンパイルして Oracle データベースに格納で
きます。コンパイルされたサブプログラムは、ストアド・プロシージャまたはストアド・ファ
ンクションと呼ばれるスキーマ・オブジェクトになり、そのデータベースに接続されている任
意の数のアプリケーションから参照できます。
SQL の CREATE PROCEDURE 文を使用すると、データベースに格納するスタンドアロン・プロ
シージャを作成できます。詳細は、
『Oracle Database SQL リファレンス』の「CREATE
PROCEDURE」を参照してください。SQL の CREATE FUNCTION 文を使用すると、Oracle デー
タベースに格納するスタンドアロン・ファンクションを作成できます。詳細は、
『Oracle
Database SQL リファレンス』の「CREATE FUNCTION」を参照してください。
サブプログラムは、コンパイルされた小型の形式で格納されます。コールされたサブプログラ
ムはすぐにロードされ、処理されます。サブプログラムは共有メモリー機能を使用するため、
複数のユーザーが実行する場合でも、メモリーにはサブプログラムのコピーが 1 つのみロード
されます。
1-18
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL アーキテクチャ
パッケージ内で定義されたストアド・サブプログラムは、パッケージ・サブプログラムと呼ば
れます。独立して定義されたものは、スタンドアロン・サブプログラムと呼ばれます。別のサ
ブプログラムや PL/SQL ブロック内でネストされたサブプログラムは、ローカル・サブプログ
ラムと呼ばれます。これは他のアプリケーションからは参照できず、囲みブロック内にのみ存
在します。
ストアド・サブプログラムは、モジュール構造を持ち、再利用可能な PL/SQL コードの重要な
構成要素です。Java の JAR ファイル、Perl のモジュール、C++ の共有ライブラリまたは Visual
Basic の DLL を使用する可能性がある場合は、常に PL/SQL のストアド・プロシージャ、スト
アド・ファンクションおよびパッケージを使用する必要があります。
ストアド・サブプログラムは、データベース・トリガー、別のストアド・サブプログラム、
Oracle プリコンパイラ、OCI アプリケーション、または対話形式で SQL*Plus や Enterprise
Manager からコールできます。また、Web サーバーを構成し、Web ページの HTML をストア
ド・サブプログラムによって生成することで、データの入力およびレポートの生成で使用する
Web インタフェースを簡単に作成できます。
例 1-18 では、CALL 文または BEGIN ...END ブロックを使用して、SQL*Plus から例 1-12 のスト
アド・サブプログラムをコールする方法を示します。
例 1-18 SQL*Plus からスタンドアロン・プロシージャをコールする方法
CALL award_bonus(179, 1000);
BEGIN
award_bonus(179, 10000);
END;
/
-- using named notation
BEGIN award_bonus(emp_id=>179, bonus=>10000); END;
/
BEGIN ..END ブロックの使用は、様々な場合に推奨されます。BEGIN ..END ブロックからのサブ
プログラムのコールでは、CALL 文がサポートしていない、パラメータの名前表記法または混合
表記法が利用できます。名前付きパラメータの詳細は、8-7 ページの「サブプログラムのパラ
メータの位置表記法、名前表記法または混合表記法」を参照してください。さらに、CALL 文を
使用すると、PL/SQL サブプログラムでは処理されなかった「ORA-01403: データが見つかり
ません。
」エラーを除去できます。
PL/SQL プロシージャ・コールの例は、8-7 ページの例 8-5「位置表記法、名前表記法または混
合表記法でのサブプログラムのコール」および 7-8 ページの「パラメータとしてのスキーマ・
オブジェクト名の引渡し」を参照してください。CALL 文の使用の詳細は、『Oracle Database
SQL リファレンス』を参照してください。
データベース・トリガー
データベース・トリガーは、データベースの表、ビューまたはイベントに対応付けられている
ストアド・サブプログラムです。トリガーは、複数のイベントが発生した際に、1 回または複
数回(INSERT 文、UPDATE 文または DELETE 文の影響を受けた行ごとに 1 回)コールできま
す。また、イベントの発生後にトリガーをコールして、イベントを記録したり、事後処理を実
行することができます。または、イベントが発生する前にトリガーをコールして、誤操作を回
避したり、新しいデータをビジネス・ルールに準拠するように修正することができます。例
1-19 では、1-10 ページの例 1-7 の処理のように、表レベルのトリガーは employees 表の給与
が更新されるたびに起動されます。更新のたびに、トリガーはレコードを emp_audit 表に書
き込みます。
例 1-19 データベース・トリガーの作成
CREATE TABLE emp_audit ( emp_audit_id NUMBER(6), up_date DATE,
new_sal NUMBER(8,2), old_sal NUMBER(8,2) );
CREATE OR REPLACE TRIGGER audit_sal
AFTER UPDATE OF salary ON employees FOR EACH ROW
PL/SQL の概要
1-19
PL/SQL アーキテクチャ
BEGIN
-- bind variables are used here for values
INSERT INTO emp_audit VALUES( :old.employee_id, SYSDATE,
:new.salary, :old.salary );
END;
/
トリガーの実行部には、プロシージャ文のみでなく、SQL データ操作文も含めることができま
す。表レベルのトリガー以外にも、ビュー用の INSTEAD OF トリガーとスキーマ用のシステ
ム・イベントのトリガーがあります。トリガーの詳細は、
『Oracle Database 概要』および
『Oracle Database アプリケーション開発者ガイド - 基礎編』を参照してください。SQL の
CREATE TRIGGER 文の詳細は、『Oracle Database SQL リファレンス』を参照してください。
Oracle のツール製品
PL/SQL エンジンを持つアプリケーション開発用 Oracle のツール製品は、PL/SQL ブロックと
サブプログラムを処理できます。Oracle のツール製品はブロックをローカルの PL/SQL エンジ
ンに渡します。エンジンはすべてのプロシージャ文をアプリケーション内で実行し、SQL 文の
みをデータベースに送信します。大部分の処理は、データベース・サーバー上ではなくアプリ
ケーション内で行われます。ブロックに SQL 文がない場合、ブロック全体がアプリケーション
で実行されます。アプリケーションが条件制御や反復制御を活用できる場合は、この機能が特
に便利です。
Oracle Forms アプリケーションは、フィールド・エントリの値のテストや単純な計算のために
SQL 文を頻繁に使用します。この場合、かわりに PL/SQL を使用すると、データベースへの
コールを回避できます。PL/SQL ファンクションを使用して、フィールド・エントリを操作す
ることもできます。
1-20
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
2
PL/SQL 言語の基礎
前の章では、PL/SQL の概要を示しました。この章では、PL/SQL を詳細に説明します。他の
プログラミング言語と同様に、PL/SQL にはキャラクタ・セット、予約語、デリミタ、データ
型および一定の構文規則があります。
この章の項目は、次のとおりです。
■
キャラクタ・セットおよび字句単位
■
宣言
■
PL/SQL のネーミング規則
■
PL/SQL の識別子の有効範囲と可視性
■
変数への値の代入
■
PL/SQL の式および比較
■
条件付きコンパイル
■
PL/SQL を使用して Web アプリケーションおよび Server Pages を作成する方法
■
PL/SQL の組込みファンクションのまとめ
PL/SQL 言語の基礎
2-1
キャラクタ・セットおよび字句単位
キャラクタ・セットおよび字句単位
PL/SQL プログラムは、特定のキャラクタ・セットを使用したテキストとして作成されます。
■
大文字と小文字の英字、A ~ Z および a ~ z
■
数字、0 ~ 9
■
記号、( ) + - * / < > = ! ~ ^ ; : . ' @ % , " # $ & _ | { } ? [ ]
■
タブ、空白および改行
PL/SQL キーワードは大 / 小文字が区別されないため、文字列リテラルと文字リテラルの中を
除き、小文字の英字は対応する大文字の英字と等価です。
PL/SQL テキストの行には字句単位と呼ばれる文字のグループがあります。
■
デリミタ(単純記号とコンパウンド記号)
■
識別子(予約語を含む)
■
リテラル
■
コメント
わかりやすくするために、字句単位は空白で区切ることができます。実際には、隣接する識別
子は、空白またはデリミタで区切る必要があります。次の行は予約語の END と IF が結合され
ているため、不正です。
IF x > y THEN high := x; ENDIF; -- 不正です。END IF とする必要があります。
文字列リテラルとコメントの場合を除き、字句単位の中に空白を埋め込むことはできません。
たとえば、次の行は代入を表すコンパウンド記号(:=)が分かれているため、不正です。
count : = count + 1; -- 不正です。 := とする必要があります。
構造を示すために、改行で行を分けたり、空白またはタブで行にインデントを付けることがで
きます。次に示す最初の IF 文は、このような方法で形式を整えることによってより見やすく
できます。
IF x>y THEN max:=x;ELSE max:=y;END IF;
次の文のほうがより見やすくなります。
IF x > y THEN
max := x;
ELSE
max := y;
END IF;
デリミタ
デリミタは、PL/SQL にとって特別な意味を持つ単純記号またはコンパウンド記号です。たと
えば、デリミタを使用して加算や減算などの算術演算を表現できます。表 2-1 に、PL/SQL の
デリミタのリストを示します。
表 2-1 PL/SQL のデリミタ
2-2
記号
意味
+
加算演算子
%
属性のインジケータ
'
文字列のデリミタ
.
構成要素の選択子
/
除算演算子
(
式またはリストのデリミタ
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
キャラクタ・セットおよび字句単位
表 2-1 PL/SQL のデリミタ(続き)
記号
意味
)
式またはリストのデリミタ
:
ホスト変数のインジケータ
,
項目のセパレータ
*
乗算演算子
"
二重引用符で囲んだ識別子のデリミタ
=
関係演算子
<
関係演算子
>
関係演算子
@
リモート・アクセスのインジケータ
;
文の終了記号
-
減算 / 否定演算子
:=
代入演算子
=>
結合演算子
||
連結演算子
**
指数演算子
<<
ラベルのデリミタ(開始)
>>
ラベルのデリミタ(終了)
/*
複数行コメントのデリミタ(開始)
*/
複数行コメントのデリミタ(終了)
..
範囲演算子
<>
関係演算子
!=
関係演算子
~=
関係演算子
^=
関係演算子
<=
関係演算子
>=
関係演算子
--
単一行コメントのインジケータ
識別子
識別子を使用して、定数、変数、例外、カーソル、カーソル変数、サブプログラム、パッケー
ジなどの PL/SQL プログラムに名前を付けることができます。次に識別子の例をいくつか示し
ます。
X
t2
phone#
credit_limit
LastName
oracle$number
PL/SQL 言語の基礎
2-3
キャラクタ・セットおよび字句単位
識別子は英字 1 文字でもかまいませんが、後に英字、数字、ドル記号、アンダースコアおよび
シャープ記号を続けることもできます。次の例のように、ハイフン、スラッシュ、空白などの
文字は使用できません。
mine&yours: アンパサンドがあるため使用不可
debit-amount: ハイフンがあるため使用不可
on/off: スラッシュがあるため使用不可
user id: スペースがあるため使用不可
ドル記号、アンダースコアおよびシャープ記号を隣接して使用したり、先頭以外の位置で使用
することができます。
money$$$tree
SN##
try_again_
識別子では大文字と小文字が使用でき、両者の混用もできます。PL/SQL では、文字列リテラ
ルと文字リテラルの中を除いて、大 / 小文字は区別されません。したがって、2 つの識別子の
違いが英字の大 / 小文字の違いのみであれば、PL/SQL は同じ識別子とみなします。
lastname
LastName -- lastname と同じ
LASTNAME -- lastname および LastName と同じ
識別子のサイズは 30 文字以内にする必要があります。ドル記号、アンダースコアおよびシャー
プ記号を含むすべての文字が意味を持ちます。たとえば、PL/SQL は、次の 2 つの識別子を別
のものとして扱います。
lastname
last_name
識別子は、内容がわかりやすいものにしてください。cpm のようなあいまいな名前は避けます。
かわりに、cost_per_thousand のように意味のわかりやすい名前を使用してください。
予約語
識別子には、PL/SQL に対して構文上の特別な意味を持つ予約語があります。たとえば、
BEGIN と END は予約語です。一般に、予約語は区別しやすくするために大文字で書かれていま
す。
予約語を再定義しようとするとコンパイル・エラーが発生します。ただし、識別子の中に予約
語を埋め込むことはできます。次に例を示します。
DECLARE
-- end BOOLEAN; the use of "end" is not allowed; causes compilation error
end_of_game BOOLEAN; -- allowed
予約語の他に、PL/SQL で特別な意味を持つキーワードがあります。PL/SQL のキーワードを
識別子に使用することはできますが、お薦めしません。PL/SQL の予約語とキーワードのリス
トは、D-1 ページの表 D-1「PL/SQL の予約語」および D-2 ページの表 D-2「PL/SQL のキー
ワード」を参照してください。
事前定義の識別子
例外 INVALID_NUMBER など、パッケージ STANDARD でグローバルに宣言されている識別子
は、再宣言できます。ただし、事前定義の識別子を再宣言すると、ローカルな宣言がグローバ
ルな宣言をオーバーライドするためエラーが発生しやすくなります。
2-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
キャラクタ・セットおよび字句単位
二重引用符で囲んだ識別子
柔軟性を高めるために、PL/SQL では識別子を二重引用符で囲むことができます。通常は、こ
のようにする必要はありませんが、ときには便利な場合もあります。二重引用符で囲んだ識別
子には、空白など、二重引用符を除くすべての印字可能文字を任意に並べて入れることができ
ます。したがって、次の識別子は有効です。
"X+Y"
"last name"
"on/off switch"
"employee(s)"
"*** header info ***"
二重引用符で囲んだ識別子の最大サイズは、二重引用符を数えずに 30 字です。PL/SQL の予約
語を二重引用符で囲んだ識別子として使用することもできますが、それは好ましくないプログ
ラミング習慣です。
リテラル
リテラルは、識別子によって表現する必要がない明示的な数値、文字、文字列またはブール値
です。例として、数値リテラル 147 やブール・リテラル FALSE があります。PL/SQL のデー
タ型の詳細は、3-2 ページの「事前定義された PL/SQL データ型の概要」を参照してください。
数値リテラル
算術式では、整数と実数の 2 種類の数値リテラルを使用できます。整数リテラルは、小数点を
持たず、必要に応じて符号を付けた整数です。次に例を示します。
030
6
-14
0
+32767
実数リテラルとは、小数点を持ち、必要に応じて符号を付けた整数または小数です。次に例を
示します。
6.6667
0.0
-12.0
3.14159
+8300.00
.5
25.
PL/SQL では、12.0 や 25. などの数字は、整数値がある場合でも実数とみなします。
数字のみで構成される -2147483648 ~ 2147483647 の範囲の数値リテラルの値は、
PLS_INTEGER データ型です。それ以外の数値リテラルは、NUMBER データ型です。数値のみ
で構成されているリテラル値の後に f または d を追加して、それぞれ BINARY_FLOAT または
BINARY_TABLE を指定できます。データ型のプロパティは、3-2 ページの「PL/SQL の数値型」
を参照してください。
数値リテラルはドル記号やカンマを含むことはできませんが、科学表記法で書くことができま
す。数字の後に E(または e)を付けて、必要な場合は符号付き整数を続けます。次に例を示
します。
2E5
1.0E-7
3.14159e0
-1E38
-9.5e-3
E は、10 の累乗を意味します。次の例で示すように、E の前の数に、E の後の数の 10 の累乗を
掛けます(二重アスタリスク(**)は指数演算子です)
。
5E3 = 5 * 10**3 = 5 * 1000 = 5000
E の後の数値は、小数点が移動する桁数にも対応しています。上の例では、暗黙的な小数点が 3
桁右に移動しました。次の例では、3 桁左に移動します。
5E-3 = 5 * 10**-3 = 5 * 0.001 = 0.005
NUMBER リテラルの絶対値は、1.0E-130 ~ 1.0E126(ただし 1.0E126 を含まない)の範囲に
することができます。リテラルは、0 の場合もあります。例 2-1 を参照してください。有効範
囲外の結果の詳細は、3-3 ページの「NUMBER データ型」を参照してください。
PL/SQL 言語の基礎
2-5
キャラクタ・セットおよび字句単位
例 2-1 NUMBER リテラル
DECLARE
n NUMBER; -- declare n of NUMBER datatype
BEGIN
n := -9.999999E-130; -- valid
n := 9.999E125; -- valid
-- n := 10.0E125; -- invalid, "numeric overflow or underflow"
END;
/
例 2-2 に示すように、実数リテラルには、後ろに f または d 文字を付けて、BINARY_FLOAT ま
たは BINARY_DOUBLE 型を指定できます。
例 2-2 BINARY_FLOAT および BINARY_DOUBLE の使用
DECLARE
x BINARY_FLOAT := sqrt(2.0f); -- single-precision floating-point number
y BINARY_DOUBLE := sqrt(2.0d); -- double-precision floating-point number
BEGIN
NULL;
END;
/
文字リテラル
文字リテラルは引用符(アポストロフィ)で囲まれた 1 文字のことです。文字リテラルには、
PL/SQL キャラクタ・セットのすべての印刷可能文字(英字、数字、空白および特殊記号)を
使用できます。次に例を示します。
'Z'
'%'
'7'
' '
'z'
'('
文字リテラルの中で、PL/SQL は大 / 小文字を区別します。このため、PL/SQL はリテラル
'Z' と 'z' を違うものとして扱います。また文字リテラル '0' ~ '9' は、整数リテラルと同
じではありませんが、暗黙のうちに整数に変換されるため、算術式の中で使用できます。
文字列リテラル
文字値は、識別子によって表現することも、引用符(')で囲まれた 0(ゼロ)文字以上の並び
である文字列リテラルとして明示的に書くこともできます。NULL 文字列('')を除くすべての
文字列リテラルは、CHAR データ型に属します。
次に文字列リテラルの例を示します。
'Hello, world!'
'XYZ Corporation'
'10-NOV-91'
'He said "Life is like licking honey from a thorn."'
'$1,000,000'
文字列リテラルの中で、PL/SQL は大 / 小文字を区別します。たとえば、PL/SQL は次の 2 つ
のリテラルを異なるものとして扱います。
'baker'
'Baker'
文字列の中でアポストロフィを表現する場合は、引用符を 2 つ書きます。これは二重引用符を
書く場合とは違う意味を持ちます。
'I''m a string, you''re a string.'
2-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
キャラクタ・セットおよび字句単位
複雑なリテラル内で引用符を二重にする場合(特に SQL 文を表すもの)は、注意が必要です。
次の表記法を使用して、リテラルに独自のデリミタ文字を定義することもできます。デリミタ
文字には、文字列に含まれていない文字を使用します。これによって、リテラル内の引用符を
エスケープする必要がなくなります。
-- q'!...!' notation allows the of use single quotes
-- inside the literal
string_var := q'!I'm a string, you're a string.!';
デリミタ [、{、<、( を ]、}、>、) とペアで使用すると、'INVALID' の前後の引用符を二重にす
ることなく、SQL 文を表す文字列リテラルをサブプログラムに渡すことができます。
func_call(q'[select index_name from user_indexes where status =
'INVALID']');
NCHAR リテラルおよび NVARCHAR2 リテラルの前には、q ではなく nq を付けます。
where_clause := nq'#where col_value like '%é'#';
NCHAR データ型および Unicode 文字列の詳細は、『Oracle Database グローバリゼーション・サ
ポート・ガイド』を参照してください。
ブール・リテラル
ブール・リテラルとは、事前定義の値 TRUE、FALSE および NULL のことです。NULL は、存在
しない値、不明な値または適用できない値を示します。ブール・リテラルは値であり、文字列
ではないことに注意してください。たとえば、TRUE は数値 25 と同じように 1 つの値です。
日時リテラル
日時リテラルには、データ型に応じて様々な形式があります。次に例を示します。
例 2-3 日時リテラルの使用
DECLARE
d1 DATE := DATE '1998-12-25';
t1 TIMESTAMP := TIMESTAMP '1997-10-22 13:01:01';
t2 TIMESTAMP WITH TIME ZONE := TIMESTAMP '1997-01-31 09:26:56.66 +02:00';
-- Three years and two months
-- For greater precision, we would use the day-to-second interval
i1 INTERVAL YEAR TO MONTH := INTERVAL '3-2' YEAR TO MONTH;
-- Five days, four hours, three minutes, two and 1/100 seconds
i2 INTERVAL DAY TO SECOND := INTERVAL '5 04:03:02.01' DAY TO SECOND;
特定の時間隔値が YEAR TO MONTH であるか DAY TO SECOND であるかも指定できます。たと
えば、current_timestamp - current_timestamp では、デフォルトで INTERVAL DAY
TO SECOND 型の値が生成されます。時間隔の型は、次の形式で指定できます。
■
(interval_expression) DAY TO SECOND
■
(interval_expression) YEAR TO MONTH
日付および時刻型の構文の詳細は、
『Oracle Database SQL リファレンス』を参照してください。
日付 / 時刻算術の実行例は、
『Oracle Database アプリケーション開発者ガイド - 基礎編』を参
照してください。
コメント
PL/SQL コンパイラはコメントを無視しますが、ユーザーはコメントを無視しないでください。
プログラムにコメントを付け加えると、わかりやすくなり理解に役立ちます。一般に、コメン
トは各コード・セグメントの目的や使用方法を説明するために使用します。PL/SQL では、単
一行コメントと複数行コメントの 2 種類のコメント・スタイルがサポートされています。
PL/SQL 言語の基礎
2-7
キャラクタ・セットおよび字句単位
単一行コメント
単一行コメントは、行の中の任意の位置にある二重ハイフン(--)から始まり、その行の終わ
りまで続きます。次に例を示します。
例 2-4 単一行コメントの使用
DECLARE
howmany
NUMBER;
num_tables NUMBER;
BEGIN
-- begin processing
SELECT COUNT(*) INTO howmany FROM USER_OBJECTS
WHERE OBJECT_TYPE = 'TABLE'; -- Check number of tables
num_tables := howmany;
-- Compute some other value
END;
/
コメントは、行の末尾であれば文の途中でも使用できることに注意してください。
プログラムのテストやデバッグのときに、コード中の 1 行を無効にする場合があります。次の
例では、行をコメントにすることによってその行を無効にする方法を示します。
-- DELETE FROM employees WHERE comm_pct IS NULL;
複数行コメント
例 2-5 に示すように、複数行コメントは、スラッシュ - アスタリスク(/*)で始まってアスタ
リスク - スラッシュ(*/)で終わり、複数行にまたがることができます。複数行コメントのデ
リミタを使用すると、コードの一部分をすべてコメントにできます。
例 2-5 複数行コメントの使用
DECLARE
some_condition BOOLEAN;
pi NUMBER := 3.1415926;
radius NUMBER := 15;
area NUMBER;
BEGIN
/* Perform some simple tests and assignments */
IF 2 + 2 = 4 THEN
some_condition := TRUE; /* We expect this THEN to always be performed */
END IF;
/* The following line computes the area of a circle using pi, which is the
ratio between the circumference and diameter. After the area is computed,
the result is displayed. */
area := pi * radius**2;
DBMS_OUTPUT.PUT_LINE('The area is: ' || TO_CHAR(area));
END;
/
コメントの制限
コメントはネストできません。また、Oracle プリコンパイラ・プログラムが処理する PL/SQL
ブロックの中では、単一行コメントは使用できません。これは、行の終わりを示す文字が無視
され、単一行コメントが行の終わりでなくブロックの終わりまで続いてしまうためです。この
場合、かわりに /* */ 表記法を使用します。
2-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
宣言
宣言
プログラムは、変数と定数に値を格納します。プログラムの実行中に、変数の値を変更できま
すが、定数の値は変更できません。
変数および定数は、任意の PL/SQL ブロック、サブプログラムまたはパッケージの宣言部で宣
言できます。宣言によって、値の記憶域を割り当て、データ型を指定し、値を参照できるよう
に格納場所の名前を決めます。
次に例を示します。
DECLARE
birthday DATE;
emp_count SMALLINT := 0;
1 つ目の宣言で、DATE 型の変数の名前を決めています。2 つ目の宣言で、SMALLINT 型の変数
の名前を決め、代入演算子を使用して変数に初期値 0 を代入しています。
代入演算子の後に続く式は複雑なものでもかまいません。また、事前に初期化されている変数
を参照することもできます。
DECLARE
pi
REAL := 3.14159;
radius REAL := 1;
area REAL := pi * radius**2;
変数はデフォルトで NULL に初期化されます。そのため、変数宣言に「:= NULL」を含めると
冗長になります。
定数
定数を宣言するには、型指定子の前にキーワード CONSTANT が必要です。次の宣言では、
REAL 型の定数の名前を決め、定数に変更不可能な値 5000 を代入しています。定数は、宣言の
中で初期化する必要があります。それ以外の場合は、コンパイル・エラーが発生します。
DECLARE
credit_limit CONSTANT REAL := 5000.00;
max_days_in_year CONSTANT INTEGER := 366;
urban_legend CONSTANT BOOLEAN := FALSE;
DEFAULT の使用
変数の初期化には、代入演算子のかわりにキーワード DEFAULT も使用できます。次に例を示
します。
blood_type CHAR := 'O';
この宣言は、次のように書き換えることができます。
blood_type CHAR DEFAULT 'O';
標準的な値を持つ変数には、DEFAULT を使用します。特殊な値を持つ変数(カウンタやアキュ
ムレータ)には、代入演算子を使用します。次に例を示します。
hours_worked
INTEGER DEFAULT 40;
employee_count INTEGER := 0;
DEFAULT を使用して、サブプログラム・パラメータ、カーソル・パラメータおよびユーザー定
義レコードのフィールドを初期化することもできます。
PL/SQL 言語の基礎
2-9
宣言
NOT NULL の使用
宣言によって、初期値を代入する以外に NOT NULL 制約を付けることもできます。
DECLARE
acct_id INTEGER(4) NOT NULL := 9999;
NOT NULL と定義されている変数には NULL を代入できません。NULL を代入しようとすると、
PL/SQL は事前定義の例外 VALUE_ERROR を呼び出します。
NOT NULL 制約の後に初期化句を続ける必要があります。
PL/SQL では、サブタイプ NATURALN と POSITIVEN は、あらかじめ NOT NULL として定義さ
れています。これらの型の変数を宣言する場合は、NOT NULL 制約を省略できますが、初期化
句を含める必要があります。
%TYPE 属性の使用
%TYPE 属性は、変数またはデータベース列のデータ型を与えます。例 2-6 に示すように、
%TYPE で宣言した変数は、変数のデータ型の他にデフォルト値と制約を継承します。
例 2-6 変数のデータ型を持つ %TYPE の使用
DECLARE
credit PLS_INTEGER RANGE 1000..25000;
debit credit%TYPE;
v_name VARCHAR2(20);
name VARCHAR2(20) NOT NULL := 'JoHn SmItH';
-- If we increase the length of NAME, the other variables become longer also
upper_name name%TYPE := UPPER(name);
lower_name name%TYPE := LOWER(name);
init_name name%TYPE := INITCAP(name);
BEGIN
-- display inherited default values
DBMS_OUTPUT.PUT_LINE('name: ' || name || ' upper_name: ' || upper_name
|| ' lower_name: ' || lower_name || ' init_name: ' || init_name);
-- lower_name := 'jonathan henry smithson'; invalid, character string is too long
-- lower_name := NULL; invalid, NOT NULL CONSTRAINT
-- debit := 50000; invalid, value out of range
END;
/
%TYPE 属性を使用して宣言された変数は、データ型指定子を使用して宣言された変数と同じよ
うに扱われます。たとえば前述の宣言では、PL/SQL は debit を PLS_INTEGER 型の変数とし
て扱います。%TYPE 属性を使用した宣言には、初期化句も含めることができます。
%TYPE 属性は、データベース列を参照する変数を宣言する場合に特に便利です。次の例のよう
に、表や列を参照したり、所有者、表、列を参照することができます。
DECLARE
-- If the length of the column ever changes, this code
-- will use the new length automatically.
the_trigger user_triggers.trigger_name%TYPE;
table_name.column_name.%TYPE を使用して変数を宣言する場合、実際のデータ型、およ
び精度、位取り、長さなどの属性を知っておく必要はありません。列のデータベース定義が変
更された場合でも、変数のデータ型は実行時にそれに対応して変更されます。ただし、%TYPE
変数は NOT NULL、チェック制約またはデフォルト値などの列制約を継承しません。たとえば、
例 2-7 で、データベース列 empid が NOT NULL として定義されていても、変数 v_empid に
NULL を代入できます。
2-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
宣言
例 2-7 表の列での %TYPE の使用
CREATE TABLE employees_temp (empid NUMBER(6) NOT NULL PRIMARY KEY,
deptid NUMBER(6) CONSTRAINT check_deptid CHECK (deptid BETWEEN 100 AND 200),
deptname VARCHAR2(30) DEFAULT 'Sales');
DECLARE
v_empid
employees_temp.empid%TYPE;
v_deptid employees_temp.deptid%TYPE;
v_deptname employees_temp.deptname%TYPE;
BEGIN
v_empid := NULL; -- this works, null constraint is not inherited
-- v_empid := 10000002; -- invalid, number precision too large
v_deptid := 50; -- this works, check constraint is not inherited
-- the default value is not inherited in the following
DBMS_OUTPUT.PUT_LINE('v_deptname: ' || v_deptname);
END;
/
%TYPE を使用して宣言したサブタイプによって継承される列制約の詳細は、3-19 ページの「サ
ブタイプの制約およびデフォルト値」を参照してください。
%ROWTYPE 属性の使用
%ROWTYPE 属性は、表またはビューの中の行を表すレコード型を与えます。行の中の列と、そ
れに対応するレコード中のフィールドは、同じ名前と同じデータ型を持ちます。ただし、例 2-8
に示すように、%ROWTYPE レコードのフィールドは NOT NULL、チェック制約またはデフォル
ト値などの制約を継承しません。3-19 ページの例 3-11 を参照してください。
例 2-8 表の行での %ROWTYPE の使用
DECLARE
emprec
employees_temp%ROWTYPE;
BEGIN
emprec.empid := NULL; -- this works, null constraint is not inherited
-- emprec.empid := 10000002; -- invalid, number precision too large
emprec.deptid := 50; -- this works, check constraint is not inherited
-- the default value is not inherited in the following
DBMS_OUTPUT.PUT_LINE('emprec.deptname: ' || emprec.deptname);
END;
/
例 2-9 に示すように、レコードには、表から選択された行全体のデータを格納することも、
カーソルまたは強い型指定のカーソル変数でフェッチされた行全体のデータを格納することも
できます。
例 2-9 %ROWTYPE 属性の使用
DECLARE
-- %ROWTYPE can include all the columns in a table...
emp_rec employees%ROWTYPE;
-- ...or a subset of the columns, based on a cursor.
CURSOR c1 IS
SELECT department_id, department_name FROM departments;
dept_rec c1%ROWTYPE;
-- Could even make a %ROWTYPE with columns from multiple tables.
CURSOR c2 IS
SELECT employee_id, email, employees.manager_id, location_id
FROM employees, departments
WHERE employees.department_id = departments.department_id;
join_rec c2%ROWTYPE;
BEGIN
-- We know EMP_REC can hold a row from the EMPLOYEES table.
PL/SQL 言語の基礎
2-11
宣言
SELECT * INTO emp_rec FROM employees WHERE ROWNUM < 2;
-- We can refer to the fields of EMP_REC using column names
-- from the EMPLOYEES table.
IF emp_rec.department_id = 20 AND emp_rec.last_name = 'JOHNSON' THEN
emp_rec.salary := emp_rec.salary * 1.15;
END IF;
END;
/
集計代入
%ROWTYPE 宣言に初期化句を含めることはできませんが、レコード中のすべてのフィールドに
一度に値を代入する方法があります。レコードの宣言で同じ表またはカーソルが参照されてい
る場合は、あるレコードを別のレコードに代入できます。例 2-10 に、可能なレコードの代入を
示します。
例 2-10 %ROWTYPE 宣言を使用したレコードへの値の代入
DECLARE
dept_rec1
dept_rec2
CURSOR c1
dept_rec3
BEGIN
dept_rec1
-- dept_rec2
-- dept_rec2
END;
/
departments%ROWTYPE;
departments%ROWTYPE;
IS SELECT department_id, location_id FROM departments;
c1%ROWTYPE;
:= dept_rec2; -- allowed
refers to a table, dept_rec3 refers to a cursor
:= dept_rec3; -- not allowed
次の例に示すように、SELECT 文または FETCH 文を使用して列の値のリストをレコードに代入
できます。列名の順番は、CREATE TABLE 文または CREATE VIEW 文で定義された順番である
必要があります。
DECLARE
dept_rec departments%ROWTYPE;
BEGIN
SELECT * INTO dept_rec FROM departments
WHERE department_id = 30 and ROWNUM < 2;
END;
/
ただし、レコード型のコンストラクタが存在しない場合は、代入文を使用して列の値のリスト
をレコードに代入できません。
エイリアシングの使用
%ROWTYPE 属性と関連のあるカーソルからフェッチされた選択リスト項目は、単純名を持つ必
要があります。また、選択リスト項目が式の場合は別名を持つ必要があります。例 2-11 では、
complete_name という別名を使用して 2 つの列の連結を表しています。
例 2-11 列名の別名の使用
BEGIN
-- We assign an alias (complete_name) to the expression value, because
-- it has no column name.
FOR item IN
( SELECT first_name || ' ' || last_name complete_name
FROM employees WHERE ROWNUM < 11 )
LOOP
-- Now we can refer to the field in the record using this alias.
DBMS_OUTPUT.PUT_LINE('Employee name: ' || item.complete_name);
END LOOP;
END;
/
2-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL のネーミング規則
宣言の制限
PL/SQL では前方参照ができません。宣言文などの他の文で変数または定数を参照するときは、
事前に宣言する必要があります。
PL/SQL ではサブプログラムの前方宣言が可能です。詳細は、8-5 ページの「ネストした
PL/SQL サブプログラムの宣言」を参照してください。
言語によっては、同一のデータ型の複数の変数の並びを一度に宣言できます。ただし、
PL/SQL ではそれができません。各変数を次のように別々に宣言する必要があります。
DECLARE
-- Multiple declarations not allowed.
-- i, j, k, l SMALLINT;
-- Instead, declare each separately.
i SMALLINT;
j SMALLINT;
-- To save space, you can declare more than one on a line.
k SMALLINT; l SMALLINT;
PL/SQL のネーミング規則
定数、変数、カーソル、カーソル変数、例外、プロシージャ、ファンクション、パッケージな
どの PL/SQL プログラム項目には、いずれも同じネーミング規則が適用されます。名前には単
純名、修飾名、リモート名または修飾リモート名があります。たとえば、プロシージャ名
raise_salary は次のように使用できます。
raise_salary(...); -- simple
emp_actions.raise_salary(...); -- qualified
raise_salary@newyork(...); -- remote
emp_actions.raise_salary@newyork(...); -- qualified and remote
1 番目の例ではプロシージャ名をそのまま使用しています。2 番目の例では、プロシージャが
emp_actions という名前のパッケージに格納されているため、ドット表記法を使用して名前
を修飾する必要があります。3 番目の例では、プロシージャがリモート・データベースに格納
されているため、リモート・アクセスのインジケータ(@)を使用してデータベース・リンク
newyork を参照しています。4 番目の例では、プロシージャ名を修飾し、データベース・リン
クの参照も行っています。
シノニム
シノニムを作成し、表、順序、ビュー、スタンドアロン・サブプログラム、パッケージ、オブ
ジェクト型などのリモート・スキーマ・オブジェクトに関する位置の透過性を提供できます。
ただし、サブプログラムやパッケージの中で宣言された項目については、シノニムを作成でき
ません。これには、定数、変数、カーソル、カーソル変数、例外およびパッケージ化されたサ
ブプログラムが該当します。
有効範囲
同じ有効範囲の中では、宣言されたすべての識別子が他と重複しないものである必要がありま
す。そのため、変数と定数はデータ型が異なる場合でも同じ名前を共有できません。例 2-12 で
は、2 番目の宣言は誤りです。
例 2-12 同じ有効範囲での識別子の重複によるエラー
DECLARE
valid_id BOOLEAN;
valid_id VARCHAR2(5); -- not allowed, duplicate identifier
BEGIN
-- The error occurs when the identifier is referenced,
-- not in the declaration part.
valid_id := FALSE; -- raises an error here
END;
/
PL/SQL 言語の基礎
2-13
PL/SQL のネーミング規則
識別子に適用される有効範囲規則については、2-15 ページの「PL/SQL の識別子の有効範囲と
可視性」を参照してください。
大 / 小文字の区別
定数、変数およびパラメータの名前では、すべての識別子と同様に大 / 小文字が区別されませ
ん。たとえば、PL/SQL は次の名前を同じものとみなします。
例 2-13 識別子の大 / 小文字の区別
DECLARE
zip_code INTEGER;
Zip_Code INTEGER; -- duplicate identifier, despite Z/z case difference
BEGIN
zip_code := 90120; -- raises error here because of duplicate identifiers
END;
/
名前解決
潜在的にあいまいな SQL 文では、データベース列の名前はローカル変数名および仮パラメータ
名より優先されます。たとえば、同じ名前の変数と列の両方が 1 つの WHERE 句で使用された場
合、SQL は両方とも列を参照するとみなします。
例 2-14 に示すように、重複を避けるため、ローカル変数と仮パラメータの名前に接頭辞を追加
するか、ブロック・ラベルを使用して参照を修飾します。
例 2-14 名前解決でのブロック・ラベルの使用
CREATE TABLE employees2 AS SELECT last_name FROM employees;
<<main>>
DECLARE
last_name VARCHAR2(10) := 'King';
v_last_name VARCHAR2(10) := 'King';
BEGIN
-- deletes everyone, because both LAST_NAMEs refer to the column
DELETE FROM employees2 WHERE last_name = last_name;
DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows.');
ROLLBACK;
-- OK, column and variable have different names
DELETE FROM employees2 WHERE last_name = v_last_name;
DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows.');
ROLLBACK;
-- OK, block name specifies that 2nd last_name is a variable
DELETE FROM employees2 WHERE last_name = main.last_name;
DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows.');
ROLLBACK;
END;
/
例 2-15 では、ローカル変数と仮パラメータへの参照を、サブプログラム名を使用して修飾して
います。
例 2-15 名前解決でのサブプログラムの使用
DECLARE
FUNCTION dept_name (department_id IN NUMBER)
RETURN departments.department_name%TYPE
IS
department_name departments.department_name%TYPE;
BEGIN
-- DEPT_NAME.department_name specifies the local variable
-- instead of the table column
SELECT department_name INTO dept_name.department_name
2-14
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の識別子の有効範囲と可視性
FROM departments
WHERE department_id = dept_name.department_id;
RETURN department_name;
END;
BEGIN
FOR item IN (SELECT department_id FROM departments)
LOOP
DBMS_OUTPUT.PUT_LINE('Department: ' || dept_name(item.department_id));
END LOOP;
END;
/
名前解決の詳細は、付録 B「PL/SQL での識別子名の解決」を参照してください。
PL/SQL の識別子の有効範囲と可視性
識別子に対する参照は、その有効範囲と可視性に従って解決されます。識別子の有効範囲とは、
その識別子の参照が可能な、プログラム・ユニット(ブロック、サブプログラムまたはパッ
ケージ)の領域です。識別子は、未修飾の名前で識別子を参照できる領域からのみ、可視の状
態になっています。図 2-1 は、x という名前の変数の有効範囲と可視性を示します。この変数
は囲みブロックで宣言されてからサブブロックで再宣言されます。
ある PL/SQL ブロックで宣言された識別子は、そのブロックに対してはローカルであり、その
サブブロックすべてに対してはグローバルです。グローバル識別子がサブブロックの中で再宣
言されると、両方の識別子が有効範囲内にあることになります。ただし、サブブロックの中で
グローバル識別子を参照する場合は修飾名が必要になるため、可視であるのはローカル識別子
のみです。
同じブロックで識別子を 2 度宣言できませんが、同じ識別子を 2 つの異なるブロックで宣言で
きます。識別子が表す 2 つの項目は区別され、一方を変更しても他方には影響がありません。
ただし、あるブロックから、同じレベルの他のブロックで宣言されている識別子への参照はで
きません。そのような識別子は、そのブロックに対してローカルでもグローバルでもないため
です。
図 2-1 有効範囲と可視性
PL/SQL 言語の基礎
2-15
PL/SQL の識別子の有効範囲と可視性
例 2-16 に、有効範囲規則を示します。あるサブブロックで宣言された識別子は、別のサブブ
ロックで参照できないことに注意してください。これは、あるブロックと同じレベルでネスト
された他のブロックで宣言された識別子を、そのブロックで参照できないためです。
例 2-16 有効範囲規則
DECLARE
a CHAR;
b REAL;
BEGIN
-- identifiers available here: a
DECLARE
a INTEGER;
c REAL;
BEGIN
NULL; -- identifiers available
END;
DECLARE
d REAL;
BEGIN
NULL; -- identifiers available
END;
-- identifiers available here: a
END;
/
(CHAR), b
here: a (INTEGER), b, c
here: a (CHAR), b, d
(CHAR), b
グローバル識別子はサブブロックで再宣言でき、その場合はローカルな宣言が優先され、サブ
ブロックでは、修飾名を使用しないとグローバル識別子を参照できません。例 2-17 に示すよう
に、外側のブロックのラベルを修飾子として使用できます。
例 2-17 識別子でのラベル修飾子の使用
<<outer>>
DECLARE
birthdate DATE := '09-AUG-70';
BEGIN
DECLARE
birthdate DATE;
BEGIN
birthdate := '29-SEP-70';
IF birthdate = outer.birthdate THEN
DBMS_OUTPUT.PUT_LINE ('Same Birthday');
ELSE
DBMS_OUTPUT.PUT_LINE ('Different Birthday');
END IF;
END;
END;
/
また、例 2-18 に示すように、外側のサブプログラムの名前を修飾子として使用できます。
例 2-18 識別子でのサブプログラム修飾子の使用
CREATE OR REPLACE PROCEDURE check_credit(limit NUMBER) AS
rating NUMBER := 3;
FUNCTION check_rating RETURN BOOLEAN IS
rating
NUMBER := 1;
over_limit
BOOLEAN;
BEGIN
IF check_credit.rating <= limit THEN
over_limit := FALSE;
ELSE
rating := limit;
2-16
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の識別子の有効範囲と可視性
over_limit := TRUE;
END IF;
RETURN over_limit;
END check_rating;
BEGIN
IF check_rating THEN
DBMS_OUTPUT.PUT_LINE( 'Credit rating over limit (' || TO_CHAR(limit)
|| ').' || ' Rating: ' || TO_CHAR(rating));
ELSE
DBMS_OUTPUT.PUT_LINE( 'Credit rating OK. ' || 'Rating: '
|| TO_CHAR(rating) );
END IF;
END;
/
CALL check_credit(1);
ただし、同一の有効範囲内でラベルとサブプログラムを同じ名前にすることはできません。例
2-19 に示すように、ラベルを重複して使用しないようにしてください。
例 2-19 複数の重複したラベルを使用する PL/SQL ブロック
<<compute_ratio>>
<<another_label>>
DECLARE
numerator NUMBER := 22;
denominator NUMBER := 7;
the_ratio NUMBER;
BEGIN
<<inner_label>>
<<another_label>>
DECLARE
denominator NUMBER := 0;
BEGIN
-- first use the denominator value = 7 from global DECLARE
-- to compute a rough value of pi
the_ratio := numerator/compute_ratio.denominator;
DBMS_OUTPUT.PUT_LINE('Ratio = ' || the_ratio);
-- now use the local denominator value = 0 to raise an exception
-- inner_label is not needed but used for clarification
the_ratio := numerator/inner_label.denominator;
DBMS_OUTPUT.PUT_LINE('Ratio = ' || the_ratio);
-- if you use a duplicate label, you might get errors
-- or unpredictable results
the_ratio := numerator/another_label.denominator;
DBMS_OUTPUT.PUT_LINE('Ratio = ' || the_ratio);
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('Divide-by-zero error: can''t divide '
|| numerator || ' by ' || denominator);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Unexpected error.');
END inner_label;
END compute_ratio;
/
PL/SQL 言語の基礎
2-17
変数への値の代入
変数への値の代入
変数に値を代入する場合は、代入文を使用します。たとえば、次の文では変数 bonus の古い値
を上書きして、新しい値を代入します。
bonus := salary * 0.15;
変数と定数は、ブロックまたはサブプログラムに入るたびに初期化されます。デフォルトでは、
変数は NULL に初期化されます。例 2-20 に示すように、変数を明示的に初期化しないかぎり、
その値は未定義(NULL)です。
例 2-20 変数と定数の初期化
DECLARE
counter INTEGER;
BEGIN
-- COUNTER is initially NULL, so 'COUNTER + 1' is also null.
counter := counter + 1;
IF counter IS NULL THEN
DBMS_OUTPUT.PUT_LINE('COUNTER is NULL not 1.');
END IF;
END;
/
予期しない結果を避けるため、値を代入する前に変数を参照しないでください。代入演算子の
後に続く式は、複雑なものでもかまいませんが、そのデータ型は変数のデータ型と同じか、ま
たは変数のデータ型に変換できるものである必要があります。
ブール値の代入
例 2-21 に示すように、ブール変数に代入できるのは、値 TRUE、FALSE および NULL のみです。
関係演算子を使用して、これらのリテラル値、または比較などの式を代入できます。
例 2-21 ブール値の代入
DECLARE
done BOOLEAN; -- DONE is initially NULL
counter NUMBER := 0;
BEGIN
done := FALSE; -- Assign a literal value
WHILE done != TRUE -- Compare to a literal value
LOOP
counter := counter + 1;
done := (counter > 500); -- If counter > 500, DONE = TRUE
END LOOP;
END;
/
SQL 問合せ結果の PL/SQL 変数への代入
SELECT 文を使用しても変数に値を代入できます。例 2-22 に示すように、選択リストの項目ご
とに、対応する型互換の変数が INTO リストに存在している必要があります。
例 2-22 変数への問合せ結果の代入
DECLARE
emp_id employees.employee_id%TYPE := 100;
emp_name employees.last_name%TYPE;
wages
NUMBER(7,2);
BEGIN
SELECT last_name, salary + (salary * nvl(commission_pct,0))
2-18
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の式および比較
INTO emp_name, wages FROM employees
WHERE employee_id = emp_id;
DBMS_OUTPUT.PUT_LINE('Employee ' || emp_name || ' might make ' || wages);
END;
/
SQL には BOOLEAN 型がないため、列の値を選択して BOOLEAN 変数に代入することはできませ
ん。変数の値が未定義の場合を含め、DML 文での変数の代入の詳細は、6-2 ページの「データ
操作」を参照してください。
PL/SQL の式および比較
式はオペランドと演算子を使用して作成します。オペランドとは、変数、定数、リテラルまた
はファンクション・コールのことで、式の中の値はオペランドを使用して表現します。単純な
算術式の例を次に示します。
-X / 2 + 3
否定演算子(-)のような単項演算子は、1 つのオペランドに対して作用します。除算演算子
(/)のようなバイナリ演算子は、2 つのオペランドに対して作用します。PL/SQL には 3 項演
算子はありません。
最も単純な式は変数 1 つで構成され、その変数の値が式の値になります。PL/SQL は、演算子
が指定する方法でオペランドの値を組み合せて、式を評価します。式は常に 1 つの値を戻しま
す。PL/SQL は、式の内容と、式が使用されているコンテキストに基づいてこの値のデータ型
を決定します。
演算子の優先順位
式の中の演算は、優先順位に応じて特定の順序で実行されます。表 2-2 に、デフォルトでの演
算の順序を上から順に示します。
表 2-2 演算の順序
演算子
演算
**
指数
+, -
恒等、否定
*, /
乗算、除算
+, -, ||
加算、減算、連結
=、<、>、<=、>=、<>、!=、
~=、^=、IS NULL、LIKE、
BETWEEN、IN
比較
NOT
論理否定
AND
論理積
OR
論理和
優先順位が高い演算子が先に適用されます。たとえば、次の 2 つの式の結果はどちらも 8 にな
ります。これは、除算が加算よりも優先順位が高いためです。同じ優先順位の演算子は、特に
順序を考慮せずに適用されます。
5 + 12 / 4
12 / 4 + 5
カッコを使用すると、評価の順序を制御できます。たとえば、次の式ではカッコで演算子のデ
フォルトの優先順位が上書きされるため、式の結果は 11 ではなく 7 になります。
(8 + 6) / 2
PL/SQL 言語の基礎
2-19
PL/SQL の式および比較
次の例では、最も深くネストされた副式が必ず最初に評価されるため、除算の前に減算が実行
されます。
100 + (20 / 5 + (7 - 3))
次の例のように、カッコが不要な場合でも、わかりやすくするために自由にカッコを使用でき
ます。
(salary * 0.05) + (commission * 0.25)
論理演算子
論理演算子 AND、OR および NOT は、表 2-3 に示す 3 値論理に従います。AND と OR はバイナリ
演算子、NOT は単項演算子です。
表 2-3 論理真理値表
x
y
x AND y
x OR y
NOT x
TRUE
TRUE
TRUE
TRUE
FALSE
TRUE
FALSE
FALSE
TRUE
FALSE
TRUE
NULL
NULL
TRUE
FALSE
FALSE
TRUE
FALSE
TRUE
TRUE
FALSE
FALSE
FALSE
FALSE
TRUE
FALSE
NULL
FALSE
NULL
TRUE
NULL
TRUE
NULL
TRUE
NULL
NULL
FALSE
FALSE
NULL
NULL
NULL
NULL
NULL
NULL
NULL
真理値表からわかるように、AND は、オペランドの両方が TRUE の場合にのみ TRUE を戻しま
す。一方、OR は、オペランドの片方が TRUE ならば TRUE を戻します。NOT はオペランドの反
対の値(論理否定)を戻します。たとえば、NOT TRUE は FALSE を戻します。
NULL は値を持たないため、NOT NULL は NULL を戻します。NULL を伴う式で予測不可能な
結果が発生しないように注意してください。2-26 ページの「比較文と条件文での NULL の扱
い」を参照してください。
評価の順序
カッコを使用して評価の順序を指定しない場合は、演算子の優先順位によって順序が決定され
ます。次の式を比べてみてください。
NOT (valid AND done)
|
NOT valid AND done
ブール変数 valid と done がどちらも値 FALSE を持つ場合、1 番目の式の結果は TRUE になり
ます。ただし、2 番目の式では NOT が AND より優先されるため、結果は FALSE になります。
したがって、2 番目の式は次の式と等価になります。
(NOT valid) AND done
次の例では、valid の値が FALSE である場合、done の値とは関係なく式全体の結果が FALSE
になることに注意してください。
valid AND done
同様に、次の例では、valid の値が TRUE である場合に、done の値とは関係なく式全体の結
果が TRUE になります。
valid OR done
2-20
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の式および比較
短絡評価
論理式を評価するときに、PL/SQL では短絡評価を使用します。これによって、PL/SQL は結
果が判別できた時点でただちに式の評価を停止します。そのため、評価を続ければエラーにな
るような式でも書くことができます。例 2-23 の OR 式で考えてみます。
例 2-23 短絡評価
DECLARE
on_hand INTEGER := 0;
on_order INTEGER := 100;
BEGIN
-- Does not cause divide-by-zero error; evaluation stops after first expression
IF (on_hand = 0) OR ((on_order / on_hand) < 5) THEN
DBMS_OUTPUT.PUT_LINE('On hand quantity is zero.');
END IF;
END;
/
on_hand の値が 0(ゼロ)の場合、左のオペランドは TRUE になるため、PL/SQL は右のオペ
ランドを評価しません。OR 演算子を適用する前に両方のオペランドを評価した場合には、右の
オペランドは 0 による除算エラーになります。
短絡評価は、PL/SQL の IF 文、CASE 文および CASE 式に適用されます。
比較演算子
比較演算子は式と式を比較します。結果は常に TRUE、FALSE、NULL のいずれかです。比較
演算子は、一般に、SQL DML 文の WHERE 句と、条件制御文の中で使用します。例 2-24 に、異
なる型の比較の例を示します。
例 2-24 比較演算子の使用
DECLARE
PROCEDURE assert(assertion VARCHAR2, truth BOOLEAN)
IS
BEGIN
IF truth IS NULL THEN
DBMS_OUTPUT.PUT_LINE('Assertion ' || assertion || ' is unknown (NULL)');
ELSIF truth = TRUE THEN
DBMS_OUTPUT.PUT_LINE('Assertion ' || assertion || ' is TRUE');
ELSE
DBMS_OUTPUT.PUT_LINE('Assertion ' || assertion || ' is FALSE');
END IF;
END;
BEGIN
assert('2 + 2 = 4', 2 + 2 = 4);
assert('10 > 1', 10 > 1);
assert('10 <= 1', 10 <= 1);
assert('5 BETWEEN 1 AND 10', 5 BETWEEN 1 AND 10);
assert('NULL != 0', NULL != 0);
assert('3 IN (1,3,5)', 3 IN (1,3,5));
assert('''A'' < ''Z''', 'A' < 'Z');
assert('''baseball'' LIKE ''%all%''', 'baseball' LIKE '%all%');
assert('''suit'' || ''case'' = ''suitcase''', 'suit' || 'case' = 'suitcase');
END;
/
PL/SQL 言語の基礎
2-21
PL/SQL の式および比較
関係演算子
次の表に、関係演算子とその意味を示します。
演算子
意味
=
等しい
<>, !=, ~=, ^=
等しくない
<
より小さい
>
より大きい
<=
より小さいか、等しい
>=
より大きいか、等しい
IS NULL 演算子
IS NULL 演算子は、オペランドが NULL の場合はブール値 TRUE を、NULL ではない場合は
FALSE を戻します。NULL が関係する比較は、常に結果が NULL になります。値が NULL かど
うかをテストするには、次の文を使用します。
IF variable IS NULL THEN ...
LIKE 演算子
LIKE 演算子を使用すると、文字、文字列または CLOB 値をパターンと比較できます。大 / 小文
字が区別されます。LIKE は、パターンが一致すればブール値 TRUE を、一致しなければ
FALSE を戻します。
LIKE を使用してパターンを比較するために、ワイルドカードと呼ばれる 2 つの特殊な目的の文
字を使用できます。アンダースコア(_)は 1 つの文字を表します。パーセント記号(%)は 0
(ゼロ)個以上の文字を表します。たとえば、last_name の値が 'JOHNSON' の場合、次の式
は TRUE になります。
last_name LIKE 'J%S_N'
パーセント記号やアンダースコアを検索するには、エスケープ文字を定義して、パーセント記
号またはアンダースコアの前にそのエスケープ文字を挿入します。次の例では、バックスラッ
シュをエスケープ文字として使用しているため、文字列中のパーセント記号はワイルドカード
としての役割は果たしません。
IF sale_sign LIKE '50\% off!'ESCAPE '\' THEN...
BETWEEN 演算子
BETWEEN 演算子は、ある値が、指定された範囲に含まれているかどうかをテストします。つま
り、
「下限以上、上限以下」という意味を持ちます。たとえば、次の式は FALSE です。
45 BETWEEN 38 AND 44
IN 演算子
IN 演算子は、セット・メンバーシップを調べます。集合のいずれかのメンバーと等しいかどう
かがテストされます。集合には NULL が含まれていてもかまいませんが、NULL は無視されま
す。たとえば、次の式は、値が集合に含まれるかどうかを調べます。
letter IN ('a','b','c')
この条件を反転する場合は注意が必要です。次の形式の式について考えます。
value NOT IN set
この式では、集合に NULL が含まれていると FALSE になります。
2-22
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の式および比較
連結演算子
連結演算子(||)は、文字列(CHAR、VARCHAR2、CLOB またはそれと同等の Unicode で使用
可能な型)を他の文字列に連結します。使用例を次に示します。
'suit' || 'case'
これは、次の行を戻します。
'suitcase'
両方のオペランドがデータ型 CHAR を持つ場合、連結演算子は CHAR 型の値を戻します。一方
のオペランドが CLOB 値を持つ場合、連結演算子は一時的な CLOB を戻します。それ以外の場
合は、VARCHAR2 型の値を戻します。
ブール式
PL/SQL では、SQL 文の中でもプロシージャ文の中でも、変数と定数を比較できます。これら
の比較はブール式と呼ばれ、関係演算子で区切られた単純式またはコンポジット式で構成され
ます。ブール式は一般に論理演算子 AND、OR および NOT で結合されます。ブール式の結果は
常に、TRUE、FALSE、NULL のいずれかになります。
SQL 文の中でブール式を使用して、表の中の文が影響を与える列を指定できます。プロシー
ジャ文では、条件制御の基盤としてブール式が使用されます。ブール式には、算術式、文字式
および日付式の 3 種類があります。
ブール算術式
関係演算子を使用して数値を比較し、等しいか等しくないかを判定できます。比較は量による
ものです。つまり、片方の数値がより大きな量を表す場合、その数値はより大きいとみなされ
ます。たとえば、次のような代入文があるとします。
number1 := 75;
number2 := 70;
次の式は TRUE になります。
number1 > number2
ブール文字式
文字値を比較して、等しいか等しくないかを判定できます。デフォルトでは、比較は文字列の
各バイトのバイナリ値に基づいて行われます。たとえば、次のような代入文があるとします。
string1 := 'Kathy';
string2 := 'Kathleen';
次の式は TRUE になります。
string1 > string2
初期化パラメータ NLS_COMP=ANSI を設定すると、NLS_SORT 初期化パラメータで識別される
照合順番を比較に使用できます。照合順番とは、特定の範囲の数値コードが個々の文字に対応
しているキャラクタ・セットの内部的な順序のことです。内部的な順番を表す数値が他方の文
字より大きい場合、その文字値はより大きいとみなされます。この種の文字が照合順番に使用
される場所については、言語ごとに規則が異なる場合があります。たとえば、アクセント記号
が付いた文字のソート順序は、バイナリ値が同じであってもデータベース・キャラクタ・セッ
トに応じて異なることがあります。
PL/SQL 言語の基礎
2-23
PL/SQL の式および比較
NLS_SORT パラメータの値によっては、大 / 小文字およびアクセント記号の有無を区別しない
比較を実行できます。大 / 小文字を区別しない比較では、オペランドの文字の大 / 小文字が異
なる場合でも TRUE が戻されます。アクセント記号の有無を区別しない比較は、大 / 小文字を
区別せず、オペランドのアクセント記号またはデリミタ文字が異なる場合でも TRUE が戻され
ます。たとえば、大 / 小文字を区別しない比較では、'True' と 'TRUE' の文字値は同じであ
るとみなされ、'Cooperate'、'Co-Operate' および 'co ・ erate' の文字値もすべて同じ
であるとみなされます。大 / 小文字を区別せずに比較するには、NLS_SORT パラメータの通常
の値の末尾に _CI を付けます。アクセント記号の有無を区別せずに比較するには、NLS_SORT
の値の末尾に _AI を付けます。
文字値を比較する場合には、ベース型 CHAR と VARCHAR2 の間にある意味上の違いを考慮する
必要があります。詳細は、3-22 ページの「CHAR と VARCHAR2 のデータ型の違い」を参照し
てください。
多くの型は文字型に変換できます。たとえば、CLOB 変数を使用して比較、代入および他の文字
操作を実行できます。実行可能な変換の詳細は、3-5 ページの「PL/SQL の文字型と文字列型」
を参照してください。
ブール日付式
日付も比較できます。比較は時系列によってなされます。つまり、片方の日付がより新しけれ
ば、その日付はより大きいとみなされます。たとえば、次のような代入文があるとします。
date1 := '01-JAN-91';
date2 := '31-DEC-90';
次の式は TRUE になります。
date1 > date2
PL/SQL ブール式のガイドライン
一般に、実数を比較して等しいかどうかを判定することはお薦めしません。実数は近似値とし
て格納されます。たとえば、次のような IF 条件は TRUE にならない可能性があります。
DECLARE
fraction BINARY_FLOAT := 1/3;
BEGIN
IF fraction = 11/33 THEN
DBMS_OUTPUT.PUT_LINE('Fractions are equal (luckily!)');
END IF;
END;
/
比較する場合は、カッコを使用することをお薦めします。たとえば次の式で、100 < tax は
ブール値になりますが、これは数値 500 と比較できないため、この式は無効です。
100 < tax < 500 -- 無効
これをデバッグすれば、次の式になります。
(100 < tax) AND (tax < 500)
ブール変数はそれ自身が TRUE または FALSE です。変数をリテラル値の TRUE、FALSE と比較
するのではなく、単に変数を条件テストに使用できます。例 2-25 では、ループはすべて等価で
す。
例 2-25 条件テストでのブール変数の使用
DECLARE
done BOOLEAN ;
BEGIN
-- Each WHILE loop is equivalent
done := FALSE;
WHILE done = FALSE
LOOP
2-24
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の式および比較
done := TRUE;
END LOOP;
done := FALSE;
WHILE NOT (done = TRUE)
LOOP
done := TRUE;
END LOOP;
done := FALSE;
WHILE NOT done
LOOP
done := TRUE;
END LOOP;
END;
/
CLOB 値を比較演算子または LIKE や BETWEEN などのファンクションとともに使用すると、一
時的な LOB が作成されます。一時表領域がこのような一時的な LOB を処理できる大きさかど
うかを確認する必要があります。
CASE 式
CASE 文では、単純な式と検索式の 2 種類の式が使用されます。これらの式は、その式が使用
される CASE 文の種類に対応しています。4-4 ページの「CASE 文の使用」を参照してくださ
い。
単純な CASE 式
単純な CASE 式は、1 つ以上の選択肢から結果を選択して戻します。CASE 式が複数の行にわた
るブロックを含む場合でも、CASE 式は代入やプロシージャ・コールなどの大きい文の一部を
構成する 1 つの式です。CASE 式は選択子を使用します。選択子は、その値によって戻す代替ア
クションが決まる式です。
CASE 式の書式は、例 2-26 に示すとおりです。選択子(grade)の後に 1 つ以上の WHEN 句が
あり、各句が順番にチェックされます。選択子の値によって、どの句が評価されるかが決定さ
れます。選択子の値と最初に一致した WHEN 句によって結果値が決定され、後続の WHEN 句は
評価されません。一致する句がない場合は、オプションの ELSE 句が実行されます。
例 2-26 CASE 文での WHEN 句の使用
DECLARE
grade CHAR(1) := 'B';
appraisal VARCHAR2(20);
BEGIN
appraisal :=
CASE grade
WHEN 'A' THEN 'Excellent'
WHEN 'B' THEN 'Very Good'
WHEN 'C' THEN 'Good'
WHEN 'D' THEN 'Fair'
WHEN 'F' THEN 'Poor'
ELSE 'No such grade'
END;
DBMS_OUTPUT.PUT_LINE('Grade ' || grade || ' is ' || appraisal);
END;
/
オプションの ELSE 句の機能は、IF 文の ELSE 句に似ています。選択子の値が WHEN 句のオプ
ションの 1 つでなければ、ELSE 句が実行されます。ELSE 句が指定されておらず、一致する
WHEN 句がなければ、式は NULL を戻します。
PL/SQL 言語の基礎
2-25
PL/SQL の式および比較
検索 CASE 式
検索 CASE 式を使用すると、1 つの式を様々な値と比較するのではなく、異なる条件をテストで
きます。この式の書式は、例 2-27 に示すとおりです。
検索 CASE 式には選択子はありません。各 WHEN 句にはブール値を生成する検索条件が含まれ
ており、単一の WHEN 句で異なる変数または複数の条件をテストできます。
例 2-27 CASE 文での検索条件の使用
DECLARE
grade CHAR(1) := 'B';
appraisal VARCHAR2(120);
id NUMBER := 8429862;
attendance NUMBER := 150;
min_days CONSTANT NUMBER := 200;
FUNCTION attends_this_school(id NUMBER) RETURN BOOLEAN IS
BEGIN RETURN TRUE; END;
BEGIN
appraisal :=
CASE
WHEN attends_this_school(id) = FALSE THEN 'N/A - Student not enrolled'
-- Have to test this condition early to detect good students with bad attendance
WHEN grade = 'F' OR attendance < min_days
THEN 'Poor (poor performance or bad attendance)'
WHEN grade = 'A' THEN 'Excellent'
WHEN grade = 'B' THEN 'Very Good'
WHEN grade = 'C' THEN 'Good'
WHEN grade = 'D' THEN 'Fair'
ELSE 'No such grade'
END;
DBMS_OUTPUT.PUT_LINE('Result for student ' || id || ' is ' || appraisal);
END;
/
検索条件は順番に評価されます。各検索条件のブール値によって、どの WHEN 句が実行される
かが決定されます。検索条件が TRUE になると、その WHEN 句が実行されます。WHEN 句が 1 つ
でも実行された後は、後続の検索条件は評価されません。TRUE になる検索条件がなければ、オ
プションの ELSE 句が実行されます。WHEN 句が実行されず、ELSE 句が指定されていなけれ
ば、式の値は NULL となります。
比較文と条件文での NULL の扱い
NULL を使用する場合は、次の規則を念頭に置くことで、問題の発生を未然に防ぐことができ
ます。
■
NULL が関係する比較は、常に結果が NULL になります。
■
論理演算子 NOT を NULL 値に適用すると NULL が戻ります。
■
条件制御文において条件が NULL になる場合、関連する一連の文は実行されません。
■
単純な CASE 文中の式または CASE 式が NULL になる場合は、WHEN NULL を使用して一致さ
せることができません。この場合は、検索 CASE 構文を使用して WHEN expression IS
NULL をテストする必要があります。
例 2-28 では、x と y が等しくないために一連の文が実行されることが予測されます。ただし、
NULL は予測不可能です。そのため、x と y が等しいかどうかは不明です。したがって、IF 条
件は NULL になり、一連の文は実行されずにバイパスされます。
例 2-28 比較での NULL の使用
DECLARE
x NUMBER := 5;
y NUMBER := NULL;
2-26
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の式および比較
BEGIN
IF x != y THEN -- yields NULL, not TRUE
DBMS_OUTPUT.PUT_LINE('x != y'); -- not executed
ELSIF x = y THEN -- also yields NULL
DBMS_OUTPUT.PUT_LINE('x = y');
ELSE
DBMS_OUTPUT.PUT_LINE('Can''t tell if x and y are equal or not.');
END IF;
END;
/
次の例では、a と b が等しいために一連の文が実行されると予測されます。ただし、等号条件
が成立するかどうかは不明であるため、IF 条件は NULL になり、一連の文は実行されずにバイ
パスされます。
DECLARE
a NUMBER := NULL;
b NUMBER := NULL;
BEGIN
IF a = b THEN -- yields NULL, not TRUE
DBMS_OUTPUT.PUT_LINE('a = b'); -- not executed
ELSIF a != b THEN -- yields NULL, not TRUE
DBMS_OUTPUT.PUT_LINE('a != b'); -- not executed
ELSE
DBMS_OUTPUT.PUT_LINE('Can''t tell if two NULLs are equal');
END IF;
END;
/
NULL と NOT 演算子
論理演算子 NOT を NULL 値に適用すると NULL が戻ることに注意してください。このため、次
の 2 つの IF 文は必ずしも等価ではありません。
IF x > y THEN high := x; ELSE high := y; END IF;
IF NOT x > y THEN high := y; ELSE high := x; END IF;
IF 条件が FALSE または NULL になると、ELSE 句内の一連の文が実行されます。x と y のどち
らも NULL ではない場合、両方の IF 文で同じ値が high に代入されます。ただし、x と y の
どちらかが NULL の場合、1 番目の IF 文は y の値を high に代入しますが、2 番目の IF 文は
x の値を high に代入します。
NULL と長さ 0(ゼロ)の文字列
(ゼロ)の文字列
PL/SQL は長さが 0(ゼロ)の文字値をすべて NULL とみなします。これには文字関数やブー
ル式によって戻された値が含まれます。たとえば、次の文ではターゲットの変数に NULL を代
入します。
DECLARE
null_string VARCHAR2(80) := TO_CHAR('');
address VARCHAR2(80);
zip_code VARCHAR2(80) := SUBSTR(address, 25, 0);
name VARCHAR2(80);
valid BOOLEAN := (name != '');
NULL 文字列かどうかをテストする場合は、次のように IS NULL 演算子を使用してください。
IF v_string IS NULL THEN ...
PL/SQL 言語の基礎
2-27
PL/SQL の式および比較
NULL と連結演算子
連結演算子は NULL オペランドを無視します。使用例を次に示します。
'apple' || NULL || NULL || 'sauce'
これは、次の行を戻します。
'applesauce'
組込みファンクションの引数としての NULL
組込みファンクションに引数 NULL が渡されると、次に示す場合を除いて NULL が戻されま
す。
ファンクション DECODE は、先頭の引数を 1 つまたは複数の検索式と比較します。検索式は結
果式と対になっています。検索式や結果式は NULL の場合があります。検索に成功すると、対
応する結果が戻されます。例 2-29 で、列 manager_id が NULL ならば、DECODE は値
'nobody' を戻します。
例 2-29 ファンクション DECODE の使用
DECLARE
the_manager VARCHAR2(40);
name employees.last_name%TYPE;
BEGIN
-- NULL is a valid argument to DECODE. In this case, manager_id is null
-- and the DECODE function returns 'nobody'.
SELECT DECODE(manager_id, NULL, 'nobody', 'somebody'), last_name
INTO the_manager, name FROM employees WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE(name || ' is managed by ' || the_manager);
END;
/
先頭の引数が NULL の場合、ファンクション NVL は 2 番目の引数の値を戻します。例 2-30 で
は、問合せで指定された列が NULL の場合、ファンクションは値 -1 を戻し、従業員が存在しな
いことを出力に示します。
例 2-30 ファンクション NVL の使用
DECLARE
the_manager employees.manager_id%TYPE;
name employees.last_name%TYPE;
BEGIN
-- NULL is a valid argument to NVL. In this case, manager_id is null
-- and the NVL function returns -1.
SELECT NVL(manager_id, -1), last_name
INTO the_manager, name FROM employees WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE(name || ' is managed by employee Id: ' || the_manager);
END;
/
2 番目の引数が NULL の場合、ファンクション REPLACE はオプションの 3 番目の引数が存在
するかどうかにかかわらず、1 番目の引数の値を戻します。たとえば、例 2-31 の REPLACE の
コールは、OLD_STRING の値を変更しません。
例 2-31 ファンクション REPLACE の使用
DECLARE
string_type VARCHAR2(60);
old_string string_type%TYPE := 'Apples and oranges';
v_string string_type%TYPE := 'more apples';
-- NULL is a valid argument to REPLACE, but does not match
-- anything so no replacement is done.
new_string string_type%TYPE := REPLACE(old_string, NULL, v_string);
2-28
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
条件付きコンパイル
BEGIN
DBMS_OUTPUT.PUT_LINE('Old string = ' || old_string);
DBMS_OUTPUT.PUT_LINE('New string = ' || new_string);
END;
/
3 番目の引数が NULL ならば、REPLACE は、1 番目の引数から 2 番目の引数をすべて削除した
ものを戻します。たとえば、次の REPLACE のコールは、DASHED_STRING のダッシュを別の
文字で置き換えるのではなく、削除します。
DECLARE
string_type VARCHAR2(60);
dashed string_type%TYPE := 'Gold-i-locks';
-- When the substitution text for REPLACE is NULL,
-- the text being replaced is deleted.
name string_type%TYPE := REPLACE(dashed, '-', NULL);
BEGIN
DBMS_OUTPUT.PUT_LINE('Dashed name
= ' || dashed);
DBMS_OUTPUT.PUT_LINE('Dashes removed = ' || name);
END;
/
2 番目の引数と 3 番目の引数が NULL の場合、REPLACE は単に 1 番目の引数を戻します。
条件付きコンパイル
条件付きコンパイルを使用すると、ソース・コードを削除することなく、PL/SQL アプリケー
ションの機能をカスタマイズできます。たとえば、条件付きコンパイルを使用して、PL/SQL
アプリケーションを次のようにカスタマイズできます。
■
■
最新のリリースのデータベースでは最新の機能を利用し、古いリリースのデータベースに
対しては、新しい機能を無効にしてそのアプリケーションを実行します。
開発環境ではデバッグ機能またはトレース機能をアクティブ化し、本番サイトでの実行で
は、アプリケーション内でその機能を隠ぺいします。
xxiv ページの「条件付きコンパイル」の新機能の説明を参照してください。ビジネスユースの
事例および実践的な適用事例については、Oracle Technology Network の Web サイト
(http://www.oracle.com/technology/tech/pl_sql/)を参照してください。
条件付きコンパイルの動作方法
条件付きコンパイルでは、選択ディレクティブ、問合せディレクティブおよびエラー・ディレ
クティブを使用してコンパイルのソース・テキストを指定します。問合せディレクティブでは、
PLSQL_CCFLAGS 初期化パラメータの名前 / 値ペアによって設定された値にアクセスします。
選択ディレクティブでは、問合せディレクティブまたは静的パッケージ定数をテストできます。
DBMS_DB_VERSION パッケージでは、条件付きコンパイルに使用できるデータベースのバー
ジョンおよびリリース定数が提供されます。DBMS_PREPROCESSOR パッケージでは、PL/SQL
ユニットの条件付きコンパイル・ディレクティブによって選択される処理後のソース・テキス
トにアクセスするためのサブプログラムが提供されます。
注意 : 条件付きコンパイル機能および関連する PL/SQL パッケージは、
リリース 10.1.0.4 以上の Oracle で使用可能です。
PL/SQL 言語の基礎
2-29
条件付きコンパイル
条件付きコンパイルの制御トークン
条件付きコンパイルのトリガー文字は $ で、これによってアプリケーションがコンパイルされ
る前に処理されるコードが識別されます。条件付きコンパイル制御トークンの形式は次のとお
りです。
preprocessor_control_token ::= $plsql_identifier
$ は識別子名の先頭に置く必要があり、$ と名前の間に空白を入れることはできません。$ は識
別子名に埋め込むこともできますが、特別な意味は持ちません。予約済のプリプロセッサ制御
トークンは、$IF、$THEN、$ELSE、$ELSIF、$END および $ERROR です。条件付きコンパイ
ル制御トークンの使用例は、2-34 ページの例 2-34 を参照してください。
条件付きコンパイルの選択ディレクティブの使用
条件付きコンパイルの選択ディレクティブでは、静的な式を評価して、コンパイルに含める必
要があるテキストを判定します。選択ディレクティブの形式は次のとおりです。
$IF boolean_static_expression $THEN text
[ $ELSIF boolean_static_expression $THEN text ]
[ $ELSE text ]
$END
boolean_static_expression は、静的な BOOLEAN 式である必要があります。静的な
BOOLEAN 式の説明は、2-31 ページの「条件付きコンパイルでの静的な式の使用」を参照してく
ださい。PL/SQL の IF ..THEN 制御構造の詳細は、4-2 ページの「条件テスト : IF 文および
CASE 文」を参照してください。
条件付きコンパイルのエラー・ディレクティブの使用
エラー・ディレクティブ $ERROR では、ユーザー定義のエラーを呼び出します。形式は次のと
おりです。
$ERROR varchar2_static_expression $END
varchar2_static_expression は、静的な VARCHAR2 式である必要があります。静的な
VARCHAR2 式の説明は、2-31 ページの「条件付きコンパイルでの静的な式の使用」を参照して
ください。例 2-33 を参照してください。
条件付きコンパイルの問合せディレクティブの使用
問合せディレクティブは、コンパイル環境のチェックに使用します。問合せディレクティブの
形式は次のとおりです。
inquiry_directive ::= $$id
問合せディレクティブは、2-31 ページの「条件付きコンパイルでの事前定義問合せディレク
ティブの使用」に示すとおり、事前定義またはユーザー定義にできます。次に、条件付きコン
パイルが問合せディレクティブを解決しようとする場合の処理フローの順序を示します。
1.
id は、$$id の形式で、問合せディレクティブとして検索キーに使用します。
2.
2 パス・アルゴリズムは、次のように進行します。
PLSQL_CCFLAGS 初期化パラメータの文字列が右から左へスキャンされ、id で一致名(大
/ 小文字を区別しない)が検索されて、検出されると完了します。
事前定義された問合せディレクティブが検索され、検出されると完了します。
3.
2-30
$$id を値に解決できない場合は、ソース・テキストがラップされていなくても PLW-6003
警告メッセージがレポートされます。リテラル NULL は、未定義の問合せディレクティブ
の値として代入されます。PL/SQL コードがラップされている場合は、未定義の問合せ
ディレクティブが示されないように、警告メッセージが無効になります。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
条件付きコンパイル
たとえば、次のようなセッション設定があるとします。
ALTER SESSION SET
PLSQL_CCFLAGS = 'plsql_ccflags:true, debug:true, debug:0';
$$debug の値は 0 で、$$plsql_ccflags の値は TRUE です。$$plsql_ccflags の値は、
PLSQL_CCFLAGS コンパイラ・パラメータの値内のユーザー定義の plsql_ccflags を解決し
ます。これは、ユーザー定義のディレクティブは事前定義のディレクティブをオーバーライド
するためです。
たとえば、次のようなセッション設定があるとします。
ALTER SESSION SET PLSQL_CCFLAGS = 'debug:true'
$$debug の値は TRUE、$$plsql_ccflags の値は 'debug:true'、$$my_id の値はリテラ
ル NULL です。$$my_id を使用すると、ソース・テキストがラップされていなくても、
PLW-6003 が呼び出されます。
問合せディレクティブの使用例は、2-34 ページの例 2-34 を参照してください。
条件付きコンパイルでの事前定義問合せディレクティブの使用
この項では、事前定義され、条件式で使用できる問合せディレクティブ名について説明します。
このような問合せディレクティブ名には、次のものが含まれます。
■
PLSQL_CCFLAGS、PLSQL_DEBUG、PLSQL_OPTIMIZE_LEVEL、PLSQL_CODE_TYPE、
PLSQL_WARNINGS、NLS_LENGTH_SEMANTICS などの PL/SQL コンパイル用の Oracle 初
期化パラメータ。11-2 ページの「PL/SQL コンパイル用の初期化パラメータ」を参照して
ください。例については、例 2-34 を参照してください。
SQL の ALTER 文の REUSE SETTINGS 句を使用して PL/SQL ユニットを再コンパイルする
と、現行の PL/SQL コンパイル環境の初期化パラメータ値が変更されないようにすること
ができます。例 2-35 を参照してください。
■
行番号を示す PLS_INTEGER リテラル値である PLSQL_LINE は、現行ユニットの
$$PLSQL_LINE を参照します。次に例を示します。
$IF $$PLSQL_LINE = 32 $THEN ...
PLSQL_LINE の値は、PLSQL_CCFLAGS で明示的に定義できます。
■
VARCHAR2 リテラル値である PLSQL_UNIT は、現行のソース・ユニットを示しています。
名前付きコンパイル・ユニットの場合は、$$PLSQL_UNIT にユニット名が含まれますが、
ユニット名に限定されない場合があります。無名ブロックの場合は、$$PLSQL_UNIT に空
の文字列が含まれます。次に例を示します。
IF $$PLSQL_UNIT = 'AWARD_BONUS' THEN ...
PLSQL_UNIT の値は、PLSQL_CCFLAGS で明示的に定義できます。また、前述の例は、通
常の PL/SQL の PLSQL_UNIT の使用を示しています。$$PLSQL_UNIT =
'AWARD_BONUS' は静的な式ではなく VARCHAR2 の比較であるため、$IF でサポートされ
ません。PLSQL_UNIT での $IF の有効な使用の 1 つは、無名ブロックを決定することで
す。
$IF $$PLSQL_UNIT IS NULL $THEN ...
条件付きコンパイルでの静的な式の使用
条件付きコンパイルの処理では、コンパイラで完全に評価できる静的な式のみが使用できます。
変数への参照を含むすべての式または PL/SQL の実行が必要なファンクションは、コンパイル
中には使用できず、評価されません。PL/SQL のデータ型の詳細は、3-2 ページの「事前定義さ
れた PL/SQL データ型の概要」を参照してください。
静的な式とは、静的な BOOLEAN、PLS_INTEGER または VARCHAR2 式のいずれかです。パッ
ケージで宣言される静的定数も静的な式です。
PL/SQL 言語の基礎
2-31
条件付きコンパイル
静的なブール式 静的な BOOLEAN 式には次のものが含まれます。
■
TRUE、FALSE およびリテラル NULL
■
x > y、x < y、x >= y、x <= y、x = y および x <> y。x と y は静的な PLS_INTEGER 式です。
■
■
NOT x、x AND y、x OR y、x > y、x >= y、x = y、x <= y、x <> y。x と y は静的な BOOLEAN
式です。
x IS NULL および x IS NOT NULL。x は静的な式です。
静的な PLS_INTEGER 式 静的な PLS_INTEGER 式には次のものが含まれます。
■
-2147483648 ~ 2147483647 およびリテラル NULL
静的な VARCHAR2 式 静的な VARCHAR2 式には次のものが含まれます。
■
'abcdef' および 'abc' || 'def'
■
リテラル NULL
■
TO_CHAR(x)。x は静的な PLS_INTEGER 式です。
■
TO_CHAR(x f, n)。x は静的な PLS_INTEGER 式で、f と n は静的な VARCHAR2 式です。
■
x || y。x と y は静的な VARCHAR2 式または静的な PLS_INTEGER 式です。
静的定数 静的定数は次のパッケージ仕様部で宣言されます。
static_constant CONSTANT datatype := static_expression;
有効な静的定数の宣言は、次のとおりです。
■
宣言された datatype と static_expression の型が同じ場合
■
static_expression が静的な式である場合
■
datatype が BOOLEAN または PLS_INTEGER のいずれかである場合
静的定数はパッケージ仕様部で宣言する必要があり、package_name パッケージ本体内にある
場合でも、package_name.constant_name として参照する必要があります。
静的パッケージ定数が、PL/SQL ユニットで有効な選択ディレクティブの BOOLEAN 式として
使用されると、条件付きコンパイルのメカニズムによって、参照されるパッケージへの依存性
が自動的に生成されます。パッケージが変更されると依存ユニットは無効になり、再コンパイ
ルして変更を取得する必要があります。依存性を生成できるのは、有効な静的な式のみです。
複数の PL/SQL ユニットの条件付きコンパイルを制御する静的定数を持つパッケージを使用す
る場合は、パッケージ仕様部のみを作成し、複数の依存性のために、そのパッケージ仕様部を
条件付きコンパイルの制御専用にします。個々のユニットの条件付きコンパイルを制御するに
は、PLSQL_CCFLAGS に特定のフラグを設定できます。
例 2-32 では、my_debug パッケージは、デバッグを制御し、複数の PL/SQL ユニットをトレー
スするための定数を定義します。この例では、定数 debug および trace はプロシージャ
my_proc1 および my_proc2 の静的な式で使用され、プロシージャからの依存性を my_debug
に生成します。
例 2-32 静的定数の使用
CREATE PACKAGE my_debug IS
debug CONSTANT BOOLEAN := TRUE;
trace CONSTANT BOOLEAN := TRUE;
END my_debug;
/
CREATE PROCEDURE my_proc1 IS
BEGIN
$IF my_debug.debug $THEN DBMS_OUTPUT.put_line('Debugging ON');
2-32
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
条件付きコンパイル
$ELSE DBMS_OUTPUT.put_line('Debugging OFF'); $END
END my_proc1;
/
CREATE PROCEDURE my_proc2 IS
BEGIN
$IF my_debug.trace $THEN DBMS_OUTPUT.put_line('Tracing ON');
$ELSE DBMS_OUTPUT.put_line('Tracing OFF'); $END
END my_proc2;
/
定数の値の 1 つを変更すると、パッケージのすべての依存ユニットが新しい値で再コンパイル
されます。たとえば、debug の値を FALSE に変更すると、my_proc1 がデバッグ・コードな
しで再コンパイルされます。my_proc2 も再コンパイルされますが、trace の値が変更されて
いないため、my_proc2 は変更されません。
PLSQL_CCFLAGS 初期化パラメータの設定
動的 PLSQL_CCFLAGS 初期化パラメータに、関連した値を持つフラグ名を設定し、PL/SQL ユ
ニットの条件付きコンパイルを制御することができます。たとえば、例 2-34 に示すように、
PLSQL_CCFLAGS 初期化パラメータを ALTER SESSION で動的に設定し、PL/SQL ユニットの
デバッグ機能とトレース機能を有効にできます。
また、例 2-35 に示すように、SQL の ALTER PROCEDURE 文を使用して、特定の PL/SQL ユ
ニットの条件付きコンパイルを独立して制御するように、PLSQL_CCFLAGS 初期化パラメータ
を設定することもできます。
フラグ名は、予約語やキーワードなどの、引用されていない任意の PL/SQL 識別子に設定でき
ます。フラグ値を明示的に設定する場合は、TRUE、FALSE、PLS_INTEGER または NULL に設
定する必要があります。フラグ名およびフラグ値では大 / 小文字が区別されません。制限を含
む PLSQL_CCFLAGS 初期化パラメータの詳細は、
『Oracle Database リファレンス』を参照して
ください。
DBMS_DB_VERSION パッケージ定数の使用
DBMS_DB_VERSION パッケージは、条件付きコンパイルの単純な選択を行う場合に役立つ定数
を提供します。PLS_INTEGER 定数 VERSION および RELEASE は、現行の Oracle バージョンと
リリース番号を識別します。BOOLEAN 定数 VER_LE_9、VER_LE_9_1、VER_LE_9_2、
VER_LE_10、VER_LE_10_1 および VER_LE_10_2 は、そのバージョンおよびリリース以下で
あることを基準にして、TRUE または FALSE に評価されます。たとえば、Oracle 10g リリース
2(10.2)の定数は、次のように評価されます。
■
■
■
VER_LE_10 は、データベースのバージョンが 10 以下の状態を表します。この場合、
VER_LE_10 は TRUE です。
VER_LE_10_2 は、データベースのバージョンが 10 以下で、リリースが 2 以下の状態を表
します。この場合、VER_LE_10_2 は TRUE です。
Oracle 10g リリース 1(10.1)以下を表す定数はすべて FALSE になります。
例 2-33 に、条件付きコンパイルでの DBMS_DB_VERSION 定数の使用例を示します。Oracle
データベースのバージョンとリリースの両方がチェックされます。ここでは、$ERROR の使用
例も示します。
例 2-33 DBMS_DB_VERSION 定数の使用
BEGIN
$IF DBMS_DB_VERSION.VER_LE_10_1 $THEN
$ERROR 'unsupported database release' $END
$ELSE
DBMS_OUTPUT.PUT_LINE ('Release ' || DBMS_DB_VERSION.VERSION || '.' ||
DBMS_DB_VERSION.RELEASE || ' is supported.');
-- Note that this COMMIT syntax is newly supported in 10.2
COMMIT WRITE IMMEDIATE NOWAIT;
PL/SQL 言語の基礎
2-33
条件付きコンパイル
$END
END;
/
DBMS_DB_VERSION パッケージの詳細は、
『Oracle Database PL/SQL パッケージ・プロシー
ジャおよびタイプ・リファレンス』を参照してください。
条件付きコンパイルの例
この項では、条件付きコンパイルの使用例を示します。
条件付きコンパイルを使用してデータベースのバージョンのコードを指定
する方法
例 2-34 では、BINARY_DOUBLE データ型をデータベースの PL/SQL ユニットの計算で使用でき
るかどうかを、条件付きコンパイルを使用して判断します。BINARY_DOUBLE データ型は、10g
以上のデータベースのバージョンでのみ使用できます。ここでは、PLSQL_CCFLAGS パラメー
タの使用例も示します。
例 2-34 データベースのバージョンでの条件付きコンパイルの使用
-- set flags for displaying debugging code and tracing info
ALTER SESSION SET PLSQL_CCFLAGS = 'my_debug:FALSE, my_tracing:FALSE';
CREATE PACKAGE my_pkg AS
SUBTYPE my_real IS
$IF DBMS_DB_VERSION.VERSION < 10 $THEN NUMBER; -- check database version
$ELSE
BINARY_DOUBLE;
$END
my_pi my_real; my_e my_real;
END my_pkg;
/
CREATE PACKAGE BODY my_pkg AS
BEGIN -- set up values for future calculations based on DB version
$IF DBMS_DB_VERSION.VERSION < 10 $THEN
my_pi := 3.14016408289008292431940027343666863227;
my_e := 2.71828182845904523536028747135266249775;
$ELSE
my_pi := 3.14016408289008292431940027343666863227d;
my_e := 2.71828182845904523536028747135266249775d;
$END
END my_pkg;
/
CREATE PROCEDURE circle_area(radius my_pkg.my_real) IS
my_area my_pkg.my_real;
my_datatype VARCHAR2(30);
BEGIN
my_area := my_pkg.my_pi * radius;
DBMS_OUTPUT.PUT_LINE('Radius: ' || TO_CHAR(radius)
|| ' Area: ' || TO_CHAR(my_area) );
$IF $$my_debug $THEN -- if my_debug is TRUE, run some debugging code
SELECT DATA_TYPE INTO my_datatype FROM USER_ARGUMENTS
WHERE OBJECT_NAME = 'CIRCLE_AREA' AND ARGUMENT_NAME = 'RADIUS';
DBMS_OUTPUT.PUT_LINE('Datatype of the RADIUS argument is: ' || my_datatype);
$END
END;
/
2-34
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
条件付きコンパイル
my_debug に TRUE を設定する場合は、例 2-35 に示すように、REUSE SETTINGS 句があるプロ
シージャ circle_area に対してのみこの変更を実行できます。
例 2-35 ALTER PROCEDURE を使用して PLSQL_CCFLAGS を設定する方法
ALTER PROCEDURE circle_area COMPILE PLSQL_CCFLAGS = 'my_debug:TRUE'
REUSE SETTINGS;
DBMS_PREPROCESSOR プロシージャを使用してソース・テキストの印刷
または取出しを行う方法
DBMS_PREPROCESSOR サブプログラムは、条件付きコンパイル・ディレクティブの処理後に、
PL/SQL ユニットの処理後のソース・テキストを印刷または取り出します。この処理後のテキ
ストは、有効な PL/SQL ユニットのコンパイルに使用する実際のソースです。例 2-36 に、
PRINT_POST_PROCESSED_SOURCE プロシージャで例 2-34 の my_pkg の処理後の形式を印刷
する方法を示します。
例 2-36 PRINT_POST_PROCESSED_SOURCE を使用したソース・コードの表示
CALL DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE('PACKAGE', 'HR', 'MY_PKG');
例 2-34 の my_pkg が HR アカウントを使用して 10g 以上のリリースのデータベースでコンパイ
ルされる場合、例 2-36 の出力は次のようになります。
PACKAGE my_pkg AS
SUBTYPE my_real IS
BINARY_DOUBLE;
my_pi my_real; my_e my_real;
END my_pkg;
PRINT_POST_PROCESSED_SOURCE は、非選択テキストを空白に置き換えます。処理後のテキ
ストに含まれない例 2-34 のコードの行は、空白行として表されます。DBMS_PREPROCESSOR
パッケージの詳細は、
『Oracle Database PL/SQL パッケージ・プロシージャおよびタイプ・リ
ファレンス』を参照してください。
条件付きコンパイルの制限
条件付きコンパイルのディレクティブは、オブジェクト型の仕様部やスキーマ・レベルのネス
トした表または VARRAY の仕様部では使用できません。依存する型の属性構造および依存する
表の列構造は、オブジェクト型の仕様部で指定された属性構造によって決定されます。オブ
ジェクト型の属性構造に対するすべての変更は、それらの変更が依存オブジェクトに適用され
るように、決められた方法で実行される必要があります。変更を適用するには、SQL の ALTER
TYPE ...ATTRIBUTE 文を使用します。プリプロセッサ・ディレクティブを使用すると、ALTER
TYPE ...ATTRIBUTE 文を使用しなくても、オブジェクト型の属性構造を変更できます。その結
果、依存オブジェクトが非同期になったり、依存表がアクセス不可になる場合があります。
SQL パーサーでは、CREATE [OR REPLACE] 文や無名ブロックの実行などの SQL 操作の実行時
に、ディレクティブの配置についての制限があります。これらの SQL 操作の実行時、最初の条
件付きコンパイル・ディレクティブの位置について、SQL パーサーでは次の制限があります。
■
■
条件付きコンパイル・ディレクティブは、オブジェクト型の仕様部やスキーマ・レベルの
ネストした表または VARRAY の仕様部では使用できません。
パッケージ仕様部、パッケージ本体、型本体および仮パラメータがないスキーマ・レベル
のファンクションまたはプロシージャでは、最初の条件付きコンパイル・ディレクティブ
が、キーワード IS/AS の直後に配置される場合があります。
PL/SQL 言語の基礎
2-35
PL/SQL を使用して Web アプリケーションおよび Server Pages を作成する方法
■
1 つ以上の仮パラメータを持つスキーマ・レベルのファンクションまたはプロシージャで
は、最初の条件付きコンパイル・ディレクティブは、ユニット名の後の開きカッコの直後
に配置されることがあります。次に例を示します。
CREATE OR REPLACE PROCEDURE my_proc (
$IF $$xxx $THEN i IN PLS_INTEGER $ELSE i IN INTEGER $END
) IS BEGIN NULL; END my_proc;
/
■
■
トリガーまたは無名ブロックでは、トリガー・ブロックに DECLARE セクションがある場
合、最初の条件付きコンパイル・ディレクティブは、キーワード BEGIN の直後またはキー
ワード DECLARE の直後に配置される場合があります。
無名ブロックでプレースホルダが使用される場合、条件付きコンパイル内ではこの配置は
行われません。次に例を示します。
BEGIN
:n := 1; -- プレースホルダの有効な使用
$IF ....$THEN
:n := 1; -- プレースホルダの無効な使用
$END
PL/SQL を使用して Web アプリケーションおよび Server Pages を
作成する方法
PL/SQL を使用して、Web アプリケーションや Server Pages を開発できます。この項では、そ
れらの方法を簡単に説明します。PL/SQL を使用して Web アプリケーションを作成する方法の
詳細は、
『Oracle Database アプリケーション開発者ガイド - 基礎編』の PL/SQL Web ツール
キットを使用したアプリケーションの開発に関する項を参照してください。PL/SQL を使用し
て Web Server Pages(PSP)を作成する方法の詳細は、
『Oracle Database アプリケーション開
発者ガイド - 基礎編』の PL/SQL Server Pages の開発に関する項を参照してください。
PL/SQL Web アプリケーション
PL/SQL を使用すると Oracle データベースから直接 Web ページを生成するアプリケーション
を作成できるため、データベースを Web 上で使用可能にし、事務管理部門のデータをイントラ
ネット上でアクセス可能にすることができます。PL/SQL Web アプリケーションのプログラ
ム・フローは、CGI Perl スクリプトのプログラム・フローに似ています。通常、開発者は CGI
スクリプトを使用して Web ページを動的に作成しますが、多くの場合それらのスクリプトは
Oracle データベースへのアクセスに適していません。PL/SQL ストアド・プロシージャで Web
コンテンツを配信することによって、強力で柔軟なデータベース処理が実現されます。たとえ
ば、DML、動的 SQL およびカーソルを使用できます。各 HTTP リクエストを処理する新しい
CGI プロセスを fork するためのプロセス・オーバーヘッドを解消することもできます。
PL/SQL Gateway と PL/SQL Web Toolkit を使用して、完全に Web ブラウザ・ベースのアプリ
ケーションを PL/SQL に実装できます。
■
■
2-36
PL/SQL Gateway を使用すると、HTTP リスナーを介して Web ブラウザで PL/SQL ストア
ド・プロシージャを呼び出すことができます。PL/SQL Gateway の 1 つの実装である
mod_plsql は Oracle HTTP Server のプラグインであり、Web ブラウザで PL/SQL ストア
ド・プロシージャを呼び出せるようにします。
PL/SQL Web Toolkit は、実行時に mod_plsql によってコールされるストアド・プロシー
ジャを使用するための一般的なインタフェースを提供する一連の PL/SQL パッケージで
す。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL の組込みファンクションのまとめ
PL/SQL Server Pages
PL/SQL Server Pages(PSP)を使用すると、Web ページを動的コンテンツで開発できます。こ
れは、Web ページ用に HTML コードを一度に 1 行ずつ書き出すストアド・プロシージャを
コーディングする方法の代替手段です。
特殊なタグを使用すると、PL/SQL スクリプトを HTML ソース・コードに埋め込むことができ
ます。スクリプトは、ページがブラウザなどの Web クライアントによって要求された時に実行
されます。スクリプトは、パラメータ、データベースへの問合せまたは更新を受け入れること
が可能で、結果を示すカスタマイズ済のページを表示できます。
開発中、PSP はページ・レイアウト用の静的部分およびコンテンツ用の動的部分を持つテンプ
レートのように動作できます。任意の HTML オーサリング・ツールを使用してレイアウトを設
計できます。プレースホルダは動的コンテンツ用に残します。次に、コンテンツを生成する
PL/SQL スクリプトを作成できます。終了した後、作成した PSP ファイルをストアド・プロ
シージャとして単にデータベースにロードします。
PL/SQL の組込みファンクションのまとめ
PL/SQL には、データを操作するために役立つ多くの強力なファンクションが用意されていま
す。組込みファンクションは、次のカテゴリに分類できます。
エラー・レポート
数値
文字
データ型変換
日付
オブジェクト参照
その他
表 2-4 に、各カテゴリのファンクションを示します。エラー・レポート・ファンクションの説
明は、13-115 ページの「SQLCODE ファンクション」および 13-116 ページの「SQLERRM ファ
ンクション」を参照してください。その他のファンクションの説明は、
『Oracle Database SQL
リファレンス』を参照してください。
SQL 文の中では、エラー報告ファンクション SQLCODE と SQLERRM を除くすべてのファンク
ションを使用できます。また、オブジェクト参照ファンクション DEREF、REF および VALUE
とファンクション DECODE、DUMP および VSIZE 以外であれば、すべてのファンクションをプ
ロシージャ文で使用できます。
SQL 集計関数(AVG や COUNT など)と SQL 分析関数(CORR や LAG など)は PL/SQL に組み
込まれていませんが、SQL 文に使用できます(ただし、プロシージャ文には使用できません)
。
PL/SQL 言語の基礎
2-37
PL/SQL の組込みファンクションのまとめ
表 2-4 組込みファンクション
エラー
数値
文字
変換
日付
オブ
ジェク
ト参照
SQLCODE
ABS
ASCII
CHARTOROWID
ADD_MONTHS
DEREF
BFILENAME
SQLERRM
ACOS
ASCIISTR
CONVERT
CURRENT_DATE
REF
COALESCE
ASIN
CHR
HEXTORAW
CURRENT_TIME
TREAT
DECODE
ATAN
COMPOSE
RAWTOHEX
CURRENT_TIMESTAMP
VALUE
DUMP
ATAN2
CONCAT
RAWTONHEX
DBTIMEZONE
EMPTY_BLOB
BITAND
DECOMPOSE
ROWIDTOCHAR
EXTRACT
EMPTY_CLOB
CEIL
INITCAP
TO_BINARY_DOUBLE FROM_TZ
GREATEST
COS
INSTR
TO_BLOB
LAST_DAY
LEAST
COSH
INSTR2
TO_BINARY_FLOAT
LOCALTIMESTAMP
NANVL
INSTR4
TO_CHAR
MONTHS_BETWEEN
NLS_CHARSET_DECL_LEN
INSTRB
TO_CLOB
NEW_TIME
NLS_CHARSET_ID
INSTRC
TO_DATE
NEXT_DAY
NLS_CHARSET_NAME
LENGTH
TO_MULTI_BYTE
NUMTODSINTERVAL
NULLIF
TO_NCHAR
NUMTOYMINTERVAL
NVL
TO_NCLOB
ROUND
SYS_CONTEXT
TO_NUMBER
SCN_TO_TIMESTAMP
SYS_GUID
TO_SINGLE_BYTE
SESSIONTIMEZONE
UID
SYS_EXTRACT_UTC
USER
SYSDATE
USERENV
SYSTIMESTAMP
VSIZE
EXP
FLOOR
LN
LOG
MOD
POWER
LENGTH2
LENGTH4
REMAIN
DER
LENGTHB
ROUND
LENGTHC
SIGN
LOWER
SIN
LPAD
SINH
LTRIM
SQRT
NCHR
TAN
NLS_INITCAP
TANH
NLS_LOWER
TO_TIME
TRUNC
NLSSORT
TO_TIME_TZ
NLS_UPPER
TO_TIMESTAMP
REGEXP_INSTR
TO_TIMESTAMP_TZ
REGEXP_LIKE
TO_YMINTERVAL
REGEXP_REPLACE
TRUNC
REGEXP_SUBSTR
TZ_OFFSET
TIMESTAMP_TO_SCN
TO_DSINTERVAL
REPLACE
RPAD
RTRIM
SOUNDEX
SUBSTR
SUBSTR2
SUBSTR4
SUBSTRB
SUBSTRC
TRANSLATE
TRIM
UNISTR
UPPER
2-38
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
その他
3
PL/SQL のデータ型
すべての定数、変数およびパラメータは、記憶形式、制約および値の有効範囲を指定するデー
タ型(または型)を持っています。PL/SQL には、多くの事前定義のデータ型が用意されてい
ます。たとえば、整数、浮動小数点、文字、BOOLEAN、日付、コレクション、参照およびラー
ジ・オブジェクト(LOB)の各型から選択できます。また、PL/SQL では独自のサブタイプを
定義できます。この章では、PL/SQL プログラムで頻繁に使用する基本的な型について説明し
ます。より特化された型については、以降の章を参照してください。
この章の項目は、次のとおりです。
■
事前定義された PL/SQL データ型の概要
■
PL/SQL サブタイプの概要
■
PL/SQL データ型の変換
■
CHAR と VARCHAR2 のデータ型の違い
PL/SQL のデータ型
3-1
事前定義された PL/SQL データ型の概要
事前定義された PL/SQL データ型の概要
事前定義 PL/SQL のデータ型は、コンポジット、LOB、参照およびスカラー型のグループに分
けられます。
■
■
■
■
コンポジット型には、配列、レコードまたは表の要素のような、個別に操作できる内部的
な要素があります。第 5 章「PL/SQL のコレクションおよびレコードの使用」を参照して
ください。
LOB 型には、LOB ロケータという値があります。この値は、他のデータベース・データと
は別に格納されている大きいオブジェクト(テキスト・ブロックや図形イメージなど)の
位置を指定します。LOB 型には、BFILE、BLOB、CLOB および NCLOB が含まれます。3-10
ページの「PL/SQL LOB 型」を参照してください。
参照型には、他のプログラム項目を指定するポインタという値があります。参照型には、
オブジェクト型に対する REF CURSORS および REF が含まれます。6-19 ページの「カーソ
ル変数(REF CURSOR)の使用」を参照してください。
スカラー型には内部コンポーネントがありません。スカラー型は、数値や文字列などの 1
つの値を保持します。スカラー型は数値、文字、ブール、日付 / 時刻などを格納するデー
タの種類によって 4 つのグループに分類されます。スカラー・データ型は次のとおりです。
■
PL/SQL の数値型
BINARY_DOUBLE、BINARY_FLOAT、BINARY_INTEGER、DEC、DECIMAL、DOUBLE
PRECISION、FLOAT、INT、INTEGER、NATURAL、NATURALN、NUMBER、NUMERIC、
PLS_INTEGER、POSITIVE、POSITIVEN、REAL、SIGNTYPE、SMALLINT
■
PL/SQL の文字型と文字列型 および PL/SQL の各国語キャラクタ・タイプ
CHAR、CHARACTER、LONG、LONG RAW、NCHAR、NVARCHAR2、RAW, ROWID、
STRING、UROWID、VARCHAR、VARCHAR2
LONG データ型および LONG RAW データ型は、下位互換性のためにのみ使用してくださ
い。詳細は、3-6 ページの「LONG および LONG RAW データ型」を参照してくださ
い。
■
PL/SQL のブール型
BOOLEAN
■
PL/SQL の日付型、時刻型および時間隔型
DATE、TIMESTAMP、TIMESTAMP WITH TIMEZONE、TIMESTAMP WITH LOCAL
TIMEZONE、INTERVAL YEAR TO MONTH、INTERVAL DAY TO SECOND
PL/SQL の数値型
数値型は、数値データ(整数、実数および浮動小数点数)の格納、量の表現および計算に使用
します。
BINARY_INTEGER データ型
BINARY_INTEGER のデータ型は PLS_INTEGER と同じです。BINARY_INTEGER のサブタイプ
は PLS_INTEGER のサブタイプと見なすことができます。xxv ページの
「BINARY_INTEGER データ型への変更」を参照してください。簡略化のため、このマニュアル
では主に PLS_INTEGER を使用します。3-4 ページの「PLS_INTEGER データ型」を参照してく
ださい。
3-2
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
事前定義された PL/SQL データ型の概要
BINARY_INTEGER サブタイプ ベース型は、サブタイプの導出元となるデータ型です。サブタイ
プはベース型を制約と結び付け、値のサブセットを定義します。PL/SQL では、次のような
BINARY_INTEGER サブタイプがあらかじめ定義されています。
NATURAL
NATURALN
POSITIVE
POSITIVEN
SIGNTYPE
サブタイプ NATURAL および POSITIVE は、整変数をそれぞれ負ではない整数値、または正の
整数値に制限する場合に使用します。NATURALN と POSITIVEN は、整変数に NULL を代入で
きないようにします。SIGNTYPE は、整変数を値 -1、0、1 に制限するときに使用します。これ
は 3 値論理のプログラミングに役立ちます。
BINARY_FLOAT および BINARY_DOUBLE データ型
それぞれ単精度と倍精度の IEEE 754 形式の単精度浮動小数点数を格納します。これらの型は、
主に科学的な高速計算に使用されます。使用方法は、11-19 ページの「PL/SQL での計算集中型
プログラムの記述」を参照してください。異なる数値型を受け入れる数学ライブラリを記述す
る方法は、8-10 ページの「数値型のオーバーロードのガイドライン」を参照してください。
これらの型のリテラルは、末尾に f(BINARY_FLOAT の場合)または d(BINARY_DOUBLE の
場合)が付きますたとえば、2.07f や 3.000094d。
これらの型を伴う計算は、例外を呼び出すのではなく、確認が必要な特別な値を生成します。
これらの数に発生する可能性があるオーバーフロー、アンダーフローおよびその他の条件を処
理するには、BINARY_FLOAT_NAN、BINARY_FLOAT_INFINITY、
BINARY_FLOAT_MAX_NORMAL、BINARY_FLOAT_MIN_NORMAL、
BINARY_FLOAT_MAX_SUBNORMAL、BINARY_FLOAT_MIN_SUBNORMAL、および
BINARY_DOUBLE で始まる対応する名前の特別な事前定義の定数を使用できます。SQL では、
NaN(非数値)および無限大用の定数も定義されています。その他の整数は PL/SQL 専用です。
NUMBER データ型
NUMBER データ型は、1E-130 から 1.0E126(ただし 1.0E126 を含まない)までの絶対値を持
つ固定小数点数または浮動小数点数を確実に格納します。NUMBER 変数は 0 を表すこともでき
ます。2-6 ページの例 2-1 を参照してください。
NUMBER リテラル値の場合、または NUMBER の計算結果が指定の範囲内になる場合のみに使用
することをお薦めします。
■
リテラルまたは NUMBER の計算値がその範囲より小さい場合は、ゼロに丸められます。
■
リテラル値が上限を超える場合は、コンパイル・エラーが発生します。
■
NUMBER の計算値が上限を超える場合、結果は確実ではなく、信頼性がないためにエラー
となります。
NUMBER データ型の構文は、次のとおりです。
NUMBER[(precision,scale)]
精度(precision)は全体の桁数であり、位取り(scale)は、小数点以下の桁数です。精度
(precision)と位取り(scale)の指定には、定数や変数を使用できません。整数リテラルを使用
する必要があります。
固定小数点数を宣言するには、位取り(scale)を指定する必要があります。精度および位取り
の両方を含む、次の形式を使用します。
NUMBER(precision,scale)
浮動小数点数を宣言する場合は、小数点が任意の位置に浮動するため、精度(precision)や位
取り(scale)を指定できません。精度および位取りを含まない、次の形式を使用します。
NUMBER
PL/SQL のデータ型
3-3
事前定義された PL/SQL データ型の概要
整数を宣言する場合は(小数点がありません)
、精度のみの次の形式を使用します。
NUMBER(precision) -- NUMBER(precision,0) と同じ
NUMBER 型に指定できる精度(precision)の最大値は 10 進の 38 桁です。精度(precision)を
指定しないと、39 または 40、あるいはご使用のシステムがサポートしている最大値のどちらか
小さいほうになります。
位取り(scale)の範囲は -84 ~ 127 で、この値によって四捨五入の位置が決まります。たとえ
ば、位取り(scale)として 2 を指定すると小数点以下 2 桁に四捨五入されます(3.4562 は 3.46
になります)
。負の位取り(scale)を指定すると、小数点の左側で四捨五入されます。たとえ
ば、位取り(scale)として -3 を指定すると、1000 の単位に四捨五入されます(34562 は 34000
になります)
。位取り(scale)として 0 を指定すると、最も近い整数値に四捨五入されます
(3.4562 は 3 になります )。位取り(scale)を指定しないと、次の例で示すように、デフォルト
で 0(ゼロ)になります。
DECLARE
x NUMBER(3);
BEGIN
x := 123.89;
DBMS_OUTPUT.PUT_LINE('The value of x is ' || TO_CHAR(x));
END;
/
出力結果 : The value of x is 124
NUMBER データ型の詳細は、『Oracle Database SQL リファレンス』を参照してください。
NUMBER サブタイプ 次の NUMBER サブタイプは、名前の記述性を高め、ANSI/ISO および
IBM 型に対して互換性を保つ目的で用意されたデータ型です。
DEC
DECIMAL
DOUBLE PRECISION
FLOAT
INT
INTEGER
NUMERIC
REAL
SMALLINT
サブタイプ DEC、DECIMAL、NUMERIC は、固定小数点数を宣言する場合に使用します。その
場合、精度(precision)の最大値は 10 進数の 38 桁です。
サブタイプ DOUBLE PRECISION と FLOAT は、浮動小数点数を宣言する場合に使用します。そ
の場合、精度(precision)の最大値は 2 進数の 126 桁であり、10 進数の 38 桁にほぼ等しくな
ります。サブタイプ REAL は、浮動小数点数を宣言する場合に使用します。その場合、精度
(precision)の最大値は 2 進数で 63 桁であり、およそ 10 進数の 18 桁に等しくなります。
サブタイプ INTEGER、INT、SMALLINT は、整数を宣言する場合に使用します。その場合、精
度(precision)の最大値は 10 進数の 38 桁です。
PLS_INTEGER データ型
PLS_INTEGER データ型は、符号付き整数を格納するために使用します。値の大きさの範囲は、
32 ビットで表すと、-2147483648 ~ 2147483647 です。PLS_INTEGER 値は、NUMBER および
NUMBER サブタイプの値より小さい記憶域しか必要としません。また、PLS_INTEGER 演算は
ハードウェア算術計算を使用するため、ライブラリ算術計算を使用する NUMBER 演算よりも処
理速度が速くなります。効率のために、PLS_INTEGER の大きさの範囲内でのすべての計算に
PLS_INTEGER を使用してください。PLS_INTEGER の範囲外の計算には、INTEGER データ型
を使用できます。
3-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
事前定義された PL/SQL データ型の概要
注意 :
■
■
BINARY_INTEGER と PLS_INTEGER のデータ型は同じです。xxv ペー
ジの「BINARY_INTEGER データ型への変更」を参照してください。
2 つの PLS_INTEGER データ型で計算をして PLS_INTEGER の範囲値
をオーバーフローした場合、結果を NUMBER に代入した場合でも、
オーバーフロー例外が発生します。
PL/SQL の文字型と文字列型
キャラクタ・タイプは、英数字データの格納、ワードとテキストの表現および文字列の操作に
使用します。
CHAR データ型
CHAR データ型は固定長の文字データを格納するために使用します。データの内部表現形式は、
データベース・キャラクタ・セットによって異なります。CHAR データ型はオプション・パラ
メータを使用して、その最大サイズを 32767 バイトまで指定できます。サイズはバイト数また
は文字数で指定できます。各文字には、キャラクタ・セットのエンコーディングに応じて 1 バ
イト以上が含まれます。次に構文を示します。
CHAR[(maximum_size [CHAR
|
BYTE] )]
最大サイズには 1 ~ 32767 の範囲の整数リテラルを指定します。シンボリック定数や変数は指
定できません。
最大サイズを指定しなければ、デフォルトで 1 に設定されます。最大サイズを文字数ではなく
バイト数で指定すると、CHAR(n) 変数が小さすぎて n 個のマルチバイト文字を保持できなくな
る場合があります。この可能性を回避するには、データベース・キャラクタ・セットの一部の
文字に複数のバイトが含まれていても、変数で n 個の文字を保持できるように、表記法
CHAR(n CHAR) を使用します。文字数の長さを指定する場合の上限は、32767 バイトです。ダ
ブルバイトおよびマルチバイトのキャラクタ・セットの場合、指定できるのは、シングルバイ
ト・キャラクタ・セットの 1/2 または 1/3 の文字のみです。
PL/SQL の文字変数は比較的長くなりがちですが、2000 バイトを超える CHAR 値は CHAR デー
タベース列に挿入できません。
LONG 列の最大幅は 2147483648 バイト(2GB)であるため、すべての CHAR(n) 値を LONG デー
タベース列に格納できます。ただし、LONG 列から 32768 バイト以上の値を取り出して
CHAR(n) に入れることはできません。LONG データ型は、下位互換性のためにのみ使用してく
ださい。詳細は、3-6 ページの「LONG および LONG RAW データ型」を参照してください。
CHAR または BYTE 修飾子を使用しなければ、デフォルトは NLS_LENGTH_SEMANTICS 初期化
パラメータの設定によって決定されます。PL/SQL プロシージャのコンパイル時には、このパ
ラメータの設定が記録されるため、プロシージャが無効になった後に再コンパイルするときに
も同じ設定が使用されます。
CHAR と VARCHAR2 ベース型の意味上の違いは、3-22 ページの「CHAR と VARCHAR2 のデー
タ型の違い」を参照してください。
CHAR サブタイプ CHAR サブタイプ CHARACTER の値は、そのベース型と同じ範囲をとります。
つまり、CHARACTER は CHAR の別名にすぎません。このサブタイプは、CHAR 型のみの場合よ
りも識別子の記述性を高め、ANSI/ISO および IBM 型に対して互換性を保つ目的で用意された
データ型です。
PL/SQL のデータ型
3-5
事前定義された PL/SQL データ型の概要
LONG および LONG RAW データ型
注意 : LONG および LONG RAW データ型は、既存アプリケーションとの下
位互換性のためにのみ使用してください。新規アプリケーションには、
LONG のかわりに CLOB または NCLOB を、LONG RAW のかわりに、BLOB
または BFILE を使用します。
また、既存の LONG および LONG RAW データ型は、LOB データ型に置き換
えることをお薦めします。LOB データ型は、LONG または LONG RAW デー
タ型よりも制限事項が非常に少ないためです。さらに、LOB の機能はリ
リースごとに拡張されていますが、LONG および LONG RAW の機能は最近
のリリースでは拡張されていません。3-10 ページの「PL/SQL LOB 型」を
参照してください。
LONG データ型は、可変長の文字列を格納するために使用します。LONG データ型は、LONG 値
の最大サイズが 32760 バイトであるという点を除けば、VARCHAR2 データ型と同じです。
LONG RAW データ型はバイナリ・データやバイト列を格納するために使用します。LONG RAW
データは、LONG RAW データが PL/SQL によって解釈されないという点を除けば、LONG
データと同じです。LONG RAW 値の最大サイズは 32760 バイトです。
LONG 列の最大幅は 2147483648 バイト(2GB)であるため、すべての LONG 値を LONG データ
ベース列に格納できます。ただし、LONG 列から 32761 バイト以上の値を取り出して LONG 変数
に入れることはできません。
同様に、LONG RAW 列の最大幅は 2147483648 バイトであるため、すべての LONG RAW 値を
LONG RAW データベース列に格納できます。ただし、LONG RAW 列から 32761 バイト以上の値を
取り出して LONG RAW 変数に入れることはできません。
LONG 型の列にはテキスト、文字の配列、短いドキュメントなどを格納できます。LONG 型の列
は、UPDATE 文、INSERT 文および(ほとんどの)SELECT 文で参照できますが、式や SQL 関
数コール、または WHERE、GROUP BY、CONNECT BY といった一部の SQL 句では参照できませ
ん。詳細は、
『Oracle Database SQL リファレンス』を参照してください。
SQL 文では、PL/SQL は LONG 値が LONG ではなく VARCHAR2 としてバインドされます。ただ
し、バインドされた VARCHAR2 の長さが VARCHAR2 列の最大幅(4000 バイト)を超える場合
は、バインド型が LONG に自動的に変換され、エラー・メッセージが発行されます。これは、
SQL ファンクションには LONG 値を渡すことができないためです。
RAW データ型
RAW データ型はバイナリ・データやバイト列を格納するために使用します。たとえば、RAW 型
変数には図形文字の並びやデジタル化された絵を格納できます。RAW データは VARCHAR2
データと似ていますが、PL/SQL によって解釈されない点が異なります。また、RAW データを
システム間で送信する際に、Oracle Net はキャラクタ・セット変換を実行しません。
RAW データ型は必須パラメータを使用して、その最大サイズを 32767 バイトまで指定できます。
次に構文を示します。
RAW(maximum_size)
最大サイズには 1 ~ 32767 の範囲の整数リテラルを指定します。シンボリック定数や変数は指
定できません。
長さ 2001 バイト以上の RAW 値は RAW 型の列に挿入できません。LONG RAW 列の最大幅は、
2147483648 バイト(2GB)であるため、すべての RAW 値を LONG RAW データベース列に格納で
きます。ただし、LONG RAW 列から 32768 バイト以上の値を取り出して RAW 変数に入れること
はできません。LONG RAW データ型は、下位互換性のためにのみサポートされている点に注意
してください。詳細は、3-6 ページの「LONG および LONG RAW データ型」を参照してくだ
さい。
3-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
事前定義された PL/SQL データ型の概要
ROWID および UROWID データ型
内部的に、すべてのデータベース表には、ROWID というバイナリ値を格納する ROWID 疑似列
があります。各 ROWID は、行の記憶域アドレスを表します。物理 ROWID は、通常の表の行
を識別します。論理 ROWID は、索引構成表の行を識別します。ROWID データ型には物理
ROWID のみを格納できます。ただし、UROWID(ユニバーサル ROWID)データ型には物理
ROWID、論理 ROWID、外部(非 Oracle)ROWID を格納できます。
注意 : ROWID データ型は、古いアプリケーションとの下位互換性のため
のみに使用してください。新しいアプリケーションの場合には、UROWID
データ型を使用します。
ROWID を選択またはフェッチして ROWID 変数に入れる場合は、バイナリ値を 18 バイトの文
字列に変換する組込みファンクション ROWIDTOCHAR を使用します。逆に、ファンクション
CHARTOROWID は ROWID 文字列を ROWID に変換します。文字列が有効な ROWID を表してい
ないために変換が失敗すると、PL/SQL は事前定義の例外 SYS_INVALID_ROWID を発生しま
す。これは、暗黙的な変換にも適用されます。
UROWID 変数と文字列間で変換するには、ファンクション・コールなしで通常の代入文を使用
します。値は、UROWID とキャラクタ・タイプの間で暗黙的に変換されます。
物理 ROWID 物理 ROWID を使用すると、特定の行にすばやくアクセスできます。物理 ROWID
は、その行が存在するかぎり変わりません。ROWID は効率的で安定しているため、行の集合
を選択し、集合全体を操作してサブセットを更新するのに便利です。たとえば、UPDATE 文ま
たは DELETE 文の WHERE 句の中で UROWID 変数と ROWID 疑似列を比較して、カーソルから
フェッチされた最新の行を識別できます。6-34 ページの「コミットにまたがるフェッチ」を参
照してください。
物理 ROWID には 2 つの形式があります。10 バイトの拡張 ROWID 形式は相対表領域ブロッ
ク・アドレスをサポートしており、パーティション化表と非パーティション化表の行を識別で
きます。6 バイトの制限 ROWID 形式は、下位互換性のために用意されています。
拡張 ROWID は、選択された各行の物理アドレスの base-64 エンコーディングを使用します。
たとえば、ROWID を暗黙的に文字列に変換する SQL*Plus での次の問合せを考えてみます。
SELECT rowid, last_name FROM employees WHERE employee_id = 120;
これは、次の行を戻します。
ROWID
LAST_NAME
------------------ ------------------------AAALktAAFAAAABSAAU Weiss
形式 OOOOOOFFFBBBBBBRRR は、4 つの部分に分かれています。
■
■
■
■
OOOOOO: データ・オブジェクト番号(上の例では AAALkt)。データベース・セグメントを
示します。表のクラスタなど、同じセグメント中のスキーマ・オブジェクトのデータ・オ
ブジェクト番号は同じです。
FFF: ファイル番号(上の例では AAF)
。その行が格納されているデータ・ファイルを示し
ます。ファイル番号はデータベース内で一意です。
BBBBBB: ブロック番号(上の例では AAAABS)。その行が格納されているデータ・ブロック
を示します。ブロック番号は、その表領域ではなく、データ・ファイルに対応します。こ
のため、同じ表領域内の異なるデータ・ファイルにある 2 つの行は、同じブロック番号を
持つことができます。
RRR: 行番号(上の例では AAU)
。ブロック内の行を示します。
PL/SQL のデータ型
3-7
事前定義された PL/SQL データ型の概要
論理 ROWID 論理 ROWID を使用すると、特定の行に最も早くアクセスできます。Oracle は論
理 ROWID を使用して索引構成表の 2 次索引を組み立てます。論理 ROWID は恒久物理アドレ
スを持たないため、新しい行が挿入されると複数のデータ・ブロックの間を移動できます。た
だし、行の物理的な位置が変わった場合、その論理 ROWID は有効なまま残ります。
論理 ROWID には不確定要素を含めることができます。これは推測が行われたときの行のブ
ロック位置を識別します。Oracle は全体のキー検索をせずに、不確定要素を使用してブロック
を直接検索します。ただし新しい行が挿入されると、不確定要素は古くなって行へのアクセス
の処理速度が遅くなります。新しい不確定要素を得るには、2 次索引を再作成します。
ROWID 疑似列を使用して、索引構成表から論理 ROWID(これは不透明値です)を選択できま
す。また、最大サイズが 4000 バイトの UROWID 型の列に論理 ROWID を挿入できます。
ANALYZE 文は、推測の古さを追跡するために役立ちます。これは、推測を持つ ROWID を
UROWID 列に格納し、その ROWID を使用して行をフェッチするアプリケーションの場合に便
利です。
ROWID を操作するには、提供されているパッケージ DBMS_ROWID を使用します。詳細は、
『Oracle Database PL/SQL パッケージ・プロシージャおよびタイプ・リファレンス』を参照し
てください。
VARCHAR2 データ型
VARCHAR2 データ型は可変長の文字データを格納するために使用します。データの内部表現形
式は、データベース・キャラクタ・セットによって異なります。VARCHAR2 データ型は必須パ
ラメータを使用して、その最大サイズを 32767 バイトまで指定できます。次に構文を示します。
VARCHAR2(maximum_size [CHAR
|
BYTE])
最大サイズには 1 ~ 32767 の範囲の整数リテラルを指定します。シンボリック定数や変数は指
定できません。
VARCHAR2 変数が小さい場合はパフォーマンスに合わせて最適化され、大きい場合は効率的な
メモリー使用に合わせて最適化されます。分離点は 2000 バイトです。長さ 2000 バイト以上の
VARCHAR2 の場合、PL/SQL は実際の値を保持するために必要なだけのメモリーを動的に割り
当てます。長さ 2000 バイト未満の VARCHAR2 変数の場合は、変数の宣言済の長さ全体が事前
に割り当てられます。たとえば VARCHAR2(2000 BYTE) 変数と VARCHAR2(1999 BYTE) 変
数に同じ 500 バイトの値を割り当てると、前者の変数は 500 バイト、後者は 1999 バイトのメモ
リーを使用することになります。
最大サイズを文字数ではなくバイト数で指定すると、VARCHAR2(n) 変数が小さすぎて n 個の
マルチバイト文字を保持できないことがあります。この可能性を回避するには、データベー
ス・キャラクタ・セットの一部の文字に複数のバイトが含まれていても、変数で n 個の文字を
保持できるように、表記法 VARCHAR2(n CHAR) を使用します。文字数の長さを指定する場
合の上限は、32767 バイトです。ダブルバイトおよびマルチバイトのキャラクタ・セットの場
合、指定できるのは、シングルバイト・キャラクタ・セットの 1/2 または 1/3 の文字のみで
す。
PL/SQL の文字変数は比較的長くなりがちですが、4000 バイトを超える VARCHAR2 値は
VARCHAR2 データベース列に挿入できません。
LONG 列の最大幅は 2147483648 バイト(2GB)であるため、すべての VARCHAR2(n) 値を
LONG データベース列に格納できます。ただし、LONG 列から 32768 バイト以上の値を取り出し
て VARCHAR2(n) に入れることはできません。LONG データ型は、下位互換性のためにのみ使
用してください。詳細は、3-6 ページの「LONG および LONG RAW データ型」を参照してく
ださい。
CHAR または BYTE 修飾子を使用しなければ、デフォルトは NLS_LENGTH_SEMANTICS 初期化
パラメータの設定によって決定されます。PL/SQL プロシージャのコンパイル時には、このパ
ラメータの設定が記録されるため、プロシージャが無効になった後に再コンパイルするときに
も同じ設定が使用されます。
3-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
事前定義された PL/SQL データ型の概要
VARCHAR2 サブタイプ VARCHAR2 のサブタイプ STRING および VARCHAR の値は、そのベース
型と同じ範囲をとります。たとえば、VARCHAR は VARCHAR2 の別名です。
VARCHAR2 のサブタイプは、ANSI/ISO 型と IBM 型に対する互換性を保つ目的で用意された
データ型です。
現在のところ、VARCHAR は VARCHAR2 と同義です。ただし、PL/SQL の今後のリリースでの
VARCHAR は、SQL 標準に従うために比較時の意味が異なる別個のデータ型になる可能性があり
ます。VARCHAR ではなく VARCHAR2 を使用することをお薦めします。
PL/SQL の各国語キャラクタ・タイプ
よく使用される 1 バイトの ASCII と EBCDIC のキャラクタ・セットはアルファベットを表示す
るには十分ですが、日本語などのアジアの言語には何千もの文字があります。これらの言語で
は、1 文字を表すために 2 バイトまたは 3 バイトが必要です。Oracle にはグローバリゼーショ
ン・サポートが用意されており、シングルバイト文字データとマルチバイト文字データを処理
したり、キャラクタ・セット間で変換することができます。また、アプリケーションを複数の
異なる言語環境で実行できます。
グローバリゼーション・サポートによって、数字と日付の形式は、ユーザー・セッションで指
定されている言語の規則に自動的に合わせられます。したがって、世界中のユーザーは Oracle
を使用して母国語で対話できます。
PL/SQL は、識別子およびソース・コードに使用される データベース・キャラクタ・セット
と、各国語データに使用される各国語キャラクタ・セットの 2 つのキャラクタ・セットをサ
ポートしています。データ型 NCHAR と NVARCHAR2 は、各国語キャラクタ・セットから構成さ
れる文字列を格納できます。
CHAR データまたは VARCHAR2 データをキャラクタ・セットが異なるデータベース間で変換す
る場合は、データが適切な形式の文字列で構成されていることを確認してください。CHAR また
は VARCHAR2 データの詳細は、
『Oracle Database グローバリゼーション・サポート・ガイド』
を参照してください。
UTF8 および AL16UTF16 エンコーディング
各国語キャラクタ・セットでは、データは UTF8 または AL16UTF16 エンコーディングを使用
して Unicode として表されます。
AL16UTF16 エンコーディングの場合、各文字は 2 バイトです。このため、異なるプログラミン
グ言語が混在する場合に、文字列長を計算して切捨てエラーを回避するのは簡単ですが、ほと
んどが ASCII 文字で構成される文字列を格納するために余分なストレージ・オーバーヘッドを
必要とします。
UTF8 エンコーディングの場合、各文字は 1、2 または 3 バイトです。このため、ほとんどの文
字を 1 バイトで表せる場合にのみ、変数や表の列に、より多数の文字を入れることができます。
データをバイト単位のバッファに転送すると、切捨てエラーになる可能性があります。
実行時に最大限の信頼性が得られるように、できるかぎりデフォルトの AL16UTF16 エンコー
ディングを使用することをお薦めします。Unicode 文字列の保持に必要なバイト数を判断する
場合は、LENGTH ではなく LENGTHB ファンクションを使用してください。
NCHAR データ型
NCHAR データ型は、固定長の(必要に応じて空白埋めされる)各国語キャラクタ・データを格
納するために使用します。データの内部表現形式は、データベースの作成時に指定した各国語
キャラクタ・セット、つまり、可変幅のエンコーディング(UTF8)を使用するか、それとも固
定幅のエンコーディング(AL16UTF16)を使用するかによって異なります。この型は常にマル
チバイト文字に対処できるため、Unicode データの保持に使用できます。
NCHAR データ型はオプション・パラメータを使用して、その最大サイズを文字数で指定できま
す。次に構文を示します。
NCHAR[(maximum_size)]
PL/SQL のデータ型
3-9
事前定義された PL/SQL データ型の概要
物理的な上限は 32767 バイトのため、長さに指定できる最大値は、AL16UTF16 エンコーディン
グの場合は 32767/2、UTF8 エンコーティングの場合は 32767/3 です。
最大サイズには整数リテラルを指定します。シンボリック定数や変数は指定できません。
最大サイズを指定しなければ、デフォルトの 1 が使用されます。CHAR では文字数またはバイト
数で指定できますが、この値は常に文字数を表します。
v_string NCHAR(100);
-- 最大値は 100 文字
長さ 2001 バイト以上の NCHAR 値は NCHAR 型の列に挿入できません。
NCHAR 値が NCHAR 列の定義された幅より短ければ、Oracle は定義幅まで値を空白で埋めます。
CHAR および NCHAR 値は、文と式の中で交換できます。常に安全に CHAR 値が NCHAR 値になり
ますが、CHAR 値のキャラクタ・セットで NCHAR 値のすべての文字を表すことができない場合
は、NCHAR 値を CHAR 値にするとデータが失われる場合があります。このようなデータの消失
が発生すると、各文字では通常は疑問符(?)のようになります。
NVARCHAR2 データ型
NVARCHAR2 データ型は、可変長の Unicode 文字データの格納に使用します。データの内部表
現形式は、データベースの作成時に指定した各国語キャラクタ・セット、つまり、可変幅のエ
ンコーディング(UTF8)を使用するか、それとも固定幅のエンコーディング(AL16UTF16)
を使用するかによって異なります。この型は常にマルチバイト文字に対処できるため、
Unicode データの保持に使用できます。
NVARCHAR2 データ型は必須パラメータを使用して、その最大サイズを文字数で指定できます。
次に構文を示します。
NVARCHAR2(maximum_size)
物理的な上限は 32767 バイトのため、長さに指定できる最大値は、AL16UTF16 エンコーディン
グの場合は 32767/2、UTF8 エンコーティングの場合は 32767/3 です。
最大サイズには整数リテラルを指定します。シンボリック定数や変数は指定できません。
最大サイズを文字数またはバイト数で指定できる VARCHAR2 とは異なり、最大サイズは常に文
字数を表します。
v_string NVARCHAR2(200); -- 最大値は 200 文字
NVARCHAR2 データベース列の最大幅は 4000 バイトです。このため、4000 バイトよりも長い
NVARCHAR2 値を NVARCHAR2 型の列に挿入できません。
VARCHAR2 および NVARCHAR2 値は、文と式の中で交換できます。VARCHAR2 値を NVARCHAR2
値にするのは常に問題ありませんが、NVARCHAR2 値のすべての文字が VARCHAR2 値のキャラ
クタ・セットで表せるとはかぎらない場合は、NVARCHAR2 値を VARCHAR2 値にするとデータ
が失われる場合があります。このようなデータの消失が発生すると、各文字では通常は疑問符
(?)のようになります。
PL/SQL LOB 型
LOB(ラージ・オブジェクト)データ型 BFILE、BLOB、CLOB および NCLOB は、構造化されて
いないデータ(テキスト、図形イメージ、ビデオ・クリップ、サウンド・ウェーブ形式など)
のブロックを格納するために使用します。LOB によって、効率的、かつランダムで、断片的な
データへのアクセスができます。BLOB、CLOB および NCLOB のサイズは、8 ~ 128TB です。
BFILE のサイズはシステムによって異なりますが、4GB(4GB - 1 バイト)を超えるものは使用
できません。
LOB 型は、いくつかの点で LONG 型と LONG RAW 型とは異なります。たとえば、LOB(NCLOB
を除く)はオブジェクト型の属性として使用できますが、LONG は使用できません。BLOB、
CLOB または NCLOB の最大サイズは、8 ~ 128TB ですが、LONG の最大サイズは 2GB です。ま
た、LOB ではデータのランダム・アクセスがサポートされていますが、LONG では順次アクセ
スしかサポートされていません。LONG データ型および LONG RAW データ型は、下位互換性のた
めにのみ使用してください。詳細は、3-6 ページの「LONG および LONG RAW データ型」を
参照してください。
3-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
事前定義された PL/SQL データ型の概要
LOB 型には LOB ロケータが格納されます。これは、外部ファイル、インライン(行内部)、ま
たはライン外(行外部)に格納される大きなオブジェクトの位置を指定するものです。BLOB
型、CLOB 型、NCLOB 型または BFILE 型のデータベース列にはロケータが格納されます。
BLOB データ、CLOB データおよび NCLOB データは、データベース内の行内部または行外部に
格納されます。BFILE データは、データベース外のオペレーティング・システム・ファイルに
格納されます。
PL/SQL の LOB は、ロケータによって操作されます。たとえば、BLOB 列の値を選択した場合、
ロケータのみが戻されます。トランザクション中に取得した場合、LOB ロケータにはトランザ
クション ID が含まれるため、別のトランザクションの LOB の更新にはその LOB ロケータを使
用できません。同様にあるセッション中に LOB ロケータを保管してから、それを別のセッショ
ンで使用することはできません。
CLOB と CHAR および VARCHAR2 型との間の変換や、BLOB と RAW との間の変換も可能です。
このため、LOB 型はほとんどの SQL および PL/SQL の文とファンクションに使用できます。
LOB の読取り、書込みおよびピース単位の操作を行うには、オラクル社が提供するパッケージ
DBMS_LOB を使用できます。
LOB の詳細は、
『Oracle Database アプリケーション開発者ガイド - ラージ・オブジェクト』を
参照してください。
BFILE データ型
BFILE データ型は、データベース外のオペレーティング・システム・ファイルに大規模なバイ
ナリ・オブジェクトを格納するために使用します。どの BFILE 変数にも、サーバー上の大規模
なバイナリ・ファイルを指すファイル・ロケータが格納されています。ロケータには、フルパ
ス名を指定するディレクトリ別名が含まれています。論理パス名はサポートされていません。
BFILE は読取り専用です。変更はできません。指定された BFILE が存在し、Oracle にその読
取り許可があることは、DBA によって保証されます。基礎となるオペレーティング・システム
がファイルの整合性を維持します。
BFILE はトランザクションには関与せず、リカバリ可能ではなく、レプリケートできません。
オープンする BFILE の最大数は、Oracle 初期化パラメータ SESSION_MAX_OPEN_FILES に設
定され、システムによって異なります。
BLOB データ型
BLOB データ型は、データベース内の行内部または行外部に大規模なバイナリ・オブジェクトを
格納するために使用します。どの BLOB 変数にも、大規模なバイナリ・オブジェクトを指すロ
ケータが格納されます。
BLOB はトランザクションに完全に関与し、リカバリ可能で、レプリケートできます。パッケー
ジ DBMS_LOB によって行われた変更は、コミットまたはロールバックできます。BLOB ロケー
タは複数の(読取り専用)トランザクションにまたがることはできますが、複数のセッション
にはまたがることができません。
CLOB データ型
CLOB データ型は、文字データの大規模なブロックを、データベース内の行内部または行外部に
格納するために使用します。固定幅と可変幅の、両方のキャラクタ・セットがサポートされて
います。どの CLOB 変数にも、文字データの大規模なブロックを指すロケータが格納されます。
CLOB はトランザクションに完全に関与し、リカバリ可能で、レプリケートできます。パッケー
ジ DBMS_LOB によって行われた変更は、コミットまたはロールバックできます。CLOB ロケー
タは複数の(読取り専用)トランザクションにまたがることはできますが、複数のセッション
にはまたがることができません。
PL/SQL のデータ型
3-11
事前定義された PL/SQL データ型の概要
NCLOB データ型
NCLOB データ型は、NCHAR データの大規模なブロックを、データベース内の行内部または行外
部に格納するために使用します。固定幅と可変幅の、両方のキャラクタ・セットがサポートさ
れています。どの NCLOB 変数にも、NCHAR データの大規模なブロックを指すロケータが格納
されます。
NCLOB はトランザクションに完全に関与し、リカバリ可能で、レプリケートできます。パッ
ケージ DBMS_LOB によって行われた変更は、コミットまたはロールバックできます。NCLOB ロ
ケータは複数の(読取り専用)トランザクションにまたがることはできますが、複数のセッ
ションにはまたがることができません。
PL/SQL のブール型
PL/SQL には、ブール値(TRUE と FALSE)を表現するための型があります。SQL には同等の
型がないため、BOOLEAN 変数とパラメータは、PL/SQL コンテキスト内では使用できますが、
SQL 文または SQL 問合せでは使用できません。
BOOLEAN データ型
BOOLEAN データ型は、論理値 TRUE と FALSE、および NULL(存在しない値、未知の値または
適用不可能な値を表す)を格納するために使用します。BOOLEAN 変数で可能な操作は論理操作
のみです。
BOOLEAN データ型はパラメータを取りません。BOOLEAN 変数に代入できるのは、値 TRUE、
FALSE および NULL のみです。
データベース列には値 TRUE や FALSE を挿入できません。列の値を選択またはフェッチして
BOOLEAN 変数に入れることはできません。SQL 問合せからのファンクション・コールに、
BOOLEAN パラメータは使用できません。TO_CHAR などの組込み SQL ファンクションでも
BOOLEAN 値を出力できないため、IF-THEN 文または CASE 文を使用して、BOOLEAN 値を 0 か
1、Y か N、TRUE か FALSE などの別の型に変換する必要があります。
PL/SQL の日付型、時刻型および時間隔型
この項で説明するデータ型を使用すると、日付、時刻および時間隔(期間)を格納し、操作で
きます。日付および時刻データ型の変数には日時と呼ばれる値が保持されます。時間隔データ
型の変数には時間隔と呼ばれる値が保持されます。日時または時間隔は、その値を決定する
フィールドで構成されます。次のリストに、各フィールドの有効値を示します。
3-12
フィールド名
有効な日時値
有効な時間隔値
YEAR
-4712 ~ 9999(年 0 を除く)
0 以外の任意の整数
MONTH
01 ~ 12
0 ~ 11
DAY
01 ~ 31(ロケールのカレンダの規則
に従って MONTH および YEAR の値に
よる制限付き)
0 以外の任意の整数
HOUR
00 ~ 23
0 ~ 23
MINUTE
00 ~ 59
0 ~ 59
SECOND
00 ~ 59.9(n)、9(n) は時刻の秒の精度
0 ~ 59.9(n)、9(n) は時間隔の秒の
精度
TIMEZONE_HOUR
-12 ~ 14(範囲は夏時間の変更に
対応)
該当なし
TIMEZONE_MINUTE
00 ~ 59
該当なし
TIMEZONE_REGION
ビュー V$TIMEZONE_NAMES に表示
該当なし
TIMEZONE_ABBR
ビュー V$TIMEZONE_NAMES に表示
該当なし
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
事前定義された PL/SQL データ型の概要
TIMESTAMP WITH LOCAL TIMEZONE を除き、前述の型はすべて SQL92 規格の一部です。日
時および時間隔のフォーマット・モデル、リテラル、タイムゾーン名および SQL ファンクショ
ンの詳細は、
『Oracle Database SQL リファレンス』を参照してください。
DATE データ型
DATE データ型は、午前 0 時からの経過秒数を含む固定長の日時の格納に使用します。デフォル
トでは、日付部分は現在の月の最初の日であり、時刻の部分は午前 0 時です。日付関数
SYSDATE は、現在の日付と時刻を戻します。
■
■
日付の等価性を各日付の時刻の部分に関係なく比較するには、比較、GROUP BY 操作など
にファンクションの結果 TRUNC(date_variable) を使用します。
DATE 変数の時刻の部分のみを確認するには、日付の部分を引きます(date_variable
- TRUNC(date_variable))。
使用できる日付は、紀元前 4712 年 1 月 1 日から西暦 9999 年 12 月 31 日までです。ユリウス日
付は、紀元前 4712 年 1 月 1 日からの日数です。ユリウス日付によって、共通の参照元からの連
続した日付が可能になります。日付関数 TO_DATE と TO_CHAR で日付書式モデル 'J' を使用
すると、DATE 値とそれに対応するユリウス日付の値の間で変換できます。
日付式の中では、デフォルトの日付書式の文字値は自動的に DATE 値に変換されます。デフォ
ルトの日付書式は、Oracle 初期化パラメータ NLS_DATE_FORMAT によって設定されます。たと
えば、デフォルトは 'DD-MON-YY' であり、これは 2 桁数字の日、月の省略名、年数の下 2 桁
を含むものということです。
日付に対しては加算および減算ができます。算術式の中では、PL/SQL は整数リテラルを日数
として解釈します。たとえば、SYSDATE + 1 は、次の日の同じ時刻ということです。
TIMESTAMP データ型
TIMESTAMP データ型は DATE データ型への拡張であり、年、月、日、時間、分および秒が格納
されます。次に構文を示します。
TIMESTAMP[(precision)]
オプションの precision パラメータでは、秒のフィールドの小数部の桁数を指定します。精
度には 0 ~ 9 の範囲の整数リテラルを指定します。シンボリック定数や変数は指定できません。
デフォルトは 6 です。
デフォルトのタイムスタンプ日付書式は、Oracle 初期化パラメータ NLS_TIMESTAMP_FORMAT
によって設定されます。
例 3-1 では、TIMESTAMP 型の変数を宣言してからリテラル値を代入しています。この例では、
秒フィールドの小数部は 0.275 です。
例 3-1 TIMESTAMP 変数へのリテラル値の代入
DECLARE
checkout TIMESTAMP(3);
BEGIN
checkout := '22-JUN-2004 07:48:53.275';
DBMS_OUTPUT.PUT_LINE( TO_CHAR(checkout));
END;
/
例 3-2 では、SCN_TO_TIMESTAMP および TIMESTAMP_TO_SCN ファンクションは、
TIMESTAMP を操作するために使用されます。
例 3-2 SCN_TO_TIMESTAMP および TIMESTAMP_TO_SCN ファンクションの使用
DECLARE
right_now TIMESTAMP;
yesterday TIMESTAMP;
sometime TIMESTAMP;
scn1 INTEGER;
PL/SQL のデータ型
3-13
事前定義された PL/SQL データ型の概要
scn2 INTEGER;
scn3 INTEGER;
BEGIN
right_now := SYSTIMESTAMP; -- Get the current SCN
scn1 := TIMESTAMP_TO_SCN(right_now);
DBMS_OUTPUT.PUT_LINE('Current SCN is ' || scn1);
yesterday := right_now - 1; -- Get the SCN from exactly 1 day ago
scn2 := TIMESTAMP_TO_SCN(yesterday);
DBMS_OUTPUT.PUT_LINE('SCN from yesterday is ' || scn2);
-- Find an arbitrary SCN somewhere between yesterday and today
-- In a real program we would have stored the SCN at some significant moment
scn3 := (scn1 + scn2) / 2;
sometime := SCN_TO_TIMESTAMP(scn3); -- What time was that SCN was in effect?
DBMS_OUTPUT.PUT_LINE('SCN ' || scn3 || ' was in effect at ' ||
TO_CHAR(sometime));
END;
/
TIMESTAMP WITH TIME ZONE データ型
TIMESTAMP WITH TIME ZONE データ型は、TIMESTAMP データ型への拡張であり、タイムゾー
ンによる時差を含みます。タイムゾーンによる時差とは、現地時間と協定世界時(UTC、旧称
はグリニッジ標準時)の時差(時間および分単位)です。次に構文を示します。
TIMESTAMP[(precision)] WITH TIME ZONE
オプションの precision パラメータでは、秒のフィールドの小数部の桁数を指定します。精
度には 0 ~ 9 の範囲の整数リテラルを指定します。シンボリック定数や変数は指定できません。
デフォルトは 6 です。
デフォルトのタイムゾーン付きタイムスタンプの書式は、Oracle 初期化パラメータ
NLS_TIMESTAMP_TZ_FORMAT によって設定されます。
例 3-3 では、TIMESTAMP WITH TIME ZONE 型の変数を宣言してからリテラル値を代入していま
す。
例 3-3 TIMESTAMP WITH TIME ZONE 変数へのリテラル値の代入
DECLARE
logoff TIMESTAMP(3) WITH TIME ZONE;
BEGIN
logoff := '10-OCT-2004 09:42:37.114 AM +02:00';
DBMS_OUTPUT.PUT_LINE( TO_CHAR(logoff));
END;
/
この例では、タイムゾーンによる時差は +02:00 です。
また、シンボリック名でタイムゾーンを指定することもできます。この指定には、
'US/Pacific' などの長い形式、'PDT' などの省略形またはその組合せを使用できます。た
とえば、次のリテラルはいずれも同じ時刻を表します。3 番目は、夏時間に切り替わった時点
で適用される規則を指定しているため、最も信頼性の高い書式です。
TIMESTAMP '15-APR-2004 8:00:00 -8:00'
TIMESTAMP '15-APR-2004 8:00:00 US/Pacific'
TIMESTAMP '31-OCT-2004 01:30:00 US/Pacific PDT'
タイムゾーンに使用可能な名前は、V$TIMEZONE_NAMES データ・ディクショナリ・ビューの
TIMEZONE_REGION および TIMEZONE_ABBR 列にあります。
3-14
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
事前定義された PL/SQL データ型の概要
2 つの TIMESTAMP WITH TIME ZONE 値は、UTC で同じ時間を表していれば、タイムゾーンに
よる時差に関係なく同一とみなされます。たとえば、UTC の太平洋標準時で午前 8:00 は東部標
準時の午前 11:00 と同じであるため、次の 2 つの値は同一とみなされます。
'29-AUG-2004 08:00:00 -8:00'
'29-AUG-2004 11:00:00 -5:00'
TIMESTAMP WITH LOCAL TIME ZONE データ型
TIMESTAMP WITH LOCAL TIME ZONE データ型は、TIMESTAMP データ型の拡張であり、タイム
ゾーンによる時差を含みます。タイムゾーンによる時差とは、現地時間と協定世界時(UTC、
旧称はグリニッジ標準時)の時差(時間および分単位)です。TIMESTAMP WITH TIME ZONE
と同様に、名前付きのタイム・ゾーンも使用できます。
次に構文を示します。
TIMESTAMP[(precision)] WITH LOCAL TIME ZONE
オプションの precision パラメータでは、秒のフィールドの小数部の桁数を指定します。精
度には 0 ~ 9 の範囲の整数リテラルを指定します。シンボリック定数や変数は指定できません。
デフォルトは 6 です。
このデータ型は、TIMESTAMP WITH TIME ZONE とは異なり、データベース列に値を挿入する
と、値はデータベースのタイム・ゾーンに正規化され、タイムゾーンによる時差は列に格納さ
れません。値を取り出すときには、ローカル・セッションのタイム・ゾーンで戻されます。
例 3-4 では、TIMESTAMP WITH LOCAL TIME ZONE 型の変数を宣言しています。
例 3-4 TIMESTAMP WITH LOCAL TIME ZONE へのリテラル値の代入
DECLARE
logoff TIMESTAMP(3) WITH LOCAL TIME ZONE;
BEGIN
-logoff := '10-OCT-2004 09:42:37.114 AM +02:00'; raises an error
logoff := '10-OCT-2004 09:42:37.114 AM '; -- okay without displacement
DBMS_OUTPUT.PUT_LINE( TO_CHAR(logoff));
END;
/
INTERVAL YEAR TO MONTH データ型
INTERVAL YEAR TO MONTH データ型は、年および月の時間隔を格納し、操作するために使用し
ます。次に構文を示します。
INTERVAL YEAR[(precision)] TO MONTH
precision では、年フィールドの桁数を指定します。精度には 0 ~ 4 の範囲の整数リテラルを指
定します。シンボリック定数や変数は指定できません。デフォルトは 2 です。
例 3-5 では、INTERVAL YEAR TO MONTH 型の変数を宣言してから、101 年および 3 月の値を代
入しています。
例 3-5 INTERVAL YEAR TO MONTH 変数へのリテラルの代入
DECLARE
lifetime
BEGIN
lifetime
lifetime
lifetime
lifetime
END;
/
INTERVAL YEAR(3) TO MONTH;
:=
:=
:=
:=
INTERVAL
'101-3';
INTERVAL
INTERVAL
'101-3' YEAR TO MONTH; -- interval literal
-- implicit conversion from character type
'101' YEAR; -- Can specify just the years
'3' MONTH; -- Can specify just the months
PL/SQL のデータ型
3-15
事前定義された PL/SQL データ型の概要
INTERVAL DAY TO SECOND データ型
INTERVAL DAY TO SECOND データ型は、日、時間、分および秒の時間隔を格納し、操作するた
めに使用します。次に構文を示します。
INTERVAL DAY[(leading_precision)]
TO SECOND[(fractional_seconds_precision)]
leading_precision および fractional_seconds_precision では、それぞれ日付
フィールドと秒フィールドの桁数を指定します。どちらの場合も、精度には 0 ~ 9 の範囲の整
数リテラルを指定します。シンボリック定数や変数は指定できません。デフォルトはそれぞれ
2 および 6 です。
例 3-6 では、INTERVAL DAY TO SECOND 型の変数を宣言しています。
例 3-6 INTERVAL DAY TO SECOND 変数へのリテラルの代入
DECLARE
lag_time INTERVAL DAY(3) TO SECOND(3);
BEGIN
lag_time := '7 09:24:30';
IF lag_time > INTERVAL '6' DAY THEN
DBMS_OUTPUT.PUT_LINE ( 'Greater than 6 days');
ELSE
DBMS_OUTPUT.PUT_LINE ( 'Less than 6 days');
END IF;
END;
/
日時および時間隔の演算
PL/SQL では、日時式と時間隔式を作成できます。この種の式に使用できる演算子を次のリス
トに示します。
オペランド 1
演算子
オペランド 2
結果タイプ
日時
+
時間隔
日時
日時
-
時間隔
日時
時間隔
+
日時
日時
日時
-
日時
時間隔
時間隔
+
時間隔
時間隔
時間隔
-
時間隔
時間隔
時間隔
*
数値
時間隔
数値
*
時間隔
時間隔
時間隔
/
数値
時間隔
また、EXTRACT などの各種ファンクションを使用して日時値を操作することもできます。この
種のファンクションのリストは、2-38 ページの表 2-4「 組込みファンクション」を参照してく
ださい。
日時の演算例の詳細は、
『Oracle Database SQL リファレンス』および『Oracle Database アプリ
ケーション開発者ガイド - 基礎編』を参照してください。
3-16
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL サブタイプの概要
日付および時刻のサブタイプを使用する場合の切捨て問題の回避
日時の型のデフォルト精度は、最大精度より低い場合があります。たとえば、DAY TO
SECOND のデフォルトは DAY(2) TO SECOND(6) ですが、最大精度は DAY(9) TO
SECOND(9) です。この種の型の変数を代入し、プロシージャのパラメータを渡す場合に切り捨
てを防ぐためには、次のサブタイプの変数とプロシージャのパラメータを宣言できます。各サ
ブタイプでは、精度に最大値が使用されます。
TIMESTAMP_UNCONSTRAINED
TIMESTAMP_TZ_UNCONSTRAINED
TIMESTAMP_LTZ_UNCONSTRAINED
YMINTERVAL_UNCONSTRAINED
DSINTERVAL_UNCONSTRAINED
PL/SQL サブタイプの概要
PL/SQL のベース型はそれぞれ、その型の項目に適用可能な値のセットや演算のセットを指定
します。サブタイプは、そのベース型と同じ演算のセットを指定しますが、指定する値はベー
ス型のサブセットのみです。サブタイプは新しい型を導入するためのものではありません。単
にそのベース型に対してオプションの制約を定義するためのものです。
サブタイプを使用すると、信頼性が向上し、ANSI/ISO 型との互換性が保たれ、さらに定数や
変数の使用意図を示すことで読みやすさが向上します。PL/SQL では、パッケージ STANDARD
の中にいくつかのサブタイプが事前に定義されています。たとえば、PL/SQL では、サブタイ
プ CHARACTER および INTEGER が次のようにあらかじめ定義されています。
SUBTYPE CHARACTER IS CHAR;
SUBTYPE INTEGER IS NUMBER(38,0); -- 整数のみ可
サブタイプ CHARACTER は、そのベース型 CHAR と同じ値の集合を指定します。したがって、
CHARACTER は無制約サブタイプです。ただし、サブタイプ INTEGER は、そのベース・タイプ
NUMBER の値のサブセットのみを指定するため、INTEGER は制約付きサブタイプです。
サブタイプの定義
ユーザー独自のサブタイプは、次の構文を使用して、任意の PL/SQL ブロック、サブプログラ
ムまたはパッケージの宣言部で定義できます。
SUBTYPE subtype_name IS base_type[(constraint)] [NOT NULL];
ここで subtype_name は後続の宣言で使用される型指定子です。base_type は任意のスカ
ラーまたはユーザー定義の PL/SQL データ型で、constraint は精度、およびスケールまたは
最大サイズを指定できるベース型にのみ適用されます。デフォルト値は許可されていない点に
注意して、3-19 ページの例 3-10 を参照してください。
次に例を示します。
DECLARE
SUBTYPE BirthDate IS DATE NOT NULL; -- based on DATE type
SUBTYPE Counter IS NATURAL;
-- based on NATURAL subtype
TYPE NameList IS TABLE OF VARCHAR2(10);
SUBTYPE DutyRoster IS NameList;
-- based on TABLE type
TYPE TimeRec IS RECORD (minutes INTEGER, hours INTEGER);
SUBTYPE FinishTime IS TimeRec;
-- based on RECORD type
SUBTYPE ID_Num IS employees.employee_id%TYPE; -- based on column type
%TYPE または %ROWTYPE を使用してベース型を指定できます。%TYPE がデータベース列の
データ型を提供する場合、サブタイプはその列のサイズ制約(存在する場合)を継承します。
サブタイプでは、3-19 ページの例 3-11 に示すとおり、NOT NULL、チェック制約、デフォルト
値のような他の種類の制約は継承しません。詳細は、2-10 ページの「%TYPE 属性の使用」およ
び 2-11 ページの「%ROWTYPE 属性の使用」を参照してください。
PL/SQL のデータ型
3-17
PL/SQL サブタイプの概要
サブタイプの使用
サブタイプを定義すると、その型の項目を宣言できます。次の例では、Counter 型の変数を宣
言しています。変数の使用意図がサブタイプ名によってどのように示されているかに注意して
ください。
DECLARE
SUBTYPE Counter IS NATURAL;
rows Counter;
ユーザー定義のサブタイプに属する変数を宣言する場合に、そのサブタイプについて制約を設
定できます。
DECLARE
SUBTYPE Accumulator IS NUMBER;
total Accumulator(7,2);
サブタイプを使用すると、範囲外の値を検出でき、信頼性が向上します。例 3-7 では、-9 ~ 9
の範囲の整数を格納するようにサブタイプ pinteger を制限しています。プログラムで
pinteger 変数の範囲外の数値を格納しようとすると、PL/SQL によって例外が呼び出されま
す。
例 3-7 サブタイプを使用した範囲の使用
DECLARE
v_sqlerrm VARCHAR2(64);
SUBTYPE pinteger IS PLS_INTEGER RANGE -9 .. 9;
y_axis pinteger;
PROCEDURE p (x IN pinteger) IS
BEGIN DBMS_OUTPUT.PUT_LINE (x); END p;
BEGIN
y_axis := 9; -- valid, in range
p(10); -- invalid for procedure p
EXCEPTION
WHEN OTHERS THEN
v_sqlerrm := SUBSTR(SQLERRM, 1, 64);
DBMS_OUTPUT.PUT_LINE('Error: ' || v_sqlerrm);
END;
/
サブタイプのデータ型の互換性
無制約のサブタイプは、そのベース型と互換性があります。たとえば、次のように宣言すると、
amount の値を変換せずに total に代入できます。
例 3-8 NUMBER データ型のデータ型の互換性
DECLARE
SUBTYPE Accumulator IS NUMBER;
amount NUMBER(7,2);
total Accumulator;
BEGIN
amount := 10000.50;
total := amount;
END;
/
異なるサブタイプでも、ベース型が同じならば互換性があります。
DECLARE
SUBTYPE b1 IS
SUBTYPE b2 IS
finished b1;
debugging b2;
3-18
BOOLEAN;
BOOLEAN;
-- Different subtypes,
-- both based on BOOLEAN.
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL サブタイプの概要
BEGIN
finished :=FALSE;
debugging := finished; -- They can be assigned to each other.
END;
/
また、異なるサブタイプの場合、ベース型が同じデータ型の系列ならば互換性があります。た
とえば、次のように宣言すると、verb の値を sentence に代入できます。
DECLARE
SUBTYPE Word IS CHAR(15);
SUBTYPE Text IS VARCHAR2(1500);
verb
Word;
-- Different subtypes
sentence Text(150); -- of types from the same family
BEGIN
verb := 'program';
sentence := verb;
-- can be assigned, if not too long.
END;
/
サブタイプの制約およびデフォルト値
この項の例では、サブタイプの制約およびデフォルト値の使用法を示します。例 3-9 では、プ
ロシージャは NOT NULL 制約を適用しますが、サイズ制約は適用しません。
例 3-9 サブプログラムによる制約の継承
DECLARE
SUBTYPE v_word IS VARCHAR2(10) NOT NULL;
verb
v_word := 'run';
noun
VARCHAR2(10) := NULL;
PROCEDURE word_to_upper (w IN v_word) IS
BEGIN
DBMS_OUTPUT.PUT_LINE (UPPER(w));
END word_to_upper;
BEGIN
word_to_upper('run_over_ten_characters'); -- size constraint is not enforced
-- word_to_upper(noun); invalid, NOT NULL constraint is enforced
END;
/
例 3-10 に、デフォルト値をサブタイプの変数に代入する例を示します。
例 3-10 サブタイプのデフォルト値
DECLARE
SUBTYPE v_word IS VARCHAR2(10) NOT NULL; -- invalid to put default here
verb v_word := 'verb';
noun v_word := 'noun';
BEGIN
DBMS_OUTPUT.PUT_LINE (UPPER(verb));
DBMS_OUTPUT.PUT_LINE (UPPER(noun));
END;
/
例 3-11 に、サブタイプの列制約がどのように継承されるかを示します。
例 3-11 %TYPE および %ROWTYPE での SUBTYPE の使用
CREATE TABLE employees_temp (empid NUMBER(6) NOT NULL PRIMARY KEY,
deptid NUMBER(6) CONSTRAINT check_deptid CHECK (deptid BETWEEN 100 AND 200),
deptname VARCHAR2(30) DEFAULT 'Sales');
DECLARE
PL/SQL のデータ型
3-19
PL/SQL データ型の変換
SUBTYPE v_empid_subtype IS employees_temp.empid%TYPE;
SUBTYPE v_deptid_subtype IS employees_temp.deptid%TYPE;
SUBTYPE v_deptname_subtype IS employees_temp.deptname%TYPE;
SUBTYPE v_emprec_subtype IS employees_temp%ROWTYPE;
v_empid
v_empid_subtype;
v_deptid v_deptid_subtype;
v_deptname v_deptname_subtype;
v_emprec v_emprec_subtype;
BEGIN
v_empid := NULL; -- this works, null constraint is not inherited
-- v_empid := 10000002; -- invalid, number precision too large
v_deptid := 50; -- this works, check constraint is not inherited
-- the default value is not inherited in the following
DBMS_OUTPUT.PUT_LINE('v_deptname: ' || v_deptname);
v_emprec.empid := NULL; -- this works, null constraint is not inherited
-- v_emprec.empid := 10000002; -- invalid, number precision too large
v_emprec.deptid := 50; -- this works, check constraint is not inherited
-- the default value is not inherited in the following
DBMS_OUTPUT.PUT_LINE('v_emprec.deptname: ' || v_emprec.deptname);
END;
/
PL/SQL データ型の変換
あるデータ型の値を別のデータ型に変換することが必要な場合があります。たとえば DATE 変
数をレポートで使用するには、これを文字列に変換する必要があります。データ型の変換につ
いて PL/SQL では、明示的な変換と暗黙的(自動的)な変換がサポートされています。意図し
たとおりにプログラムを動作させるには、できるかぎり明示的な変換を行います。
明示的な変換
値のデータ型を別のデータ型に変換するには、組込みファンクションを使用します。たとえば、
CHAR 値を DATE 値または NUMBER 値に変換するには、それぞれ TO_DATE ファンクションまた
は TO_NUMBER ファンクションを使用します。逆に、DATE 値または NUMBER 値を CHAR 値に変
換するには、TO_CHAR ファンクションを使用します。これらのファンクションの詳細は、
『Oracle Database SQL リファレンス』を参照してください。
明示的な変換を行うと、特にサブプログラムにパラメータを渡す際に、予測しないエラーや
誤った結果の発生を回避することができます。たとえば、TO_CHAR ファンクションを使用する
と、データベースの言語設定にかかわらず、DATE 値の形式を指定できます。|| 演算子で連結
した文字列に算術式を含める場合、算術式をカッコで囲むか、または算術式の周りに TO_CHAR
へのコールを挿入しないかぎり、エラーが発生する可能性があります。
暗黙的な変換
変換して意味がある場合、PL/SQL は暗黙的にデータ型の変換を実行することがあります。こ
の機能によって、ある型のリテラル、変数またはパラメータを、別の型が期待されている箇所
で使用できます。たとえば、通常は文字列を受け取るサブプログラムに数値リテラルを渡すこ
とができます。サブプログラムは、数値の文字列表現を受け取ります。
例 3-12 では、CHAR 型変数である start_time と finish_time に、午前 0 時からの秒数を表
す文字列値が保持されています。これらの値の差を NUMBER 型変数の elapsed_time に代入
する必要があります。PL/SQL は、CHAR 値を NUMBER 値に自動的に変換します。
例 3-12 暗黙的な変換
DECLARE
start_time
CHAR(5);
finish_time CHAR(5);
elapsed_time NUMBER(5);
BEGIN
3-20
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL データ型の変換
/* Get system time as seconds past midnight. */
SELECT TO_CHAR(SYSDATE,'SSSSS') INTO start_time FROM sys.dual;
-- processing done here...
/* Get system time again. */
SELECT TO_CHAR(SYSDATE,'SSSSS') INTO finish_time FROM sys.dual;
/* Compute elapsed time in seconds. */
elapsed_time := finish_time - start_time;
DBMS_OUTPUT.PUT_LINE( 'Elapsed time: ' || TO_CHAR(elapsed_time) );
END;
/
選択された列値を変数に代入する前に、PL/SQL は必要に応じて変換元の列のデータ型を変数
のデータ型に変換します。DATE 列の値を選択して VARCHAR2 変数に入れる場合がこれに該当
します。
同様に、変数の値をデータベース列に代入する前に、PL/SQL は必要に応じてその値を変数の
データ型からターゲット列のデータ型に変換します。PL/SQL では、どのような暗黙的変換が
必要なのかが決定できない場合、コンパイル・エラーが発生します。このような場合は、デー
タ型変換ファンクションを使用する必要があります。表 3-1 に、PL/SQL が実行できる暗黙的
な変換を示します。
注意 :
■
■
■
■
■
表のラベル PLS_INT と BIN_INT は、PLS_INTEGER 型と BINARY_INTEGER 型を表してい
ます。コード中ではこれらのラベルの省略形を使用できません。
PLS_INTEGER と BINARY_INTEGER はデータ型が同じであるため、変換は行われません。
この表は、異なる表現を持つ型のみを示しています。CLOB と NCLOB、CHAR と NCHAR、
VARCHAR と NVARCHAR2 など、同じ表現を持つ型は、相互に代用できます。
CLOB と NCLOB を暗黙的に変換できますが、コストが高い操作になる可能性があることに
注意してください。この変換を意図的に実行するには、変換ファンクション TO_CLOB お
よび TO_NCLOB を使用します。
TIMESTAMP、TIMESTAMP WITH TIME ZONE、TIMESTAMP WITH LOCAL TIME ZONE、
INTERVAL DAY TO SECOND および INTERVAL YEAR TO MONTH は、いずれも DATE 型
と同じ規則を使用して変換できます。ただし、これらの型は内部表現が異なるため、常に
相互に変換できるとはかぎりません。様々な日付および時刻型間の暗黙的な変換の詳細は、
『Oracle Database SQL リファレンス』を参照してください。
表 3-1 暗黙的な変換
BIN_INT
BLOB
BIN_INT
CHAR
CLOB
DATE
X
LONG
NUMBER
X
X
PLS_INT
VARCHAR2
X
X
X
CLOB
X
DATE
X
LONG
X
NUMBER
UROWID
X
BLOB
CHAR
RAW
X
PLS_INT
RAW
X
X
X
X
X
X
X
X
X
X
X
X
VARCHAR2 X
X
X
X
X
X
X
X
UROWID
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
PL/SQL のデータ型
3-21
CHAR と VARCHAR2 のデータ型の違い
値が実際に変換可能であるかどうかは、ユーザーが自分で確認する必要があります。たとえば、
'02-JUN-92' という CHAR 型の値は DATE 型に変換できますが、'YESTERDAY' という CHAR
型の値は DATE 型に変換できません。同様に、英字を含んでいる VARCHAR2 型の値は NUMBER
値に変換できません。
暗黙的変換と明示的変換の選択
データ型の暗黙的変換に頼るプログラミング習慣は、処理の低速化が発生したり、将来のソフ
トウェアで変換規則が変更される可能性があるため、好ましくありません。暗黙的変換は状況
依存であるため、結果を常に予測できるとはかぎりません。信頼性とメンテナンス性を高める
ために、データ型変換ファンクションを使用してください。
DATE の値
DATE 列の値を選択して CHAR 型変数または VARCHAR2 型変数に入れる場合、PL/SQL は内部
バイナリ値を文字値に変換する必要があります。このとき、PL/SQL は、文字列をデフォルト
の日付書式で戻すファンクション TO_CHAR をコールします。時刻やユリウス日付などの情報
を得るには、書式マスクを使用して TO_CHAR をコールします。
CHAR 型または VARCHAR2 型の値を DATE 型の列に挿入する場合にも変換が必要です。PL/SQL
は、デフォルトの日付書式を期待するファンクション TO_DATE をコールします。他の書式の
日付を挿入するには、書式マスクを使用して TO_DATE をコールします。
RAW および LONG RAW の値
RAW 型または LONG RAW 型の列の値を選択して CHAR 型変数または VARCHAR2 型変数に入れる
場合、PL/SQL は内部バイナリ値を文字値に変換する必要があります。この場合、PL/SQL は
RAW 型データまたは LONG RAW 型データの各バイナリ・バイトを文字のペアとして戻します。
個々の文字はニブル(半バイト)の 16 進値を表します。たとえば、PL/SQL はバイナリ・バイ
ト 11111111 を文字のペア 'FF' として戻します。ファンクション RAWTOHEX も同じ変換を実行
します。
CHAR 型または VARCHAR2 型の値を RAW 型または LONG RAW 型の列に挿入する場合にも変換が
必要です。変数中の文字のペアは、いずれもバイナリ・バイトの 16 進値を表している必要があ
ります。一致していない場合は、PL/SQL によって例外が呼び出されます。LONG RAW データ
型は、下位互換性のためにのみサポートされている点に注意してください。詳細は、3-6 ページ
の「LONG および LONG RAW データ型」を参照してください。
CHAR と VARCHAR2 のデータ型の違い
この項では、ベース型 CHAR と VARCHAR2 の意味上の相違点について説明します。わずかでは
ありますが、重要なこれらの相違点は、文字値の代入、比較、挿入、更新、選択またはフェッ
チに影響を及ぼします。
文字値の代入
文字値を CHAR 型変数に割り当てるとき、変数の宣言された長さよりも値が短い場合、PL/SQL
は、その値が宣言された長さと同じ長さになるまで空白を埋めます。元の値の後続する空白に
関する情報は失われます。たとえば、次の宣言では、last_name に割り当てられた値の後に
は、1 つではなく 6 つの空白ができます。
last_name CHAR(10) := 'CHEN '; -- 後続する空白に注意
CHAR 型変数の宣言された長さよりも文字値が長い場合、PL/SQL は代入を中止して事前定義済
の例外 VALUE_ERROR を呼び出します。PL/SQL が値を切り捨てたり、後続する空白を切り捨
てることはありません。たとえば、次のような宣言があるとします。
acronym CHAR(4);
3-22
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
CHAR と VARCHAR2 のデータ型の違い
次のような代入を試みると VALUE_ERROR が呼び出されます。
acronym := 'SPCA '; -- 後続する空白に注意
文字値を VARCHAR2 型変数に割り当てるとき、変数の宣言された長さよりも値が短い場合に、
値を空白で埋めたり、値に後続する空白を削除することはありません。文字値はそのまま割り
当てられ、情報は失われません。VARCHAR2 型変数の宣言された長さよりも文字値が長い場合、
PL/SQL は代入を中止して VALUE_ERROR を呼び出します。PL/SQL が値を切り捨てたり、後
続する空白を切り捨てることはありません。
文字値の比較
関係演算子を使用すると、2 つの文字値が等しいかどうかを比較できます。比較はデータベー
ス・キャラクタ・セットの照合順番に基づいて行われます。文字値の比較では、照合順番で後
の文字値が大きくなります。たとえば、例 3-13 での次のような宣言の場合、IF 条件は TRUE
です。
例 3-13 文字値の比較
DECLARE
last_name1 VARCHAR2(10) := 'COLES';
last_name2 VARCHAR2(10) := 'COLEMAN';
BEGIN
IF last_name1 > last_name2 THEN
DBMS_OUTPUT.PUT_LINE ( last_name1 || ' is greater than ' || last_name2 );
ELSE
DBMS_OUTPUT.PUT_LINE ( last_name2 || ' is greater than ' || last_name1 );
END IF;
END;
/
SQL 標準では、比較する 2 つの文字値は同じ長さである必要があります。比較対象の値の両方
が CHAR データ型の場合は、空白埋め比較方法が使用されます。PL/SQL では、長さが異なる
文字値を比較する前に、短い方の値に長い方の値と同じ長さになるまで空白が埋められます。
たとえば、次のような宣言の場合、IF 条件は TRUE です。
DECLARE
last_name1 CHAR(5) := 'BELLO';
last_name2 CHAR(10) := 'BELLO '; -- note trailing blanks
BEGIN
IF last_name1 = last_name2 THEN
DBMS_OUTPUT.PUT_LINE ( last_name1 || ' is equal to ' || last_name2 );
ELSE
DBMS_OUTPUT.PUT_LINE ( last_name2 || ' is not equal to ' || last_name1 );
END IF;
END;
/
比較対象の値の一方が VARCHAR2 データ型の場合、非空白埋め方法が使用されます。つまり、
長さが異なる文字値を比較する場合に、PL/SQL によって調整は行われず、そのままの長さが
使用されます。たとえば、次のような宣言の場合、IF 条件は FALSE です。
DECLARE
last_name1 VARCHAR2(10) := 'DOW';
last_name2 VARCHAR2(10) := 'DOW
'; -- note trailing blanks
BEGIN
IF last_name1 = last_name2 THEN
DBMS_OUTPUT.PUT_LINE ( last_name1 || ' is equal to ' || last_name2 );
ELSE
DBMS_OUTPUT.PUT_LINE ( last_name2 || ' is not equal to ' || last_name1 );
END IF;
END;
/
PL/SQL のデータ型
3-23
CHAR と VARCHAR2 のデータ型の違い
VARCHAR2 の値と CHAR の値が比較される場合、非空白埋め比較方法が使用されます。ただし、
文字値を CHAR 変数に割り当てるときに、その値が変数の宣言された長さよりも短い場合、
PL/SQL は、その値が宣言された長さになるまで空白を埋めます。次の宣言の場合、
last_name2 の値の後に 5 つの空白が含まれるため、IF 条件は FALSE です。
DECLARE
last_name1 VARCHAR2(10) := 'STAUB';
last_name2 CHAR(10)
:= 'STAUB'; -- PL/SQL blank-pads value
BEGIN
IF last_name1 = last_name2 THEN
DBMS_OUTPUT.PUT_LINE ( last_name1 || ' is equal to ' || last_name2 );
ELSE
DBMS_OUTPUT.PUT_LINE ( last_name2 || ' is not equal to ' || last_name1 );
END IF;
END;
/
すべての文字列リテラルは、CHAR データ型を持っています。比較対象の値の両方がリテラルの
場合は、空白埋め比較方法が使用されます。片方の値がリテラルの場合は、残りの値が CHAR
データ型の場合にのみ、空白埋め比較方法が使用されます。
文字値の挿入
PL/SQL 文字変数の値を Oracle データベース列に挿入する場合、それが空白埋めされるかどう
かは、変数の型ではなく列の型に依存します。
文字値を CHAR データベース列に挿入する場合、Oracle は値に後続する空白を削除しません。
列の定義された幅よりも値が短ければ、Oracle は、定義された幅まで値を空白で埋めます。そ
の結果、後続する空白に関する情報は失われます。定義されている列幅よりも文字値が長い場
合、Oracle は挿入を中止してエラーを生成します。
文字値を VARCHAR2 データベース列に挿入する場合、Oracle は値に後続する空白を削除しませ
ん。列の定義された幅よりも値が短い場合も、Oracle は値の空白埋めをしません。文字値はそ
のまま格納されるため、情報は失われません。定義されている列幅よりも文字値が長い場合、
Oracle は挿入を中止してエラーを生成します。
この項で説明した規則は更新時も適用されます。
例 3-14 で示すように、文字値を挿入するとき、RTRIM ファンクションを使用することによっ
て、後続する空白が切り捨てられ、後続する空白を格納しないようにできます。
例 3-14 ファンクション RTRIM の使用
DECLARE
v_empid NUMBER(6);
v_last_name VARCHAR2(25);
v_first_name VARCHAR2(20);
BEGIN
v_empid := 300;
v_last_name := 'Lee '; -- note trailing blanks
v_first_name := 'Brenda';
DBMS_OUTPUT.PUT_LINE ( 'Employee Id: ' || v_empid || ' Name: '
|| RTRIM(v_last_name) || ', ' || v_first_name );
END;
/
3-24
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
CHAR と VARCHAR2 のデータ型の違い
文字値の選択
Oracle データベース列から値を選択して PL/SQL 文字変数に入れる場合、それが空白埋めされ
るかどうかは、列の型ではなく変数の型に依存します。
列値を選択して CHAR 変数に入れる場合、変数の宣言された長さよりも値が短ければ、PL/SQL
は宣言された長さまで値を空白で埋めます。その結果、後続する空白に関する情報は失われま
す。文字値が変数の宣言された長さより長い場合、PL/SQL は代入を中止して例外
VALUE_ERROR を呼び出します。
列値を選択して VARCHAR2 変数に入れる場合、その値が変数の宣言された長さよりも短いと、
PL/SQL は空白埋めも、後続する空白の削除もしません。文字値はそのまま格納されるため、
情報は失われません。
たとえば、空白で埋められた CHAR 列値を選択して VARCHAR2 変数に入れる場合、後続する空
白は削除されません。VARCHAR2 型変数の宣言された長さよりも文字値が長い場合、PL/SQL
は代入を中止して VALUE_ERROR を呼び出します。
この項で説明した規則はフェッチ時にも適用されます。
PL/SQL のデータ型
3-25
CHAR と VARCHAR2 のデータ型の違い
3-26
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
4
PL/SQL の制御構造の使用
この章では、PL/SQL プログラムの制御の流れを構造化する方法を示します。PL/SQL で提供
される条件テスト、ループおよび分岐を使用すると、優れた構造を持つプログラムを作成でき
ます。
この章の項目は、次のとおりです。
■
PL/SQL の制御構造の概要
■
条件テスト : IF 文および CASE 文
■
ループの反復の制御 : LOOP 文と EXIT 文
■
順次制御 : GOTO 文と NULL 文
PL/SQL の制御構造の使用
4-1
PL/SQL の制御構造の概要
PL/SQL の制御構造の概要
図 4-1 に、手続き型コンピュータ・プログラムで使用される基本制御構造を示します。
図 4-1 制御構造
選択構造は、条件をテストし、条件の真偽に応じて一連の文を実行します。条件とは、
BOOLEAN 値(TRUE または FALSE)を戻す任意の変数または式です。反復構造は、ある条件が
真の間、一連の文を繰り返して実行します。順次構造は、一連の文を、出現する順番にそのま
ま実行します。
条件テスト : IF 文および CASE 文
IF 文は、条件の値に応じて、異なる一連の文を実行します。IF 文には、IF-THEN、
IF-THEN-ELSE および IF-THEN-ELSIF の 3 つの形式があります。IF 文の構文の説明は、
13-63 ページの「IF 文」を参照してください。
CASE 文は、単一の条件を評価して多数の代替アクションから選択するコンパクトな手段です。
3 つ以上の選択肢がある場合は、CASE 文が有効です。CASE 文の構文の説明は、13-13 ページの
「CASE 文」を参照してください。
IF-THEN 文の使用
IF 文の最も単純な形式である IF-THEN は、例 4-1 で示すように、キーワード THEN と END IF
(ENDIF ではない)によって囲まれた一連の文に条件を関連付けます。
一連の文は、条件が TRUE である場合にのみ実行されます。条件が FALSE または NULL である
場合、IF 文は何も実行しません。いずれの場合も、制御は次の文に渡されます。
例 4-1 単純な IF-THEN 文の使用
DECLARE
sales NUMBER(8,2) := 10100;
quota NUMBER(8,2) := 10000;
bonus NUMBER(6,2);
emp_id NUMBER(6) := 120;
BEGIN
IF sales > (quota + 200) THEN
bonus := (sales - quota)/4;
UPDATE employees SET salary = salary + bonus WHERE employee_id = emp_id;
END IF;
END;
/
4-2
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
条件テスト : IF 文および CASE 文
IF-THEN-ELSE 文の使用
IF 文の 2 つ目の形式である IF-THEN-ELSE は、例 4-2 で示すように、キーワード ELSE を追加
し、その後に一連の代替文を続けます。
ELSE 句の中の文は、条件が FALSE または NULL に評価された場合にのみ実行されます。
IF-THEN-ELSE 文を使用すると、一連の文のどちらかが確実に実行されます。
例 4-2 単純な IF-THEN-ELSE 文の使用
DECLARE
sales NUMBER(8,2) := 12100;
quota NUMBER(8,2) := 10000;
bonus NUMBER(6,2);
emp_id NUMBER(6) := 120;
BEGIN
IF sales > (quota + 200) THEN
bonus := (sales - quota)/4;
ELSE
bonus := 50;
END IF;
UPDATE employees SET salary = salary + bonus WHERE employee_id = emp_id;
END;
/
IF 文は、例 4-3 で示すようにネストできます。
例 4-3 IF 文のネスト
DECLARE
sales NUMBER(8,2) := 12100;
quota NUMBER(8,2) := 10000;
bonus NUMBER(6,2);
emp_id NUMBER(6) := 120;
BEGIN
IF sales > (quota + 200) THEN
bonus := (sales - quota)/4;
ELSE
IF sales > quota THEN
bonus := 50;
ELSE
bonus := 0;
END IF;
END IF;
UPDATE employees SET salary = salary + bonus WHERE employee_id = emp_id;
END;
/
IF-THEN-ELSEIF 文の使用
複数の選択肢から選択する必要がある場合があります。キーワード ELSIF(ELSEIF または
ELSE IF ではない)を使用すると、例 4-4 で示すように条件を追加できます。
最初の条件が FALSE または NULL の場合、ELSIF 句は別の条件をテストします。IF 文は任意
の数の ELSIF 句を持つことができます。最後の ELSE 句はオプションです。条件は上から下に
向かって 1 つずつ評価されます。いずれかの条件が TRUE である場合は、それに対応する一連
の文が実行され、制御は次の文に移ります。すべての条件が FALSE または NULL である場合、
例 4-4 で示すように、ELSE 句の一連の文が実行されます。
PL/SQL の制御構造の使用
4-3
条件テスト : IF 文および CASE 文
例 4-4 IF-THEN-ELSEIF 文の使用
DECLARE
sales NUMBER(8,2) := 20000;
bonus NUMBER(6,2);
emp_id NUMBER(6) := 120;
BEGIN
IF sales > 50000 THEN
bonus := 1500;
ELSIF sales > 35000 THEN
bonus := 500;
ELSE
bonus := 100;
END IF;
UPDATE employees SET salary = salary + bonus WHERE employee_id = emp_id;
END;
/
sales の値が 50000 よりも大きい場合は、1 番目と 2 番目の条件が TRUE になります。ただし、
2 番目の条件はテストされないため、bonus には 1500 という正しい値が代入されます。1 番目
の条件が TRUE に評価されると、それに対応する文が実行され、制御は UPDATE 文に移ります。
例 4-5 は IF-THEN-ELSE 文の別の例です。
例 4-5 IF-THEN 文の拡張
DECLARE
grade CHAR(1);
BEGIN
grade := 'B';
IF grade = 'A' THEN
DBMS_OUTPUT.PUT_LINE('Excellent');
ELSIF grade = 'B' THEN
DBMS_OUTPUT.PUT_LINE('Very Good');
ELSIF grade = 'C' THEN
DBMS_OUTPUT.PUT_LINE('Good');
ELSIF grade = 'D' THEN
DBMS_OUTPUT. PUT_LINE('Fair');
ELSIF grade = 'F' THEN
DBMS_OUTPUT.PUT_LINE('Poor');
ELSE
DBMS_OUTPUT.PUT_LINE('No such grade');
END IF;
ENd;
/
CASE 文の使用
IF 文と同様に、CASE 文では一連の文を選択して実行できます。ただし、CASE 文では、順序
を選択するために複数のブール式ではなく選択子を使用します。選択子は複数の選択肢から 1
つ選択するために値が使用される式です。
IF 文と CASE 文を比較するために、学業成績の説明を出力する例 4-5 のコードを考えます。5
つのブール式があることに注意してください。各インスタンスで、同じ変数 grade が 5 つの値
'A'、'B'、'C'、'D' または 'F' のどれかをテストしています。例 4-5 のコードを、例 4-6 に
示すように CASE 文を使用して書き直します。
例 4-6 CASE-WHEN 文の使用
DECLARE
grade CHAR(1);
BEGIN
grade := 'B';
CASE grade
4-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
条件テスト : IF 文および CASE 文
WHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('Excellent');
WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('Very Good');
WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('Good');
WHEN 'D' THEN DBMS_OUTPUT.PUT_LINE('Fair');
WHEN 'F' THEN DBMS_OUTPUT.PUT_LINE('Poor');
ELSE DBMS_OUTPUT.PUT_LINE('No such grade');
END CASE;
END;
/
CASE 文の方が読みやすく効率的です。長い IF-THEN-ELSIF 文はできるかぎり CASE 文とし
て書き直してください。
CASE 文は、キーワード CASE で始まります。キーワードの後に選択子(前述の例では変数
grade)があります。選択子式は、どんなに複雑でもかまいません。たとえば、ファンクショ
ン・コールを含めることができます。ただし、通常は、1 個の変数で構成されています。選択
子式が評価されるのは 1 度のみです。生成される値は、BLOB、BFILE、オブジェクト型、
PL/SQL レコード、索引付き表または VARRAY、ネストした表以外であれば、どのような
PL/SQL データ型でもかまいません。
選択子の後に 1 つ以上の WHEN 句があり、各句が順番にチェックされます。選択子の値によっ
て、どの句が実行されるかが決定されます。選択子の値が WHEN 句の式の値と等しければ、そ
の WHEN 句が実行されます。たとえば、最後の例では、grade が 'C' であれば、'Good' が出
力されます。実行が失敗することはなく、WHEN 句が 1 つでも実行されると、制御が次の文に渡
されます。
ELSE 句の機能は、IF 文の ELSE 句に似ています。前述の例では、学年が WHEN 句のオプショ
ンの 1 つでなければ、ELSE 句が選択され、'No such grade' という句が出力されます。
ELSE 句はオプションです。ただし、ELSE 句を省略すると、PL/SQL では次の暗黙的な ELSE
句が追加されます。
ELSE RAISE CASE_NOT_FOUND;
ELSE 句を省略しても、常にデフォルト・アクションがあります。CASE 文がどの WHEN 句にも
一致せず、ELSE 句を省略している場合、PL/SQL は事前定義された例外 CASE_NOT_FOUND を
呼び出します。
CASE 文は、キーワード END CASE で終了します。この 2 つのキーワードは、空白で区切る必要
があります。CASE 文の書式は、次のとおりです。
PL/SQL ブロックと同様に、CASE 文にもラベルを付けることができます。ラベルは二重の山
カッコで囲んだ未宣言の識別子で、CASE 文の先頭に置きます。オプションとして、CASE 文の
末尾にもラベル名を付けることができます。
CASE 文の実行中に呼び出された例外は、通常の方法で処理されます。つまり、通常の実行は中
止され、PL/SQL ブロックまたはサブプログラムの例外処理部に制御が移ります。
CASE 文は CASE 式の代替であり、各 WHEN 句が式になっています。詳細は、2-25 ページの
「CASE 式」を参照してください。
検索 CASE 文
PL/SQL には、単純な CASE 文と同様の検索 CASE 文も用意されています。その書式は例 4-7 で
示すとおりです。
検索 CASE 文には選択子はありません。また、例 4-7 で示すように、WHEN 句には、結果がなん
らかの型の値になる式ではなく、ブール値になる検索条件が含まれます。
例 4-7 検索 CASE 文の使用
DECLARE
grade CHAR(1);
BEGIN
grade := 'B';
CASE
WHEN grade = 'A' THEN DBMS_OUTPUT.PUT_LINE('Excellent');
PL/SQL の制御構造の使用
4-5
条件テスト : IF 文および CASE 文
WHEN grade = 'B' THEN DBMS_OUTPUT.PUT_LINE('Very Good');
WHEN grade = 'C' THEN DBMS_OUTPUT.PUT_LINE('Good');
WHEN grade = 'D' THEN DBMS_OUTPUT.PUT_LINE('Fair');
WHEN grade = 'F' THEN DBMS_OUTPUT.PUT_LINE('Poor');
ELSE DBMS_OUTPUT.PUT_LINE('No such grade');
END CASE;
END;
-- rather than using the ELSE in the CASE, could use the following
-- EXCEPTION
-WHEN CASE_NOT_FOUND THEN
-DBMS_OUTPUT.PUT_LINE('No such grade');
/
検索条件は順番に評価されます。各検索条件のブール値によって、どの WHEN 句が実行される
かが決定されます。検索条件が TRUE になると、その WHEN 句が実行されます。WHEN 句が 1 つ
でも実行されると、制御が次の文に渡されるため、後続の検索条件は評価されません。
TRUE になる検索条件がなければ、ELSE 句が実行されます。ELSE 句はオプションです。ただ
し、ELSE 句を省略すると、PL/SQL では次の暗黙的な ELSE 句が追加されます。
ELSE RAISE CASE_NOT_FOUND;
検索 CASE 文の実行中に呼び出された例外は、通常の方法で処理されます。つまり、通常の実
行は中止され、PL/SQL ブロックまたはサブプログラムの例外処理部に制御が移ります。
PL/SQL 条件文のガイドライン
次の例のような IF 文の使用は避けてください。
IF new_balance < minimum_balance THEN
overdrawn := TRUE;
ELSE
overdrawn := FALSE;
END IF;
...
IF overdrawn = TRUE THEN
RAISE insufficient_funds;
END IF;
ブール式の値はブール変数に直接代入できます。1 番目の IF 文は、次のように単純な代入に置
き換えることができます。
overdrawn := new_balance < minimum_balance;
ブール変数はそれ自身が TRUE または FALSE です。2 番目の IF 文の条件は、次のように単純
化できます。
IF overdrawn THEN ...
可能ならば、IF 文をネストするのではなく、ELSIF 句を使用してください。それによって、
読みやすく、理解しやすいコードになります。次の IF 文を比較してください。
IF condition1 THEN statement1;
ELSE IF condition2 THEN statement2;
ELSE IF condition3 THEN statement3; END IF;
END IF;
END IF;
IF condition1 THEN statement1;
ELSEIF condition2 THEN statement2;
ELSEIF condition3 THEN statement3;
END IF;
4-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
ループの反復の制御 : LOOP 文と EXIT 文
これらの文は論理的に等価ですが、2 番目の文の方が論理が明快です。
単一の式を複数の値と比較する場合は、IF と ELSIF 句の組合せのかわりに単一の CASE 文を
使用すると、論理を簡素化できます。
ループの反復の制御 : LOOP 文と EXIT 文
LOOP 文は一連の文を複数回実行します。LOOP 文には、LOOP、WHILE-LOOP および
FOR-LOOP の 3 つの形式があります。LOOP 文の構文の説明は、13-71 ページの「LOOP 文」を
参照してください。
LOOP 文の使用
LOOP 文の最も単純な形式は、キーワード LOOP と END LOOP で一連の文を囲む基本ループで
す。次に例を示します。
LOOP
sequence_of_statements
END LOOP;
ループが繰り返されるたびに一連の文が実行され、制御がループの先頭に戻ります。EXIT 文
は、ループを終了し無限ループを防ぐために使用します。ループの中では、任意の場所に 1 つ
または複数の EXIT 文を置くことができます。ただし、ループの外には置くことができません。
EXIT 文には、EXIT および EXIT-WHEN の 2 つの形式があります。
EXIT 文の使用
EXIT 文はループを無条件に終了させます。EXIT 文が現れると、例 4-8 で示すように、ループ
はただちに終了し、制御は次の文に移ります。
例 4-8 EXIT 文の使用
DECLARE
credit_rating NUMBER := 0;
BEGIN
LOOP
credit_rating := credit_rating + 1;
IF credit_rating > 3 THEN
EXIT; -- exit loop immediately
END IF;
END LOOP;
-- control resumes here
DBMS_OUTPUT.PUT_LINE ('Credit rating: ' || TO_CHAR(credit_rating));
IF credit_rating > 3 THEN
RETURN; -- use RETURN not EXIT when outside a LOOP
END IF;
DBMS_OUTPUT.PUT_LINE ('Credit rating: ' || TO_CHAR(credit_rating));
END;
/
EXIT 文はループの中に置くことに注意してください。PL/SQL ブロックを通常終了より前の段
階で終了させる場合は、RETURN 文を使用します。詳細は、8-5 ページの「RETURN 文の使用」
を参照してください。
PL/SQL の制御構造の使用
4-7
ループの反復の制御 : LOOP 文と EXIT 文
EXIT-WHEN 文の使用
EXIT-WHEN 文を使用すると、ループを条件に合わせて終了できます。EXIT 文が見つかると、
WHEN 句の中の条件が評価されます。条件の評価結果が TRUE ならば、ループは終了し、制御
はそのループの後の文に移ります。EXIT-WHEN 文を使用した例の 1-11 ページの例 1-10 を参照
してください。
条件の評価結果が TRUE になるまで、ループは終了できません。ループの中で条件の値を変更
する必要があります。前述の例で、FETCH 文が行を戻すと、条件は FALSE に評価されます。
FETCH 文が行を戻すことに失敗した場合、条件は TRUE に評価され、ループは終了し、制御は
CLOSE 文に移ります。
EXIT-WHEN 文は単純な IF 文のかわりとして使用できます。たとえば、次の 2 つの文を比較し
てください。
IF count > 100 THEN EXIT; ENDIF;
EXIT WHEN count > 100;
この 2 つの文は論理的に等価ですが、EXIT-WHEN 文の方がわかりやすく、理解しやすくなって
います。
PL/SQL ループのラベル付け
PL/SQL ブロックと同様に、ループにもラベルを付けることができます。オプション・ラベル
は二重の山カッコで囲んだ未宣言の識別子で、LOOP 文の先頭に置きます。また、LOOP 文の末
尾にもラベル名を付けることができます。ラベル付きのループをネストする場合は、末尾のラ
ベルを使用してわかりやすくします。
どちらの形式の EXIT 文でも、カレント・ループにかぎらず、任意の外側のループも終了させ
ることができます。これを行うには、終了する外側のループにラベルを付けます。次に、例 4-9
に示すように、EXIT 文でそのラベルを使用します。ラベルを付けた外側のループが、内側の
ループを含めて終了します。
例 4-9 ラベル付きループの EXIT の使用
DECLARE
s
PLS_INTEGER := 0;
i
PLS_INTEGER := 0;
j
PLS_INTEGER;
BEGIN
<<outer_loop>>
LOOP
i := i + 1;
j := 0;
<<inner_loop>>
LOOP
j := j + 1;
s := s + i * j; -- sum a bunch of products
EXIT inner_loop WHEN (j > 5);
EXIT outer_loop WHEN ((i * j) > 15);
END LOOP inner_loop;
END LOOP outer_loop;
DBMS_OUTPUT.PUT_LINE('The sum of products equals: ' || TO_CHAR(s));
END;
/
4-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
ループの反復の制御 : LOOP 文と EXIT 文
WHILE-LOOP 文の使用
WHILE-LOOP 文は、条件が TRUE に評価されるかぎり、ループ本体の文を実行します。
WHILE condition LOOP
sequence_of_statements
END LOOP;
ループを反復する前に条件が評価されます。条件が TRUE ならば、一連の文が実行されてから、
ループの先頭で制御が再開します。FALSE または NULL の場合、ループは実行されず、制御は
次の文に渡されます。WHILE-LOOP 文を使用する例については、1-11 ページの例 1-9 を参照し
てください。
反復の回数は条件に依存し、ループが終了するまでわかりません。条件はループの先頭でテス
トされるため、一連の文が一度も実行されない可能性もあります。
いくつかの言語は、条件をループの先頭ではなく末尾でテストする LOOP UNTIL 構造または
REPEAT UNTIL 構造を持っています。そのため、一連の文は 1 回以上実行されます。PL/SQL
での等価のコードを次に示します。
LOOP
sequence_of_statements
EXIT WHEN boolean_expression;
END LOOP;
WHILE ループが 1 回以上実行されるようにするには、初期化済のブール変数を条件の中で使用
します。
done := FALSE;
WHILE NOT done LOOP
sequence_of_statements
done := boolean_expression;
END LOOP;
ループの中の文でブール変数に新しい値を代入して、無限ループを回避します。
FOR-LOOP 文の使用
単純な FOR ループは、指定された整数の範囲内でループを繰り返し実行します。反復の回数は
ループに入る前からわかっています。二重ドット(..)は、範囲演算子です。繰返しの範囲は
FOR ループに入った段階で評価され、それ以降は評価されません。下限と上限が等しければ、
ループ本体は 1 回のみ実行されます。
例 4-10 の例に示すように、一連の文は 1 から 500 までの整数につき、1 回ずつ実行されます。
繰り返しが 1 回行われるたびに、ループ・カウンタが 1 つ増えます。
例 4-10 単純な FOR..LOOP 文の使用
DECLARE
p
NUMBER := 0;
BEGIN
FOR k IN 1..500 LOOP -- calculate pi with 500 terms
p := p + ( ( (-1) ** (k + 1) ) / ((2 * k) - 1) );
END LOOP;
p := 4 * p;
DBMS_OUTPUT.PUT_LINE( 'pi is approximately : ' || p ); -- print result
END;
/
デフォルトでは、反復は下限から上限の向きに進みます。キーワード REVERSE を使用した場
合、反復は上限から下限に下向きに進みます。繰返しが 1 回行われるたびに、ループ・カウン
タが 1 つ減ります。この場合でも、範囲の上限と下限は(降順ではなく)昇順に書きます。
PL/SQL の制御構造の使用
4-9
ループの反復の制御 : LOOP 文と EXIT 文
例 4-11 反転 FOR..LOOP 文の使用
BEGIN
FOR i IN REVERSE 1..3 LOOP -- assign the values 1,2,3 to i
DBMS_OUTPUT.PUT_LINE (TO_CHAR(i));
END LOOP;
END;
/
FOR ループの中では、ループ・カウンタを参照できますが、変更することはできません。
BEGIN
FOR i IN 1..3 LOOP -- assign the values 1,2,3 to i
IF i < 3 THEN
DBMS_OUTPUT.PUT_LINE (TO_CHAR(i));
ELSE
i := 2; -- not allowed, raises an error
END IF;
END LOOP;
END;
/
FOR ループで、整数の範囲のかわりに SQL 問合せを使用することをお薦めします。この手法を
使用すると、単純な構文で、問合せを実行し、結果セットのすべての行を処理できます。詳細
は、6-15 ページの「PL/SQL を使用したデータの問合せ : 暗黙カーソルの FOR ループ」を参照
してください。
PL/SQL ループの反復方法
ループ範囲の境界にはリテラル、変数または式を使用できますが、整数に評価されるものにす
る必要があります。それ以外の場合、PL/SQL は事前定義の例外 VALUE_ERROR を呼び出しま
す。下限は 1 である必要はありませんが、ループ・カウンタの増分値(または減分値)は 1 で
ある必要があります。
j IN -5..5
k IN REVERSE first..last
step IN 0..TRUNC(high/low) * 2
内部的に、PL/SQL は PLS_INTEGER 一時変数に境界の値を代入します。さらに、必要に応じ
てその値を最も近い整数に四捨五入します。PLS_INTEGER の大きさの範囲は、32 ビットで表
すと、-2147483648 ~ 2147483647 です。範囲外の数値を評価した場合、PL/SQL が代入をする
と、数値オーバーフローのエラーが発生します。3-4 ページの「PLS_INTEGER データ型」を参
照してください。
言語によっては、STEP 句を使用して異なる増分値(たとえば、1 ではなく 5)を指定できるも
のがあります。PL/SQL はこのような構造を持っていませんが、作成するのは簡単です。FOR
ループの内部で、ループ・カウンタへの各参照に新しい増分値を乗じます。例 4-12 では、本日
の日付を索引付き表の要素 5、10、および 15 に代入します。
例 4-12 FOR..LOOP 文におけるカウンタの増分の変更
DECLARE
TYPE DateList IS TABLE OF DATE INDEX BY PLS_INTEGER;
dates DateList;
k CONSTANT INTEGER := 5; -- set new increment
BEGIN
FOR j IN 1..3 LOOP
dates(j*k) := SYSDATE; -- multiply loop counter by increment
END LOOP;
END;
/
4-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
ループの反復の制御 : LOOP 文と EXIT 文
ループの動的な範囲
例 4-13 で示すように、PL/SQL では、範囲に変数を使用することでループの範囲を実行時に指
定できます。
例 4-13 実行時の LOOP 範囲の指定
CREATE TABLE temp (emp_no NUMBER, email_addr VARCHAR2(50));
DECLARE
emp_count NUMBER;
BEGIN
SELECT COUNT(employee_id) INTO emp_count FROM employees;
FOR i IN 1..emp_count LOOP
INSERT INTO temp VALUES(i, 'to be added later');
END LOOP;
COMMIT;
END;
/
ループ範囲の下限が、上限より大きい整数であると評価された場合、ループ本体は実行されず、
制御は次の文に移ります。
-- 上限が 1 になる
FOR i IN 2..limit LOOP
sequence_of_statements -- ゼロ(0)回実行
END LOOP;
-- 制御はここに移る
ループ・カウンタ変数の有効範囲
ループ・カウンタはループの中でしか定義されません。そのため、その変数名をループの外側
からは参照できません。ループが終了すると、ループ・カウンタは未定義になります。
例 4-14 ループ・カウンタ変数の有効範囲
BEGIN
FOR i IN 1..3 LOOP -- assign the values 1,2,3 to i
DBMS_OUTPUT.PUT_LINE (TO_CHAR(i));
END LOOP;
DBMS_OUTPUT.PUT_LINE (TO_CHAR(i)); -- raises an error
END;
/
ループ・カウンタは INTEGER 型のローカル変数として暗黙的に宣言されているため、ループ・
カウンタを宣言する必要はありません。ローカル宣言はグローバル宣言を隠すため、最も安全
な方法は、既存の変数の名前を使用しないことです。
DECLARE
i NUMBER := 5;
BEGIN
FOR i IN 1..3 LOOP -- assign the values 1,2,3 to i
DBMS_OUTPUT.PUT_LINE (TO_CHAR(i));
END LOOP;
DBMS_OUTPUT.PUT_LINE (TO_CHAR(i)); -- refers to original variable value (5)
END;
/
PL/SQL の制御構造の使用
4-11
ループの反復の制御 : LOOP 文と EXIT 文
この例でグローバル変数を使用する場合は、例 4-15 で示すように、ラベルとドット表記法を使
用する必要があります。
例 4-15 ループの外で変数を参照する場合のラベルの使用
<<main>>
DECLARE
i NUMBER := 5;
BEGIN
FOR i IN 1..3 LOOP -- assign the values 1,2,3 to i
DBMS_OUTPUT.PUT_LINE( 'local: ' || TO_CHAR(i)
|| ' global: ' || TO_CHAR(main.i));
END LOOP;
END main;
/
ネストされた FOR ループにも同じ有効範囲規則が適用されます。例 4-16 では、どちらのルー
プ・カウンタも同じ名前を持っています。内側のループから外側のループ・カウンタを参照す
る場合は、次のようにラベルとドット表記法を使用します。
例 4-16 ループのラベルを使用した参照
BEGIN
<<outer_loop>>
FOR i IN 1..3 LOOP -- assign the values 1,2,3 to i
<<inner_loop>>
FOR i IN 1..3 LOOP
IF outer_loop.i = 2 THEN
DBMS_OUTPUT.PUT_LINE( 'outer: ' || TO_CHAR(outer_loop.i) || ' inner: '
|| TO_CHAR(inner_loop.i));
END IF;
END LOOP inner_loop;
END LOOP outer_loop;
END;
/
FOR ループでの EXIT 文の使用
EXIT 文を使用すると、FOR ループを途中で終了させることができます。例 4-17 で示すように、
ループは通常は 10 回実行されますが、FETCH 文が行を戻さなくなると、ループはそれまで何
回実行されていてもただちに終了します。
例 4-17 LOOP での EXIT の使用
DECLARE
v_employees employees%ROWTYPE; -- declare record variable
CURSOR c1 is SELECT * FROM employees;
BEGIN
OPEN c1; -- open the cursor before fetching
-- An entire row is fetched into the v_employees record
FOR i IN 1..10 LOOP
FETCH c1 INTO v_employees;
EXIT WHEN c1%NOTFOUND;
-- process data here
END LOOP;
CLOSE c1;
END;
/
4-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
順次制御 : GOTO 文と NULL 文
ネストされた FOR ループから途中で出る必要があるとします。カレント・ループのみでなく外
側のループも終了するには、例 4-18 で示すように、終了する外側のループにラベルを付け、
EXIT 文でそのラベルを使用します。
例 4-18 LOOP でのラベル付き EXIT の使用
DECLARE
v_employees employees%ROWTYPE; -- declare record variable
CURSOR c1 is SELECT * FROM employees;
BEGIN
OPEN c1; -- open the cursor before fetching
-- An entire row is fetched into the v_employees record
<<outer_loop>>
FOR i IN 1..10 LOOP
-- process data here
FOR j IN 1..10 LOOP
FETCH c1 INTO v_employees;
EXIT WHEN c1%NOTFOUND;
-- process data here
END LOOP;
END LOOP outer_loop;
CLOSE c1;
END;
/
6-9 ページの例 6-10 を参照してください。
順次制御 : GOTO 文と NULL 文
GOTO 文と NULL 文は、PL/SQL プログラミングにとって IF 文や LOOP 文ほど重要なものでは
ありません。通常、GOTO 文は必要ありません。ただし、GOTO 文を使用すると論理を単純化
できる場合もあります。NULL 文には、条件文の意味とアクションを明確にすることによって、
コードをわかりやすくする効果があります。
GOTO 文を多用すると、コードの理解やメンテナンスが困難になる可能性があります。GOTO 文
の使用は最小限にしてください。たとえば、深くネストされた構造からエラー処理ルーチンに
分岐する場合は、GOTO 文を使用するのではなく、例外を呼び出してください。PL/SQL の例外
処理メカニズムについては、第 10 章「PL/SQL エラーの処理」を参照してください。
GOTO 文の使用
GOTO 文はラベルに無条件に分岐する場合に使用します。ラベルは有効範囲の中で他と重複しな
いもので、実行可能文か PL/SQL ブロックの前に置かれている必要があります。GOTO 文が実
行されると、ラベルが付けられた文またはブロックに制御が移ります。ラベル付きの文または
ブロックを、一連の文の中で上の方にも下の方にも置くことができます。例 4-19 では、一連の
文の下の方にある PL/SQL ブロックに制御が渡されています。
例 4-19 簡単な GOTO 文の使用
DECLARE
p
VARCHAR2(30);
n
PLS_INTEGER := 37; -- test any integer > 2 for prime
BEGIN
FOR j in 2..ROUND(SQRT(n)) LOOP
IF n MOD j = 0 THEN -- test for prime
p := ' is not a prime number'; -- not a prime number
GOTO print_now;
END IF;
END LOOP;
p := ' is a prime number';
PL/SQL の制御構造の使用
4-13
順次制御 : GOTO 文と NULL 文
<<print_now>>
DBMS_OUTPUT.PUT_LINE(TO_CHAR(n) || p);
END;
/
例 4-20 に示すラベル end_loop は、実行可能文の前に置かれていないと使用できません。ラベ
ルを有効にするため、NULL 文を追加します。
例 4-20 GOTO をラベルに使用するために NULL を使用
DECLARE
done BOOLEAN;
BEGIN
FOR i IN 1..50 LOOP
IF done THEN
GOTO end_loop;
END IF;
<<end_loop>> -- not allowed unless an executable statement follows
NULL; -- add NULL statement to avoid error
END LOOP; -- raises an error without the previous NULL
END;
/
例 4-21 で示すように、GOTO 文でカレント・ブロックから外側のブロックに分岐できます。
例 4-21 GOTO 文を使用した外側のブロックへの分岐
-- example with GOTO statement
DECLARE
v_last_name VARCHAR2(25);
v_emp_id
NUMBER(6) := 120;
BEGIN
<<get_name>>
SELECT last_name INTO v_last_name FROM employees
WHERE employee_id = v_emp_id;
BEGIN
DBMS_OUTPUT.PUT_LINE (v_last_name);
v_emp_id := v_emp_id + 5;
IF v_emp_id < 120 THEN
GOTO get_name; -- branch to enclosing block
END IF;
END;
END;
/
この GOTO 文では、参照されたラベルが置かれている最初の外側のブロックに分岐します。
GOTO 文の制限
GOTO 文の宛先として使用できないものがあります。特に、GOTO 文は IF 文、CASE 文、LOOP
文またはサブブロックには分岐できません。たとえば、次の GOTO 文は誤りです。
BEGIN
GOTO update_row; -- IF 文には分岐できない
IF valid THEN
<<update_row>>
UPDATE emp SET ...
END IF;
END;
GOTO 文では、ある IF 文の句から句へ分岐したり、ある CASE 文の WHEN 句から別の句へ分岐
することはできません。
4-14
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
順次制御 : GOTO 文と NULL 文
GOTO 文では、外部のブロックからサブブロック(内側の BEGIN-END ブロック)には分岐でき
ません。
GOTO 文では、サブプログラムの外に分岐できません。サブプログラムを途中で終了するには、
RETURN 文を使用するか、または GOTO 文を使用してサブプログラムの終了直前の場所に分岐
します。
GOTO 文では、例外ハンドラからカレント・ブロック BEGIN-END に分岐できません。ただし、
GOTO 文は、例外ハンドラから外側のブロックに分岐することはできます。
NULL 文の使用
NULL 文は、何も行わずに制御を次の文に渡します。一部の言語では、このような命令を no-op
(何もしない)と呼びます。13-76 ページの「NULL 文」を参照してください。
例 4-22 では、NULL 文によって、販売員のみがコミッションを受け取れることを明確にしてい
ます。
例 4-22 アクションを起こさないことを明示する NULL 文の使用
DECLARE
v_job_id VARCHAR2(10);
v_emp_id NUMBER(6) := 110;
BEGIN
SELECT job_id INTO v_job_id FROM employees WHERE employee_id = v_emp_id;
IF v_job_id = 'SA_REP' THEN
UPDATE employees SET commission_pct = commission_pct * 1.2;
ELSE
NULL; -- do nothing if not a sales representative
END IF;
END;
/
NULL 文を使用すると、プレースホルダやスタブ・プロシージャを簡単に作成できます。例
4-23 では、NULL 文を使用してプロシージャをコンパイルしています。実際の本体は、後で挿
入できます。NULL 文を使用する場合は、警告が有効であると、到達不能コードという警告が発
生する場合があることに注意してください。10-17 ページの「PL/SQL のコンパイル時の警告の
概要」を参照してください。
例 4-23 サブプログラム作成時のプレースホルダとしての NULL の使用
CREATE OR REPLACE PROCEDURE award_bonus (emp_id NUMBER, bonus NUMBER) AS
BEGIN -- executable part starts here
NULL; -- use NULL as placeholder, raises "unreachable code" if warnings enabled
END award_bonus;
/
NULL 文を使用すると、考慮はするがアクションが必要ないことを示すことができます。次の例
外ブロックでは、NULL 文によって、名前のない例外ではアクションを起こさないことを示して
います。
EXCEPTION
WHEN ZERO_DIVIDE THEN
ROLLBACK;
WHEN OTHERS THEN
NULL;
END;
1-13 ページの例 1-12「ストアド・サブプログラムの作成」を参照してください。
PL/SQL の制御構造の使用
4-15
順次制御 : GOTO 文と NULL 文
4-16
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
5
PL/SQL のコレクションおよびレコードの使用
多くのプログラミング手法では、配列、バッグ、リスト、ネストした表、セット、ツリーなど
のコレクション型を使用します。PL/SQL のデータ型 TABLE および VARRAY を使用すると、
データベース・アプリケーション内でこれらの型をモデル化できます。これによって、ネスト
した表、結合配列および可変サイズの配列を宣言できます。この章では、データの集まり(コ
レクション)をローカル変数として参照または操作する方法を示します。また、RECORD デー
タ型を使用して、関連する様な型の値を 1 つの論理単位として操作する方法についても説明し
ます。
この章の項目は、次のとおりです。
■
PL/SQL のコレクションおよびレコード
■
使用する PL/SQL コレクション型の選択
■
コレクション型の定義とコレクション変数の宣言
■
コレクションの初期化および参照
■
コレクションの代入
■
コレクションの比較
■
マルチレベル・コレクションの使用
■
コレクション・メソッドの使用
■
コレクション例外の回避
■
レコードの定義と宣言
■
レコードへの値の代入
PL/SQL のコレクションおよびレコードの使用
5-1
PL/SQL のコレクションおよびレコード
PL/SQL のコレクションおよびレコード
コレクションおよびレコードとは、配列、レコードまたは表の要素のような、個別に操作でき
る内部的な要素があるコンポジット型のことです。
コレクションは、すべて同じ型の要素の順序付きグループです。コレクションは、リスト、配
列および標準的なプログラミング・アルゴリズムで使用される他のデータ型を包含した一般的
な概念です。各要素は、一意の添字によってアドレスが付けられます。
レコードはフィールドに格納されるいくつかの関連したデータ項目のグループであり、それぞ
れに独自の名前とデータ型があります。レコードは、表の行または表の行の一部の列を保持す
る変数と考えることができます。フィールドは表の列に対応しています。
次の項では、PL/SQL のコレクションおよびレコードについて説明します。
■
PL/SQL のコレクション
■
PL/SQL レコード
PL/SQL のコレクション
PL/SQL には、次のコレクション型が用意されています。
■
■
■
結合配列は、索引付き表とも呼ばれ、添字の値に任意の数字または文字列を使用して要素
を参照できます。他のプログラミング言語でのハッシュ表に似ています。
ネストした表は、任意の数の要素を保持します。VARRAY では、添字に連番を使用しま
す。等価の SQL の型を定義すると、ネストした表をデータベース表に格納し、SQL を介し
て操作できます。
VARRAY(可変サイズの配列)は、固定数の要素を保持します(ただし、要素の数は実行
時に変更できます)
。VARRAY では、添字に連番を使用します。等価の SQL の型を定義す
ると、データベース表に VARRAY を格納できます。VARRAY は SQL を介して格納および
取得できますが、ネストした表に比べると柔軟性は低くなります。
コレクションは 1 次元のみですが、コレクションを要素に持つコレクションを作成すると、多
次元配列のモデルを作成できます。
アプリケーションでコレクションを使用するには、1 つ以上の PL/SQL の型を定義し、それら
の型の変数を定義します。コレクション型は、プロシージャ、ファンクションまたはパッケー
ジで定義できます。ストアド・サブプログラムに、コレクションの変数をパラメータとして渡
すことができます。
単一の値よりも複雑なデータを参照するために、PL/SQL レコードまたは SQL オブジェクト型
をコレクションに格納できます。ネストした表と VARRAY は、オブジェクト型の属性にするこ
ともできます。
ネストした表
PL/SQL のネストした表は、一連の値を表します。これは、要素数が宣言されていない 1 次元
配列と考えることができます。要素にネストした表を持つネストした表を作成すると、多次元
配列のモデルを作成できます。
データベース内では、ネストした表は一連の値を保持する列の型と考えられます。Oracle は、
ネストした表の行を特に順序付けずに格納します。ネストした表をデータベースから PL/SQL
変数の中に取り出すと、それらの行に 1 から始まる連続した添字が付けられます。これによっ
て、個の行に配列のようにアクセスできます。
ネストした表と配列には重要な相違点が 2 つあります。
1.
5-2
図 5-1 に示すように、ネストした表では要素数が宣言されていませんが、配列では数値が
事前定義されています。ネストした表のサイズは動的に大きくできますが、配列には上限
があります。5-11 ページの「コレクション要素の参照」を参照してください。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL のコレクションおよびレコード
2.
配列は常に密です(添字が連続しています)が、ネストした表は添字が連続していない場
合があります。ネストした表も最初は密ですが、疎にすることができます(つまり添字が
連続していなくてもかまいません)
。組込みプロシージャ DELETE を使用すると、ネストし
た表から要素を削除できます。組込みファンクション NEXT を使用すると、順序に欠番が
生じる場合でも、ネストした表のすべての添字に対して反復処理を実行できます。
図 5-1 配列とネストした表との相違点
VARRAY
VARRAY 型の項目は、VARRAY と呼ばれます。VARRAY を使用すると、配列操作の個の要素を
参照したり、コレクションを全体として操作することができます。要素を参照するには、標準
的な添字構文を使用します(図 5-2 を参照)。たとえば、Grade(3) は、Grades という
VARRAY の 3 番目の要素を参照します。
図 5-2 サイズ 10 の VARRAY
VARRAY には最大サイズがあり、このサイズを型定義で指定します。VARRAY の索引には、1
に固定されている下限と、拡張可能な上限があります。たとえば、VARRAY Grades の現在の
上限は 7 ですが、最大 10 まで拡張できます。したがって、VARRAY に入れることのできる要
素の数は、0(空の場合)個から型定義で指定された最大値まで変更できます。
結合配列(索引付き表)
結合配列は、キーと値のペアのセットです。各キーは一意で、配列内の対応する値を検索する
ために使用されます。キーは、整数または文字列にできます。
初めてキーを使用して値を代入すると、そのキーが結合配列に追加されます。その後、同じ
キーを使用して値を代入すると、同じエントリが更新されます。一意のキーを選択することが
重要です。たとえば、データベース表の主キー、数値のハッシュ関数、複数の文字列を連結し
た一意の文字列の値などを、キーの値として使用できます。
次に、文字列のキーを使用した結合配列型の宣言と、この型の 2 つの配列の例を示します。
例 5-1 コレクション型の宣言
DECLARE
TYPE population_type IS TABLE OF NUMBER INDEX BY VARCHAR2(64);
country_population population_type;
continent_population population_type;
howmany NUMBER;
which VARCHAR2(64);
BEGIN
country_population('Greenland') := 100000; -- Creates new entry
country_population('Iceland') := 750000; -- Creates new entry
-- Looks up value associated with a string
howmany := country_population('Greenland');
PL/SQL のコレクションおよびレコードの使用
5-3
PL/SQL のコレクションおよびレコード
continent_population('Australia') := 30000000;
continent_population('Antarctica') := 1000; -- Creates new entry
continent_population('Antarctica') := 1001; -- Replaces previous value
-- Returns 'Antarctica' as that comes first alphabetically.
which := continent_population.FIRST;
-- Returns 'Australia' as that comes last alphabetically.
which := continent_population.LAST;
-- Returns the value corresponding to the last key, in this
-- case the population of Australia.
howmany := continent_population(continent_population.LAST);
END;
/
結合配列は、任意のサイズのデータ・セットを表すために役立ち、配列内での要素の位置が不
明でも、配列の全要素をループせずに個の要素をすばやく参照します。単純な SQL 表のよう
に、主キーに基づいて値を取り出すことができます。単純な参照データの一時記憶域では、結
合配列によって、SQL 表に必要なディスク領域の使用やネットワーク操作を回避できます。
結合配列は、永続的なデータの格納ではなく一時的なデータを意図しているため、INSERT や
SELECT INTO などの SQL 文では使用できません。結合配列は、パッケージで型を宣言し、
パッケージ本体に値を代入することで、データベース・セッションの間を永続的に維持できま
す。
グローバリゼーション設定が結合配列の VARCHAR2 キーに与える影響
VARCHAR2 のキー値を持つ結合配列を使用したセッション中に、各国語またはグローバリゼー
ションの設定が変わると、プログラムでランタイム・エラーとなる可能性があります。たとえ
ば、セッション中に NLS_COMP 初期化パラメータや NLS_SORT 初期化パラメータを変更する
と、NEXT や PRIOR などのメソッドで例外が発生する可能性があります。セッション中にこれ
らの設定の変更が必要な場合は、必ず元の値に戻してから、結合配列での操作を実行してくだ
さい。
キーに文字列を使用して結合配列を宣言する場合、その宣言では VARCHAR2 型、STRING 型ま
たは LONG 型を使用する必要があります。結合配列を参照するためのキー値には、NCHAR 型や
NVARCHAR2 型などの異なる型を使用できます。TO_CHAR ファンクションで VARCHAR2 に変換
できる場合は、DATE などの型を使用することもできます。LONG データ型は、下位互換性のた
めにのみ使用してください。詳細は、3-6 ページの「LONG および LONG RAW データ型」を
参照してください。
ただし、他の型を使用する場合は、キーに使用する値の一貫性と一意性に注意してください。
たとえば、NLS_DATE_FORMAT 初期化パラメータが変更された場合は、SYSDATE の文字列値
が変更され、その結果、array_element(SYSDATE) では、以前と異なる結果が生じます。異
なる 2 つの NVARCHAR2 値が、
(特定の各国語キャラクタのかわりに疑問符が使用されて)同一
の VARCHAR2 値に変わる可能性もあります。この場合、
array_element(national_string1) と array_element(national_string2) は、同
一の要素を参照します。NLS_SORT 初期化パラメータの末尾が _CI(大 / 小文字を区別しない
比較)または _AI(アクセント記号の有無および大 / 小文字を区別しない比較)である場合、
大 / 小文字、アクセント記号またはデリミタ文字の異なる 2 つの CHAR または VARCHAR2 の値
も同じであるとみなされます。
データベース・リンクを使用して、リモート・データベースへのパラメータとして結合配列を
渡すと、2 つのデータベースで、グローバリゼーション設定が異なる可能性があります。リ
モート・データベースで FIRST や NEXT などの操作を実行すると、文字順序が元のコレクショ
ンとは異なる場合でも、リモート・データベース自体の文字順序が使用されます。キャラク
タ・セットの相違によって、一意であった 2 つのキーがリモート・データベース上では一意で
ない場合、プログラムは VALUE_ERROR 例外を受け取ります。
5-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
使用する PL/SQL コレクション型の選択
PL/SQL レコード
レコードは、行における列と同様、フィールドのグループで構成されます。%ROWTYPE 属性を
使用すると、すべての列をリストせずに、データベースの表の中の行を表す PL/SQL レコード
を宣言できます。記述したコードは、表に列が追加された後でも正常に動作します。表の列の
サブセット、または複数の表の列を表現する場合、ビューを定義するかカーソルを宣言して正
しい列を選択し、必要な結合を実行した後、ビューまたはカーソルに %ROWTYPE を適用しま
す。
PL/SQL でのレコードの使用の詳細は、この章の次の項を参照してください。
■
レコードの定義と宣言
■
レコードへの値の代入
使用する PL/SQL コレクション型の選択
他の言語を使用するコードまたはビジネス・ロジックがすでに存在する場合、通常は、その言
語の配列を変換して、型を PL/SQL のコレクション型に直接設定できます。
■
他の言語の配列は、PL/SQL の VARRAY になります。
■
他の言語の設定およびバッグは、PL/SQL のネストした表になります。
■
他の言語のハッシュ表や他の無秩序な参照表は、PL/SQL の結合配列になります。
オリジナルのコードを記述していたり、最初からビジネス・ロジックを設計している場合は、
各状況に適切なコレクション型を判断するために各コレクション型の長所を考慮してください。
ネストした表と結合配列の選択
ネストした表と結合配列(以前の索引付き表)はともに、同じような添字表記法を使用します
が、パラメータの引渡しの永続性と容易性の点で、異なる特性があります。
ネストした表はデータベースの列に格納できますが、結合配列をデータベースの列に格納する
ことはできません。ネストした表を使用すると、通常、単一列の表とそれより大きい表を結合
する必要がある SQL 操作を簡略化できます。
結合配列は、プロシージャのコールやパッケージの初期化のたびにコレクションがメモリー内
に構成される、比較的小規模な参照表に適しています。結合配列のサイズには固定制限がない
ため、量が事前にわからない情報を収集する場合に効果的です。結合配列の添字には、負数や
非連続の数字を指定したり、数字のかわりに文字列の値を使用することができるため、その索
引値は柔軟性があります。
PL/SQL は、数値のキー値を使用するホスト配列と結合配列との間で自動的に変換を行います。
データベース・サーバーとの間でのコレクションの受渡しには、データの値を結合配列で設定
し、その結合配列を(FORALL 文または BULK COLLECT 句を使用した)バルク構成で使用する
ことが、最も効果的な方法です。
ネストした表と VARRAY との使い分け
VARRAY が適している場合を次に示します。
■
要素の数が事前にわかっている。
■
通常、すべての要素が順番にアクセスされる。
データベースに格納されている間、VARRAY はその順序と添字を保持しています。
各 VARRAY は、それが列である表の内部(VARRAY が 4KB 未満の場合)か、同じ表領域内の
表の外部(VARRAY が 4KB を超える場合)のいずれかに、単一のオブジェクトとして格納され
ます。VARRAY のすべての要素は、同時に更新または取得する必要があります。これは、すべ
ての要素に対してなんらかの操作を同時に実行する場合に最適です。ただし、この方法で多数
の要素を格納および取得することは、現実的ではありません。
PL/SQL のコレクションおよびレコードの使用
5-5
コレクション型の定義とコレクション変数の宣言
ネストした表が適している場合を次に示します。
■
■
■
■
索引値が連続していない。
索引値の数が設定されていない。ただし、上限があります。5-11 ページの「コレクション
要素の参照」を参照してください。
すべての要素を同時にではなく、一部の要素を削除または更新する必要がある。
通常、メインの表の各行に複数のエントリを含む個別の参照表を作成し、結合問合せを介
してその表にアクセスする。
ネストした表は疎密な場合があります。最後から順に項目を削除せずに、任意の要素を削除で
きます。
ネストした表のデータは、個別の記憶域表に格納されます。この記憶域表は、ネストした表に
関連付けられた、システム生成によるデータベース表です。ネストした表にアクセスすると、
データベースで記憶域表が結合されます。この記憶域表によって、ネストした表は、コレク
ションの一部の要素にのみ影響を与える問合せと更新に適した内容になります。
ネストした表では、データベースへの格納(またはデータベースからの取得)時に表の順序と
添字が保持されないため、ネストした表の順序と添字は信頼できません。
コレクション型の定義とコレクション変数の宣言
コレクションを作成するには、コレクション型を定義した後、その型の変数を宣言します。コ
レクションは、他の型や変数と同じ有効範囲とインスタンス化の規則に従います。コレクショ
ンは、ブロックまたはサブプログラムに入ったときにインスタンス化され、ブロックまたはサ
ブプログラムが終了した時点で消滅します。パッケージの中では、そのパッケージが初めて参
照された時点でコレクションのインスタンスが生成され、データベース・セッションが終わっ
た時点で消滅します。
注意 : SQL オブジェクト型での PL/SQL の使用方法の詳細は、第 12 章
「PL/SQL のオブジェクト型の使用」を参照してください。CREATE TYPE
SQL 文の詳細は、
『Oracle Database SQL リファレンス』を参照してくださ
い。CREATE TYPE BODY SQL 文の詳細は、
『Oracle Database SQL リファ
レンス』を参照してください。
TABLE 型および VARRAY 型は、TYPE 定義を使用して、任意の PL/SQL ブロック、サブプログ
ラムまたはパッケージの宣言部で定義できます。構文は、13-16 ページの「コレクション定義」
を参照してください。
PL/SQL 内で宣言されたネストした表および VARRAY の場合、表または VARRAY の要素型
は、REF CURSOR 以外の任意の PL/SQL データ型となります。
VARRAY 型の定義では、その最大サイズを正の整数で指定する必要があります。次の例では、
366 個以内の日付を格納する型を定義します。
DECLARE
TYPE Calendar IS VARRAY(366) OF DATE;
結合配列は、索引付き表とも呼ばれ、任意のキー値を使用して要素を挿入できます。キーは連
続しなくてもかまいません。
キー・データ型は、PLS_INTEGER、BINARY_INTEGER または VARCHAR2 か、VARCHAR2 サブ
タイプの VARCHAR、STRING または LONG のいずれかとなります。PLS_INTEGER および
BINARY_INTEGER は、同じデータ型です。
VARCHAR2 ベースのキーを使用するには、VARCHAR2(32760) のキーの型を宣言することにな
る LONG の場合を除いて、キーの長さを指定する必要があります。RAW、LONG RAW、ROWID、
CHAR および CHARACTER の各型は、結合配列のキーとしては使用できません。LONG データ型
および LONG RAW データ型は、下位互換性のためにのみ使用してください。詳細は、3-6 ページ
の「LONG および LONG RAW データ型」を参照してください。
5-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクション型の定義とコレクション変数の宣言
初期化の句は指定できません。結合配列用のコンストラクタの表記は存在しません。
VARCHAR2 ベースのキーを使用する結合配列の要素を参照する場合は、TO_CHAR ファンクショ
ンで VARCHAR2 に変換できるかぎり、DATE、TIMESTAMP などの別の型を使用できます。
結合配列は、主キー値を索引として使用してデータを格納できます。この場合、連続したキー
値とはなりません。例 5-2 では、添字に 1 のかわりに 100 を使用して、結合配列の 1 つの要素
を作成しています。
例 5-2 結合配列の宣言
DECLARE
TYPE EmpTabTyp IS TABLE OF employees%ROWTYPE
INDEX BY PLS_INTEGER;
emp_tab EmpTabTyp;
BEGIN
/* Retrieve employee record. */
SELECT * INTO emp_tab(100) FROM employees WHERE employee_id = 100;
END;
/
PL/SQL のコレクション変数の宣言
コレクション型を定義した後は、その型の変数を宣言します。NUMBER などの事前定義の型と
同様に、宣言では新しい型名を使用します。
例 5-3 ネストした表、VARRAY
および結合配列の宣言
ネストした表、
DECLARE
TYPE nested_type IS TABLE OF VARCHAR2(30);
TYPE varray_type IS VARRAY(5) OF INTEGER;
TYPE assoc_array_num_type IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
TYPE assoc_array_str_type IS TABLE OF VARCHAR2(32) INDEX BY PLS_INTEGER;
TYPE assoc_array_str_type2 IS TABLE OF VARCHAR2(32) INDEX BY VARCHAR2(64);
v1 nested_type;
v2 varray_type;
v3 assoc_array_num_type;
v4 assoc_array_str_type;
v5 assoc_array_str_type2;
BEGIN
-- an arbitrary number of strings can be inserted v1
v1 := nested_type('Shipping','Sales','Finance','Payroll');
v2 := varray_type(1, 2, 3, 4, 5); -- Up to 5 integers
v3(99) := 10; -- Just start assigning to elements
v3(7) := 100; -- Subscripts can be any integer values
v4(42) := 'Smith'; -- Just start assigning to elements
v4(54) := 'Jones'; -- Subscripts can be any integer values
v5('Canada') := 'North America'; -- Just start assigning to elements
v5('Greece') := 'Europe';
-- Subscripts can be string values
END;
/
例 5-4 に示すとおり、%TYPE を使用すると、事前に宣言したコレクションのデータ型を指定で
きます。この指定によって、コレクションの定義を変更すると、要素の数または要素の型に依
存している他の変数が自動的に更新されます。
例 5-4 %TYPE を使用したコレクションの宣言
DECLARE
TYPE few_depts IS VARRAY(10) OF VARCHAR2(30);
TYPE many_depts IS VARRAY(100) OF VARCHAR2(64);
some_depts few_depts;
-- If we change the type of some_depts from few_depts to many_depts,
-- local_depts and global_depts will use the same type
PL/SQL のコレクションおよびレコードの使用
5-7
コレクション型の定義とコレクション変数の宣言
-- when this block is recompiled
local_depts some_depts%TYPE;
global_depts some_depts%TYPE;
BEGIN
NULL;
END;
/
コレクションは、ファンクションおよびプロシージャの仮パラメータとして宣言できます。こ
れによって、コレクションをストアド・サブプログラムに渡したり、あるサブプログラムから
別のサブプログラムに渡すことができます。例 5-5 では、ネストした表をパッケージ・プロ
シージャのパラメータとして宣言しています。
例 5-5 ネストした表としてのプロシージャのパラメータの宣言
CREATE PACKAGE personnel AS
TYPE staff_list IS TABLE OF employees.employee_id%TYPE;
PROCEDURE award_bonuses (empleos_buenos IN staff_list);
END personnel;
/
CREATE PACKAGE BODY personnel AS
PROCEDURE award_bonuses (empleos_buenos staff_list) IS
BEGIN
FOR i IN empleos_buenos.FIRST..empleos_buenos.LAST
LOOP
UPDATE employees SET salary = salary + 100
WHERE employees.employee_id = empleos_buenos(i);
END LOOP;
END;
END;
/
パッケージ外部から personnel.award_bonuses をコールするには、
personnel.staff_list 型の変数を宣言し、その変数をパラメータとして渡します。
例 5-6 ネストした表パラメータでのプロシージャのコール
DECLARE
good_employees personnel.staff_list;
BEGIN
good_employees := personnel.staff_list(100, 103, 107);
personnel.award_bonuses (good_employees);
END;
/
ファンクション仕様部の RETURN 句の中にコレクション型を指定することもできます。
要素型を指定するには、%TYPE を使用して変数またはデータベース列のデータ型を指定できま
す。また、%ROWTYPE を使用して、カーソルまたはデータベース表の行の型を指定できます。
例 5-7 および例 5-8 を参照してください。
例 5-7 %TYPE および %ROWTYPE を使用したコレクション要素型の指定
DECLARE
-- Nested table type that can hold an arbitrary number of employee IDs.
-- The element type is based on a column from the EMPLOYEES table.
-- We do not need to know whether the ID is a number or a string.
TYPE EmpList IS TABLE OF employees.employee_id%TYPE;
-- Declare a cursor to select a subset of columns.
CURSOR c1 IS SELECT employee_id FROM employees;
-- Declare an Array type that can hold information about 10 employees.
-- The element type is a record that contains all the same
5-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクションの初期化および参照
-- fields as the EMPLOYEES table.
TYPE Senior_Salespeople IS VARRAY(10) OF employees%ROWTYPE;
-- Declare a cursor to select a subset of columns.
CURSOR c2 IS SELECT first_name, last_name FROM employees;
-- Array type that can hold a list of names. The element type
-- is a record that contains the same fields as the cursor
-- (that is, first_name and last_name).
TYPE NameList IS VARRAY(20) OF c2%ROWTYPE;
BEGIN
NULL;
END;
/
例 5-8 では、RECORD 型を使用して、要素型を指定しています。5-28 ページの「レコードの定
義と宣言」を参照してください。
例 5-8 レコードとしての VARRAY
DECLARE
TYPE name_rec IS RECORD ( first_name VARCHAR2(20), last_name VARCHAR2(25) );
TYPE names IS VARRAY(250) OF name_rec;
BEGIN
NULL;
END;
/
NOT NULL 制約は、要素型に対しても指定できます。例 5-9 を参照してください。
例 5-9 コレクション要素の NOT NULL 制約
DECLARE
TYPE EmpList IS TABLE OF employees.employee_id%TYPE NOT NULL;
v_employees EmpList := EmpList(100, 150, 160, 200);
BEGIN
v_employees(3) := NULL; -- assigning NULL raises an error
END;
/
コレクションの初期化および参照
ネストした表または VARRAY は、初期化されるまでは基本構造的に NULL(コレクションの要
素ではなく、コレクション自体が NULL)です。ネストした表または VARRAY を初期化するに
は、コンストラクタを使用します。このコンストラクタは、コレクション型と同じ名前のシス
テム定義ファンクションです。このファンクションは、コレクションに渡される要素から、コ
レクションを構成します。
VARRAY やネストした表の変数に対しては、コンストラクタを明示的にコールする必要があり
ます。第 3 のコレクションである結合配列は、コンストラクタを使用しません。コンストラク
タは、ファンクション・コールが許可されているところでコールできます。
例 5-10 では、
(ファンクションに類似し、コレクション型と同じ名前を持つ)コンストラクタ
を使用して、ネストした表を初期化しています。
例 5-10 ネストした表のコンストラクタ
DECLARE
TYPE dnames_tab IS TABLE OF VARCHAR2(30);
dept_names dnames_tab;
BEGIN
dept_names := dnames_tab('Shipping','Sales','Finance','Payroll');
END;
/
PL/SQL のコレクションおよびレコードの使用
5-9
コレクションの初期化および参照
ネストした表ではサイズが宣言されていないため、コンストラクタには必要な数だけ要素を配
置できます。
例 5-11 では、(ファンクションに類似し、コレクション型と同じ名前を持つ)コンストラクタ
を使用して、VARRAY を初期化しています。
例 5-11 VARRAY のコンストラクタ
DECLARE
-- In the varray, we put an upper limit on the number of elements
TYPE dnames_var IS VARRAY(20) OF VARCHAR2(30);
dept_names dnames_var;
BEGIN
-- Because dnames is declared as VARRAY(20), we can put up to 10
-- elements in the constructor
dept_names := dnames_var('Shipping','Sales','Finance','Payroll');
END;
/
例 5-12 に示すとおり、型の宣言で NOT NULL 制約を指定する場合を除いて、NULL の要素をコ
ンストラクタに渡すことができます。
例 5-12 NULL の要素を含むコレクションのコンストラクタ
DECLARE
TYPE dnames_tab IS TABLE OF VARCHAR2(30);
dept_names dnames_tab;
TYPE dnamesNoNulls_type IS TABLE OF VARCHAR2(30) NOT NULL;
BEGIN
dept_names := dnames_tab('Shipping', NULL,'Finance', NULL);
-- If dept_names was of type dnamesNoNulls_type, we could not include
-- null values in the constructor
END;
/
例 5-13 に示すとおり、コレクションは、そのコレクションの宣言で初期化することができ、こ
れはプログラミング的に推奨される方法です。この場合は、そのコレクションの EXTEND メ
ソッドをコールして、後で要素を追加できます。
例 5-13 コレクション宣言とコンストラクタの組合せ
DECLARE
TYPE dnames_tab IS TABLE OF VARCHAR2(30);
dept_names dnames_tab := dnames_tab('Shipping','Sales','Finance','Payroll');
BEGIN
NULL;
END;
/
例 5-14 に示すとおり、引数を指定しないでコンストラクタをコールすると、空(NULL ではな
い)のコレクションを受け取ります。
例 5-14 空の VARRAY コンストラクタ
DECLARE
TYPE dnames_var IS VARRAY(20) OF VARCHAR2(30);
dept_names dnames_var;
BEGIN
IF dept_names IS NULL THEN
DBMS_OUTPUT.PUT_LINE('Before initialization, the varray is null.');
-- While the varray is null, we cannot check its COUNT attribute.
-DBMS_OUTPUT.PUT_LINE('It has ' || dept_names.COUNT || ' elements.');
ELSE
5-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクションの初期化および参照
DBMS_OUTPUT.PUT_LINE('Before initialization, the varray is not null.');
END IF;
dept_names := dnames_var(); -- initialize empty varray
IF dept_names IS NULL THEN
DBMS_OUTPUT.PUT_LINE('After initialization, the varray is null.');
ELSE
DBMS_OUTPUT.PUT_LINE('After initialization, the varray is not null.');
DBMS_OUTPUT.PUT_LINE('It has ' || dept_names.COUNT || ' elements.');
END IF;
END;
/
コレクション要素の参照
要素への参照はいずれも、コレクション名と添字をカッコで囲んで指定します。この添字に
よって、処理の対象となる要素が決まります。要素を参照するには、次の構文を使用してその
添字を指定します。
collection_name(subscript)
subscript は、ほとんどの場合、結果が整数になる式か、または文字列キーで宣言した結合配
列の場合は VARCHAR2 です。
使用できる添字範囲は、次のとおりです。
■
ネストした表の場合は、1 ~ 2147483647 です(PLS_INTEGER の上限)。
■
VARRAY の場合は、1 ~ size_limit(宣言に指定した制限)です(2147483647 以下)。
■
数値キーの結合配列の場合は、-2147483648 ~ 2147483647 です。
■
文字列キーの結合配列の場合、キーの長さおよび使用可能な値の数は、型宣言に指定した
VARCHAR2 の長さ制限およびデータベース・キャラクタ・セットによって異なります。
例 5-15 は、ネストした表の要素を参照する方法を示しています。
例 5-15 ネストした表の要素の参照
DECLARE
TYPE Roster IS TABLE OF VARCHAR2(15);
names Roster := Roster('D Caruso', 'J Hamil', 'D Piro', 'R Singh');
PROCEDURE verify_name(the_name VARCHAR2) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(the_name);
END;
BEGIN
FOR i IN names.FIRST .. names.LAST
LOOP
IF names(i) = 'J Hamil' THEN
DBMS_OUTPUT.PUT_LINE(names(i)); -- reference to nested table element
END IF;
END LOOP;
verify_name(names(3)); -- procedure call with reference to element
END;
/
例 5-16 に、ファンクション・コールでの結合配列の要素の参照方法を示します。
例 5-16 結合配列の要素の参照
DECLARE
TYPE sum_multiples IS TABLE OF PLS_INTEGER INDEX BY PLS_INTEGER;
n PLS_INTEGER := 5; -- number of multiples to sum for display
sn PLS_INTEGER := 10; -- number of multiples to sum
m PLS_INTEGER := 3; -- multiple
FUNCTION get_sum_multiples(multiple IN PLS_INTEGER, num IN PLS_INTEGER)
PL/SQL のコレクションおよびレコードの使用
5-11
コレクションの代入
RETURN sum_multiples IS
s sum_multiples;
BEGIN
FOR i IN 1..num LOOP
s(i) := multiple * ((i * (i + 1)) / 2) ; -- sum of multiples
END LOOP;
RETURN s;
END get_sum_multiples;
BEGIN
-- call function to retrieve the element identified by subscript (key)
DBMS_OUTPUT.PUT_LINE('Sum of the first ' || TO_CHAR(n) || ' multiples of ' ||
TO_CHAR(m) || ' is ' || TO_CHAR(get_sum_multiples (m, sn)(n)));
END;
/
コレクションの代入
あるコレクションを、INSERT 文、UPDATE 文、FETCH 文、SELECT 文、代入文またはサブプ
ログラム・コールよって、別のコレクションに代入できます。次の構文を使用すると、式の値
をコレクションの特定の要素に代入できます。
collection_name(subscript) := expression;
ここで、expression は結果がコレクション型定義の要素に指定された型の値です。
SET、MULTISET UNION、MULTISET INTERSECT、MULTISET EXCEPT などの演算子を使用
して、ネストした表を代入文の一部として変換できます。
値のコレクション要素への代入では、次のような例外が発生する可能性があります。
■
■
■
添字が NULL であったり、正しいデータ型に変換することができない場合、PL/SQL は事前
定義の例外 VALUE_ERROR を呼び出します。通常、添字は整数である必要があります。結
合配列では、VARCHAR2 の添字を使用するように宣言することもできます。
添字が初期化されていない要素を参照した場合、PL/SQL は SUBSCRIPT_BEYOND_COUNT
を呼び出します。
コレクションが基本構造的に NULL の場合、PL/SQL は COLLECTION_IS_NULL を呼び出
します。
コレクションの例外の詳細は、5-26 ページの「コレクション例外の回避」、5-26 ページの例
5-38 および 10-4 ページの「事前定義の PL/SQL 例外のまとめ」を参照してください。
例 5-17 は、代入の操作では、コレクションに同じデータ型が必要であることを示しています。
要素型が同じであることのみでは不十分です。
例 5-17 コレクション代入のデータ型の互換性
DECLARE
TYPE last_name_typ IS VARRAY(3) OF VARCHAR2(64);
TYPE surname_typ IS VARRAY(3) OF VARCHAR2(64);
-- These first two variables have the same datatype.
group1 last_name_typ := last_name_typ('Jones','Wong','Marceau');
group2 last_name_typ := last_name_typ('Klein','Patsos','Singh');
-- This third variable has a similar declaration, but is not the same type.
group3 surname_typ := surname_typ('Trevisi','Macleod','Marquez');
BEGIN
-- Allowed because they have the same datatype
group1 := group2;
-- Not allowed because they have different datatypes
-group3 := group2; -- raises an error
END;
/
5-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクションの代入
例 5-18 に示すとおり、基本構造的に NULL のネストした表または VARRAY を、第 2 のネスト
した表または VARRAY に代入する場合、第 2 のコレクションを再度初期化する必要がありま
す。同様に、値 NULL をコレクションに代入すると、コレクションは基本構造的に NULL にな
ります。
例 5-18 NULL 値のネストした表への代入
DECLARE
TYPE dnames_tab IS TABLE OF VARCHAR2(30);
-- This nested table has some values
dept_names dnames_tab := dnames_tab('Shipping','Sales','Finance','Payroll');
-- This nested table is not initialized ("atomically null").
empty_set dnames_tab;
BEGIN
-- At first, the initialized variable is not null.
if dept_names IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE('OK, at first dept_names is not null.');
END IF;
-- Then we assign a null nested table to it.
dept_names := empty_set;
-- Now it is null.
if dept_names IS NULL THEN
DBMS_OUTPUT.PUT_LINE('OK, now dept_names has become null.');
END IF;
-- We must use another constructor to give it some values.
dept_names := dnames_tab('Shipping','Sales','Finance','Payroll');
END;
/
例 5-19 では、ネストした表に適用可能な ANSI 規格のいくつかの演算子を示します。
例 5-19 集合演算子を使用したネストした表の代入
DECLARE
TYPE nested_typ IS TABLE OF NUMBER;
nt1 nested_typ := nested_typ(1,2,3);
nt2 nested_typ := nested_typ(3,2,1);
nt3 nested_typ := nested_typ(2,3,1,3);
nt4 nested_typ := nested_typ(1,2,4);
answer nested_typ;
-- The results might be in a different order than you expect.
-- Remember, you should not rely on the order of elements in nested tables.
PROCEDURE print_nested_table(the_nt nested_typ) IS
output VARCHAR2(128);
BEGIN
IF the_nt IS NULL THEN
DBMS_OUTPUT.PUT_LINE('Results: <NULL>');
RETURN;
END IF;
IF the_nt.COUNT = 0 THEN
DBMS_OUTPUT.PUT_LINE('Results: empty set');
RETURN;
END IF;
FOR i IN the_nt.FIRST .. the_nt.LAST
LOOP
output := output || the_nt(i) || ' ';
END LOOP;
DBMS_OUTPUT.PUT_LINE('Results: ' || output);
END;
BEGIN
answer := nt1 MULTISET UNION nt4; -- (1,2,3,1,2,4)
print_nested_table(answer);
answer := nt1 MULTISET UNION nt3; -- (1,2,3,2,3,1,3)
PL/SQL のコレクションおよびレコードの使用
5-13
コレクションの代入
print_nested_table(answer);
answer := nt1 MULTISET UNION DISTINCT nt3; -- (1,2,3)
print_nested_table(answer);
answer := nt2 MULTISET INTERSECT nt3; -- (3,2,1)
print_nested_table(answer);
answer := nt2 MULTISET INTERSECT DISTINCT nt3; -- (3,2,1)
print_nested_table(answer);
answer := SET(nt3); -- (2,3,1)
print_nested_table(answer);
answer := nt3 MULTISET EXCEPT nt2; -- (3)
print_nested_table(answer);
answer := nt3 MULTISET EXCEPT DISTINCT nt2; -- ()
print_nested_table(answer);
END;
/
例 5-20 に、代入文を使用したレコードの VARRAY への代入を示します。
例 5-20 複雑なデータ型を使用した VARRAY への値の代入
DECLARE
TYPE emp_name_rec is RECORD (
firstname
employees.first_name%TYPE,
lastname
employees.last_name%TYPE,
hiredate
employees.hire_date%TYPE
);
-- Array type that can hold information 10 employees
TYPE EmpList_arr IS VARRAY(10) OF emp_name_rec;
SeniorSalespeople EmpList_arr;
-- Declare a cursor to select a subset of columns.
CURSOR c1 IS SELECT first_name, last_name, hire_date FROM employees;
Type NameSet IS TABLE OF c1%ROWTYPE;
SeniorTen NameSet;
EndCounter NUMBER := 10;
BEGIN
SeniorSalespeople := EmpList_arr();
SELECT first_name, last_name, hire_date BULK COLLECT INTO SeniorTen FROM
employees WHERE job_id = 'SA_REP' ORDER BY hire_date;
IF SeniorTen.LAST > 0 THEN
IF SeniorTen.LAST < 10 THEN EndCounter := SeniorTen.LAST;
END IF;
FOR i in 1..EndCounter LOOP
SeniorSalespeople.EXTEND(1);
SeniorSalespeople(i) := SeniorTen(i);
DBMS_OUTPUT.PUT_LINE(SeniorSalespeople(i).lastname || ', '
|| SeniorSalespeople(i).firstname || ', ' ||
SeniorSalespeople(i).hiredate);
END LOOP;
END IF;
END;
/
例 5-21 に、FETCH 文を使用したレコードのネストした表への代入を示します。
例 5-21 複雑なデータ型を使用した表への値の代入
DECLARE
TYPE emp_name_rec is RECORD (
firstname
employees.first_name%TYPE,
lastname
employees.last_name%TYPE,
hiredate
employees.hire_date%TYPE
5-14
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクションの比較
);
-- Table type that can hold information about employees
TYPE EmpList_tab IS TABLE OF emp_name_rec;
SeniorSalespeople EmpList_tab;
-- Declare a cursor to select a subset of columns.
CURSOR c1 IS SELECT first_name, last_name, hire_date FROM employees;
EndCounter NUMBER := 10;
TYPE EmpCurTyp IS REF CURSOR;
emp_cv EmpCurTyp;
BEGIN
OPEN emp_cv FOR SELECT first_name, last_name, hire_date FROM employees
WHERE job_id = 'SA_REP' ORDER BY hire_date;
FETCH emp_cv BULK COLLECT INTO SeniorSalespeople;
CLOSE emp_cv;
-- for this example, display a maximum of ten employees
IF SeniorSalespeople.LAST > 0 THEN
IF SeniorSalespeople.LAST < 10 THEN EndCounter := SeniorSalespeople.LAST;
END IF;
FOR i in 1..EndCounter LOOP
DBMS_OUTPUT.PUT_LINE(SeniorSalespeople(i).lastname || ', '
|| SeniorSalespeople(i).firstname || ', ' || SeniorSalespeople(i).hiredate);
END LOOP;
END IF;
END;
/
コレクションの比較
コレクションが NULL かどうかをチェックできます。大きい、未満などの比較は実行できませ
ん。この制限は、暗黙的な比較にも適用されます。たとえば、コレクションは DISTINCT、
GROUP BY または ORDER BY リストには使用できません。
このような比較操作を行う場合は、2 つのコレクションが大きい、小さいなどを判断する手段
をユーザーが任意に定義し、コレクションとその要素の調査結果を TRUE または FALSE の値
で戻すような 1 つ以上のファンクションを記述する必要があります。
例 5-23 に示すとおり、ネストした表の場合は、宣言された同じ型の 2 つのネストした表が等し
いかどうかをチェックできます。また、例 5-24 に示すとおり、集合演算子(CARDINALITY、
MEMBER OF、IS A SET、IS EMPTY など)を適用して、1 つのネストした表内または 2 つの
ネストした表の間で、特定の条件をチェックすることもできます。
ネストした表と VARRAY は、基本構造的に NULL である場合があるため、例 5-22 に示すとお
り、NULL かどうかをテストできます。
例 5-22 コレクションが NULL かどうかのチェック
DECLARE
TYPE emp_name_rec is RECORD (
firstname
employees.first_name%TYPE,
lastname
employees.last_name%TYPE,
hiredate
employees.hire_date%TYPE
);
TYPE staff IS TABLE OF emp_name_rec;
members staff;
BEGIN
-- Condition yields TRUE because we have not used a constructor.
IF members IS NULL THEN
DBMS_OUTPUT.PUT_LINE('NULL');
PL/SQL のコレクションおよびレコードの使用
5-15
コレクションの比較
ELSE
DBMS_OUTPUT.PUT_LINE('Not NULL');
END IF;
END;
/
例 5-23 に、ネストした表が等しいか等しくないかの比較を示します。大きいまたは未満の比較
は実行できないため、順序付けすることはできません。
例 5-23 2 つのネストした表の比較
DECLARE
TYPE dnames_tab IS TABLE OF VARCHAR2(30);
dept_names1 dnames_tab := dnames_tab('Shipping','Sales','Finance','Payroll');
dept_names2 dnames_tab := dnames_tab('Sales','Finance','Shipping','Payroll');
dept_names3 dnames_tab := dnames_tab('Sales','Finance','Payroll');
BEGIN
-- We can use = or !=, but not < or >.
-- Notice that these 2 are equal even though the members are in different order.
IF dept_names1 = dept_names2 THEN
DBMS_OUTPUT.PUT_LINE('dept_names1 and dept_names2 have the same members.');
END IF;
IF dept_names2 != dept_names3 THEN
DBMS_OUTPUT.PUT_LINE('dept_names2 and dept_names3 have different members.');
END IF;
END;
/
例 5-24 に示すとおり、ANSI 規格の集合演算子を使用して、ネストした表の特定のプロパティ
をテストしたり、2 つのネストした表を比較することができます。
例 5-24 集合演算子を使用したネストした表の比較
DECLARE
TYPE nested_typ IS TABLE OF NUMBER;
nt1 nested_typ := nested_typ(1,2,3);
nt2 nested_typ := nested_typ(3,2,1);
nt3 nested_typ := nested_typ(2,3,1,3);
nt4 nested_typ := nested_typ(1,2,4);
answer BOOLEAN;
howmany NUMBER;
PROCEDURE testify(truth BOOLEAN DEFAULT NULL, quantity NUMBER DEFAULT NULL) IS
BEGIN
IF truth IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE(CASE truth WHEN TRUE THEN 'True' WHEN FALSE THEN 'False'
END);
END IF;
IF quantity IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE(quantity);
END IF;
END;
BEGIN
answer := nt1 IN (nt2,nt3,nt4); -- true, nt1 matches nt2
testify(truth => answer);
answer := nt1 SUBMULTISET OF nt3; -- true, all elements match
testify(truth => answer);
answer := nt1 NOT SUBMULTISET OF nt4; -- also true
testify(truth => answer);
howmany := CARDINALITY(nt3); -- number of elements in nt3
testify(quantity => howmany);
howmany := CARDINALITY(SET(nt3)); -- number of distinct elements
testify(quantity => howmany);
answer := 4 MEMBER OF nt1; -- false, no element matches
5-16
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
マルチレベル・コレクションの使用
testify(truth
answer := nt3
testify(truth
answer := nt3
testify(truth
answer := nt1
testify(truth
END;
/
=>
IS
=>
IS
=>
IS
=>
answer);
A SET; -- false, nt3 has duplicates
answer);
NOT A SET; -- true, nt3 has duplicates
answer);
EMPTY; -- false, nt1 has some members
answer);
マルチレベル・コレクションの使用
スカラー型やオブジェクト型のコレクションの他に、コレクションを要素に持つコレクション
も作成できます。たとえば、VARRAY のネストした表、VARRAY の VARRAY、ネストした表
の VARRAY などを作成できます。
ネストした表のネストした表を SQL の列として作成する場合は、CREATE TABLE 文の構文を
チェックして、記憶表の定義方法を確認します。
例 5-25、例 5-26 および例 5-27 に、マルチレベル・コレクションの構文と機能性を示します。
12-11 ページの例 12-17「ネストした表での BULK COLLECT の使用」も参照してください。
例 5-25 マルチレベル VARRAY
DECLARE
TYPE t1 IS VARRAY(10) OF INTEGER;
TYPE nt1 IS VARRAY(10) OF t1; -- multilevel varray type
va t1 := t1(2,3,5);
-- initialize multilevel varray
nva nt1 := nt1(va, t1(55,6,73), t1(2,4), va);
i INTEGER;
va1 t1;
BEGIN
-- multilevel access
i := nva(2)(3); -- i will get value 73
DBMS_OUTPUT.PUT_LINE('I = ' || i);
-- add a new varray element to nva
nva.EXTEND;
-- replace inner varray elements
nva(5) := t1(56, 32);
nva(4) := t1(45,43,67,43345);
-- replace an inner integer element
nva(4)(4) := 1; -- replaces 43345 with 1
-- add a new element to the 4th varray element
-- and store integer 89 into it.
nva(4).EXTEND;
nva(4)(5) := 89;
END;
/
例 5-26 マルチレベルのネストした表
DECLARE
TYPE tb1 IS TABLE OF VARCHAR2(20);
TYPE Ntb1 IS TABLE OF tb1; -- table of table elements
TYPE Tv1 IS VARRAY(10) OF INTEGER;
TYPE ntb2 IS TABLE OF tv1; -- table of varray elements
vtb1 tb1 := tb1('one', 'three');
vntb1 ntb1 := ntb1(vtb1);
vntb2 ntb2 := ntb2(tv1(3,5), tv1(5,7,3)); -- table of varray elements
BEGIN
vntb1.EXTEND;
PL/SQL のコレクションおよびレコードの使用
5-17
コレクション・メソッドの使用
vntb1(2) := vntb1(1);
-- delete the first element in vntb1
vntb1.DELETE(1);
-- delete the first string from the second table in the nested table
vntb1(2).DELETE(1);
END;
/
例 5-27 マルチレベルの結合配列
DECLARE
TYPE tb1 IS TABLE OF INTEGER INDEX BY PLS_INTEGER;
-- the following is index-by table of index-by tables
TYPE ntb1 IS TABLE OF tb1 INDEX BY PLS_INTEGER;
TYPE va1 IS VARRAY(10) OF VARCHAR2(20);
-- the following is index-by table of varray elements
TYPE ntb2 IS TABLE OF va1 INDEX BY PLS_INTEGER;
v1 va1 := va1('hello', 'world');
v2 ntb1;
v3 ntb2;
v4 tb1;
v5 tb1; -- empty table
BEGIN
v4(1) := 34;
v4(2) := 46456;
v4(456) := 343;
v2(23) := v4;
v3(34) := va1(33, 456, 656, 343);
-- assign an empty table to v2(35) and try again
v2(35) := v5;
v2(35)(2) := 78; -- it works now
END;
/
コレクション・メソッドの使用
コレクション・メソッドを使用すると、コレクションの使用およびアプリケーションのメンテ
ナンスが簡単になります。コレクション・メソッドには、COUNT、DELETE、EXISTS、
EXTEND、FIRST、LAST、LIMIT、NEXT、PRIOR、TRIM などがあります。
コレクション・メソッドとは、コレクションに対する操作を実行するための、ドット表記法を
使用してコールされる組込みファンクションまたはプロシージャです。コレクション・メソッ
ドには、次が適用されます。
■
コレクション・メソッドは、SQL 文からはコールできません。
■
EXTEND と TRIM は、結合配列で使用できません。
■
■
■
EXISTS、COUNT、LIMIT、FIRST、LAST、PRIOR および NEXT は、ファンクションです。
EXTEND、TRIM および DELETE はプロシージャです。
EXISTS、PRIOR、NEXT、TRIM、EXTEND および DELETE は、コレクションの添字に対応
するパラメータを取ります。通常、この添字は整数ですが、結合配列の場合は文字列も使
用できます。
基本構造的に NULL であるコレクションに適用されるのは EXISTS のみです。それ以外の
メソッドをそのようなコレクションに適用すると、PL/SQL は COLLECTION_IS_NULL を
呼び出します。
詳細は、13-19 ページの「コレクション・メソッド」を参照してください。
5-18
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクション・メソッドの使用
コレクション要素の存在のチェック(EXISTS
メソッド)
コレクション要素の存在のチェック(
EXISTS(n) は、コレクションに n 番目の要素が存在する場合に TRUE を戻します。それ以外の
場合、EXISTS(n) は FALSE を戻します。EXISTS と DELETE を組み合せると、疎であるネス
トした表を操作できます。また、EXISTS を使用すると、存在しない要素を参照したことによ
る例外の発生を回避できます。範囲外の添字を渡した場合、EXISTS は
SUBSCRIPT_OUTSIDE_LIMIT を呼び出さずに、FALSE を戻します。
例 5-28 コレクション要素の EXISTS のチェック
DECLARE
TYPE NumList IS TABLE OF INTEGER;
n NumList := NumList(1,3,5,7);
BEGIN
n.DELETE(2); -- Delete the second element
IF n.EXISTS(1) THEN
DBMS_OUTPUT.PUT_LINE('OK, element #1 exists.');
END IF;
IF n.EXISTS(2) = FALSE THEN
DBMS_OUTPUT.PUT_LINE('OK, element #2 has been deleted.');
END IF;
IF n.EXISTS(99) = FALSE THEN
DBMS_OUTPUT.PUT_LINE('OK, element #99 does not exist at all.');
END IF;
END;
/
コレクション内の要素数のカウント(COUNT
コレクション内の要素数のカウント(
メソッド)
COUNT は、コレクションに現在含まれている要素の数を戻します。
例 5-29 COUNT を使用したコレクションの要素のカウント
DECLARE
TYPE NumList IS TABLE OF NUMBER;
n NumList := NumList(2,4,6,8); -- Collection starts with 4 elements.
BEGIN
DBMS_OUTPUT.PUT_LINE('There are ' || n.COUNT || ' elements in N.');
n.EXTEND(3); -- Add 3 new elements at the end.
DBMS_OUTPUT.PUT_LINE('Now there are ' || n.COUNT || ' elements in N.');
n := NumList(86,99); -- Assign a completely new value with 2 elements.
DBMS_OUTPUT.PUT_LINE('Now there are ' || n.COUNT || ' elements in N.');
n.TRIM(2); -- Remove the last 2 elements, leaving none.
DBMS_OUTPUT.PUT_LINE('Now there are ' || n.COUNT || ' elements in N.');
END;
/
コレクションの現在のサイズは不明の場合があるため、そのような場合に COUNT が役立ちま
す。たとえば、Oracle データの列をフェッチしてネストした表に入れることができます。この
場合、結果セットのサイズに応じて要素の数を決めます。
VARRAY の場合、COUNT は常に LAST と同じです。EXTEND および TRIM メソッドを使用し
て、VARRAY のサイズを増減できます。この場合、COUNT 値の上限は LIMIT メソッドで指定
した値になります。
ネストした表の場合、COUNT は通常、LAST と同じです。ただし、ネストした表の途中から要
素を削除すると、COUNT は LAST より小さくなります。要素を総計するときに、COUNT は削除
された要素を無視します。DELETE をパラメータ・セットを指定せずに使用すると、COUNT が
0 に設定されます。
PL/SQL のコレクションおよびレコードの使用
5-19
コレクション・メソッドの使用
コレクションの最大サイズのチェック(LIMIT
メソッド)
コレクションの最大サイズのチェック(
サイズが宣言されていないネストした表や結合配列の場合、LIMIT は NULL を戻します。
VARRAY の場合、LIMIT は VARRAY に入れることのできる要素の最大数を戻します。この最
大数は型定義で指定し、TRIM メソッドや EXTEND メソッドを使用して後で変更できます。
例 5-30 LIMIT を使用したコレクションの最大サイズのチェック
DECLARE
TYPE dnames_var IS VARRAY(7) OF VARCHAR2(30);
dept_names dnames_var := dnames_var('Shipping','Sales','Finance','Payroll');
BEGIN
DBMS_OUTPUT.PUT_LINE('dept_names has ' || dept_names.COUNT
|| ' elements now');
DBMS_OUTPUT.PUT_LINE('dept_names''s type can hold a maximum of '
|| dept_names.LIMIT || ' elements');
DBMS_OUTPUT.PUT_LINE('The maximum number you can use with '
|| 'dept_names.EXTEND() is ' || (dept_names.LIMIT - dept_names.COUNT));
END;
/
最初または最後のコレクション要素の検索(FIRST
メソッドとLAST
メソッド)
最初または最後のコレクション要素の検索(
メソッドと
FIRST と LAST は、それぞれ整数の添字を使用しているコレクションの最初と最後(最小と最
大)の索引番号を戻します。
キー値が VARCHAR2 の結合配列の場合は、最小および最大のキー値が戻ります。デフォルトで
は、文字列内の文字のバイナリ値に基づいて順序付けが行われます。NLS_COMP 初期化パラ
メータが ANSI に設定されている場合、順序付けは NLS_SORT 初期化パラメータで指定したロ
ケール固有のソート順に基づきます。
コレクションが空の場合、FIRST と LAST は NULL を戻します。コレクションに含まれる要素
の数が 1 つのみの場合、FIRST と LAST は同じ索引値を戻します。
例 5-31 に、FIRST および LAST を使用して、添字が連続しているコレクションの要素に対して
反復処理を実行する方法を示します。
例 5-31 コレクションでの FIRST および LAST の使用
DECLARE
TYPE NumList IS TABLE OF NUMBER;
n NumList := NumList(1,3,5,7);
counter INTEGER;
BEGIN
DBMS_OUTPUT.PUT_LINE('N''s first subscript is ' || n.FIRST);
DBMS_OUTPUT.PUT_LINE('N''s last subscript is ' || n.LAST);
-- When the subscripts are consecutive starting at 1,
-- it's simple to loop through them.
FOR i IN n.FIRST .. n.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Element #' || i || ' = ' || n(i));
END LOOP;
n.DELETE(2); -- Delete second element.
-- When the subscripts have gaps or the collection might be uninitialized,
-- the loop logic is more extensive. We start at the first element, and
-- keep looking for the next element until there are no more.
IF n IS NOT NULL THEN
counter := n.FIRST;
WHILE counter IS NOT NULL
LOOP
DBMS_OUTPUT.PUT_LINE('Element #' || counter || ' = ' || n(counter));
counter := n.NEXT(counter);
5-20
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクション・メソッドの使用
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('N is null, nothing to do.');
END IF;
END;
/
VARRAY の場合、FIRST は常に 1 を戻し、LAST は常に COUNT と同じです。
ネストした表の場合、通常は FIRST は 1 を戻し、LAST は COUNT と同じです。ただし、ネスト
した表の先頭から要素を削除すると、FIRST は 1 より大きい数値を戻します。また、ネストし
た表の途中から要素を削除すると、LAST は COUNT より大きくなります。
要素をスキャンするときに、FIRST および LAST は削除された要素を無視します。
コレクションの各要素のループ(PRIOR
メソッドと NEXT メソッド)
コレクションの各要素のループ(
PRIOR(n) は、コレクションの索引 n の前の索引番号を戻します。NEXT(n) は、索引 n の後の
索引番号を戻します。n の前の番号がない場合、PRIOR(n) は NULL を戻します。n の後の番号
がない場合、NEXT(n) は NULL を戻します。
キーが VARCHAR2 型の結合配列の場合は、これらのメソッドは適切なキー値を戻します。
NLS_COMP 初期化パラメータが ANSI に設定されていないかぎり、順序付けは文字列内の文字
のバイナリ値に従います。この場合、ANSI の場合の順序付けは、NLS_SORT 初期化パラメー
タで指定したロケール固有のソート順に従います。
これらのメソッドは、添字の値の固定セットを使用したループに比べて高い信頼性があります。
これは、ループ中にコレクションの要素が挿入または削除される可能性があるためです。特に
結合配列の場合、添字は連続した順序ではないため、添字の順序が(1、2、4、8、16)や
('A'、'E'、'I'、'O'、'U')となっている可能性があります。
例 5-32 PRIOR および NEXT を使用したコレクションの要素へのアクセス
DECLARE
TYPE NumList IS TABLE OF NUMBER;
n NumList := NumList(1966,1971,1984,1989,1999);
BEGIN
DBMS_OUTPUT.PUT_LINE('The element after #2 is #' || n.NEXT(2));
DBMS_OUTPUT.PUT_LINE('The element before #2 is #' || n.PRIOR(2));
n.DELETE(3); -- Delete an element to show how NEXT can handle gaps.
DBMS_OUTPUT.PUT_LINE('Now the element after #2 is #' || n.NEXT(2));
IF n.PRIOR(n.FIRST) IS NULL THEN
DBMS_OUTPUT.PUT_LINE('Can''t get PRIOR of the first element or NEXT of the
last.');
END IF;
END;
/
PRIOR または NEXT を使用すると、任意の添字列を索引とするコレクション内を移動できます。
例 5-33 では、NEXT を使用して、いくつかの要素が削除されたネストした表内を移動していま
す。
例 5-33 ネストした表の要素への NEXT を使用したアクセス
DECLARE
TYPE NumList IS TABLE OF NUMBER;
n NumList := NumList(1,3,5,7);
counter INTEGER;
BEGIN
n.DELETE(2); -- Delete second element.
-- When the subscripts have gaps, the loop logic is more extensive. We start at
PL/SQL のコレクションおよびレコードの使用
5-21
コレクション・メソッドの使用
-- the first element, and keep looking for the next element until there are no more.
counter := n.FIRST;
WHILE counter IS NOT NULL
LOOP
DBMS_OUTPUT.PUT_LINE('Counting up: Element #' || counter || ' = ' ||
n(counter));
counter := n.NEXT(counter);
END LOOP;
-- Run the same loop in reverse order.
counter := n.LAST;
WHILE counter IS NOT NULL
LOOP
DBMS_OUTPUT.PUT_LINE('Counting down: Element #' || counter || ' = ' ||
n(counter));
counter := n.PRIOR(counter);
END LOOP;
END;
/
要素間を横断するときに、PRIOR および NEXT は削除された要素をスキップします。
コレクションのサイズの拡大(EXTEND
メソッド)
コレクションのサイズの拡大(
ネストした表または VARRAY のサイズを大きくするには、EXTEND を使用します。
このプロシージャには次の 3 つの形式があります。
■
EXTEND は、コレクションに 1 つの NULL 要素を追加します。
■
EXTEND(n) は、コレクションに n 個の NULL 要素を追加します。
■
EXTEND(n,i) は、コレクションに i 番目の要素のコピーを n 個追加します。
索引付き表で EXTEND を使用することはできません。EXTEND を使用して、初期化されていな
いコレクションに要素を追加することはできません。NOT NULL 制約を TABLE または VARRAY
型に指定した場合、EXTEND の最初の 2 つの形式はその型のコレクションに適用できません。
EXTEND は、コレクションの内部サイズ(削除された要素を含む)を操作します。これは、す
べての要素を完全に削除するパラメータを指定しない DELETE ではなく、DELETE(n) を使用
して削除された要素を指します。EXTEND は削除された要素を見つけると、それらの要素を数
に含めます。PL/SQL は削除された要素のプレースホルダを保持するため、新しい値を代入し
て要素を再作成できます。
例 5-34 EXTEND を使用したコレクションのサイズの拡大
DECLARE
TYPE NumList IS TABLE OF INTEGER;
n NumList := NumList(2,4,6,8);
x NumList := NumList(1,3);
PROCEDURE print_numlist(the_list NumList) IS
output VARCHAR2(128);
BEGIN
FOR i IN the_list.FIRST .. the_list.LAST
LOOP
output := output || NVL(TO_CHAR(the_list(i)),'NULL') || ' ';
END LOOP;
DBMS_OUTPUT.PUT_LINE(output);
END;
BEGIN
DBMS_OUTPUT.PUT_LINE('At first, N has ' || n.COUNT || ' elements.');
n.EXTEND(5); -- Add 5 elements at the end.
DBMS_OUTPUT.PUT_LINE('Now N has ' || n.COUNT || ' elements.');
-- Elements 5, 6, 7, 8, and 9 are all NULL.
print_numlist(n);
5-22
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクション・メソッドの使用
DBMS_OUTPUT.PUT_LINE('At first, X has ' || x.COUNT || ' elements.');
x.EXTEND(4,2); -- Add 4 elements at the end.
DBMS_OUTPUT.PUT_LINE('Now X has ' || x.COUNT || ' elements.');
-- Elements 3, 4, 5, and 6 are copies of element #2.
print_numlist(x);
END;
/
削除された要素を含めると、ネストした表の内部サイズは、COUNT と LAST が戻す値とは異な
ります。これは、すべての要素を完全に削除するパラメータを指定しない DELETE ではなく、
DELETE(n) を使用して削除された要素を指します。たとえば、ネストした表を 5 つの要素で初
期化してから、要素 2 と要素 5 を削除した場合、内部サイズは 5 で、COUNT は 3 を戻し、LAST
は 4 を戻します。削除されたすべての要素は、その位置に関係なく同様に処理されます。
コレクションのサイズの縮小(TRIM
メソッド)
コレクションのサイズの縮小(
このプロシージャには次の 2 つの形式があります。
■
TRIM は、コレクションの末尾から 1 つの要素を削除します。
■
TRIM(n) は、コレクションの末尾から n 個の要素を削除します。
すべての要素を削除する場合は、パラメータを指定せずに DELETE を使用します。
たとえば、次の文では、ネストした表の courses から最後の 3 つの要素を削除します。
例 5-35 TRIM を使用したコレクションのサイズの縮小
DECLARE
TYPE NumList IS TABLE OF NUMBER;
n NumList := NumList(1,2,3,5,7,11);
PROCEDURE print_numlist(the_list NumList) IS
output VARCHAR2(128);
BEGIN
IF n.COUNT = 0 THEN
DBMS_OUTPUT.PUT_LINE('No elements in collection.');
ELSE
FOR i IN the_list.FIRST .. the_list.LAST
LOOP
output := output || NVL(TO_CHAR(the_list(i)),'NULL') || ' ';
END LOOP;
DBMS_OUTPUT.PUT_LINE(output);
END IF;
END;
BEGIN
print_numlist(n);
n.TRIM(2); -- Remove last 2 elements.
print_numlist(n);
n.TRIM; -- Remove last element.
print_numlist(n);
n.TRIM(n.COUNT); -- Remove all remaining elements.
print_numlist(n);
-- If too many elements are specified,
-- TRIM raises the exception SUBSCRIPT_BEYOND_COUNT.
BEGIN
n := NumList(1,2,3);
n.TRIM(100);
EXCEPTION
WHEN SUBSCRIPT_BEYOND_COUNT THEN
DBMS_OUTPUT.PUT_LINE('I guess there weren''t 100 elements that could be
trimmed.');
END;
PL/SQL のコレクションおよびレコードの使用
5-23
コレクション・メソッドの使用
-- When elements are removed by DELETE, placeholders are left behind. TRIM counts
-- these placeholders as it removes elements from the end.
n := NumList(1,2,3,4);
n.DELETE(3); -- delete element 3
-- At this point, n contains elements (1,2,4).
-- TRIMming the last 2 elements removes the 4 and the placeholder, not 4 and 2.
n.TRIM(2);
print_numlist(n);
END;
/
n が大きすぎる場合、TRIM(n) は SUBSCRIPT_BEYOND_COUNT を呼び出します。
TRIM は、コレクションの内部サイズを操作します。TRIM は削除された要素を見つけると、そ
れらの要素を数に含めます。これは、すべての要素を完全に削除するパラメータを指定しない
DELETE ではなく、DELETE(n) を使用して削除された要素を指します。
例 5-36 削除された要素に対する TRIM の使用
DECLARE
TYPE CourseList IS TABLE OF VARCHAR2(10);
courses CourseList;
BEGIN
courses := CourseList('Biol 4412', 'Psyc 3112', 'Anth 3001');
courses.DELETE(courses.LAST); -- delete element 3
/* At this point, COUNT equals 2, the number of valid
elements remaining. So, you might expect the next
statement to empty the nested table by trimming
elements 1 and 2. Instead, it trims valid element 2
and deleted element 3 because TRIM includes deleted
elements in its tally. */
courses.TRIM(courses.COUNT);
DBMS_OUTPUT.PUT_LINE(courses(1)); -- prints 'Biol 4412'
END;
/
一般に、TRIM と DELETE の間の相互作用には依存しないでください。ネストした表は、固定
サイズの配列のように扱って DELETE のみを使用するか、またはスタックのように扱って
TRIM と EXTEND のみを使用することをお薦めします。
PL/SQL は切り捨てられた(TRIM)要素のプレースホルダを保持しないため、切り捨てられた
要素に新しい値を代入するのみではその要素を置き換えることができません。
コレクション要素の削除(DELETE
メソッド)
コレクション要素の削除(
このプロシージャには次の様な形式があります。
■
■
■
5-24
パラメータを指定しない DELETE はコレクションからすべての要素を削除し、COUNT を 0
に設定します。
DELETE(n) は、数値キーの結合配列またはネストした表から n 番目の要素を削除します。
結合配列のキーが文字列の場合は、そのキー値に対応する要素が削除されます。n が
NULL である場合、DELETE(n) は何も実行しません。
DELETE(m,n) は、結合配列またはネストした表から m ~ n の範囲のすべての要素を削除し
ます。m が n より大きい場合、または m か n が NULL である場合、DELETE(m,n) は何も
実行しません。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクション・メソッドの使用
次に例を示します。
例 5-37 コレクションに対する DELETE メソッドの使用
DECLARE
TYPE NumList IS TABLE OF NUMBER;
n NumList := NumList(10,20,30,40,50,60,70,80,90,100);
TYPE NickList IS TABLE OF VARCHAR2(64) INDEX BY VARCHAR2(32);
nicknames NickList;
BEGIN
n.DELETE(2);
-- deletes element 2
n.DELETE(3,6); -- deletes elements 3 through 6
n.DELETE(7,7); -- deletes element 7
n.DELETE(6,3); -- does nothing since 6 > 3
n.DELETE;
-- deletes all elements
nicknames('Bob') := 'Robert';
nicknames('Buffy') := 'Esmerelda';
nicknames('Chip') := 'Charles';
nicknames('Dan') := 'Daniel';
nicknames('Fluffy') := 'Ernestina';
nicknames('Rob') := 'Robert';
-- following deletes element denoted by this key
nicknames.DELETE('Chip');
-- following deletes elements with keys in this alphabetic range
nicknames.DELETE('Buffy','Fluffy');
END;
/
VARRAY の添字は常に連続しているため、TRIM メソッドを使用して末尾の要素を削除するこ
とを除き、個の要素は削除できません。パラメータを指定せずに DELETE を使用すると、すべ
ての要素を削除できます。
削除対象の要素が存在しない場合でも、DELETE(n) は単にその要素をスキップするため、例外
は呼び出されません。PL/SQL は削除された要素のプレースホルダを保持するため、削除され
た要素に新しい値を代入して、その要素を置き換えることができます。これは、すべての要素
を完全に削除するパラメータを指定しない DELETE ではなく、DELETE(n) を使用して削除さ
れた要素を指します。
DELETE を使用すると、疎であるネストした表を維持できます。疎であるネストした表は、そ
の他のネストした表と同様に、データベース内に格納できます。
ネストした表に割り当てられるメモリーの量は、動的に増減します。要素を削除すると、メモ
リーはページ単位で解放されます。表全体を削除した場合は、すべてのメモリーが解放されま
す。
コレクション・パラメータへのメソッドの適用
サブプログラム内で、コレクション・パラメータは引数のプロパティがバインドされているこ
とを前提にしています。組込みコレクション・メソッド(FIRST、LAST、COUNT など)をその
ようなパラメータに適用できます。コレクション・パラメータを取って要素に反復処理を実行
したり、要素を追加または削除する、汎用目的のサブプログラムを作成できます。VARRAY パ
ラメータの場合、パラメータ・モードに関係なく、LIMIT の値は常にパラメータの型定義から
導出されます。
PL/SQL のコレクションおよびレコードの使用
5-25
コレクション例外の回避
コレクション例外の回避
例 5-38 に、PL/SQL によって事前に定義されている様々なコレクションの例外を示します。ま
た、この例では、問題を回避するための注釈も示します。
例 5-38 コレクションに関する例外
DECLARE
TYPE WordList IS TABLE OF VARCHAR2(5);
words WordList;
err_msg VARCHAR2(100);
PROCEDURE display_error IS
BEGIN
err_msg := SUBSTR(SQLERRM, 1, 100);
DBMS_OUTPUT.PUT_LINE('Error message = ' || err_msg);
END;
BEGIN
BEGIN
words(1) := 10; -- Raises COLLECTION_IS_NULL
-- A constructor has not been used yet.
-- Note: This exception applies to varrays and nested tables,
-- but not to associative arrays which do not need a constructor.
EXCEPTION
WHEN OTHERS THEN display_error;
END;
-- After using a constructor, we can assign values to the elements.
words := WordList('1st', '2nd', '3rd'); -- 3 elements created
-- Any expression that returns a VARCHAR2(5) is valid.
words(3) := words(1) || '+2';
BEGIN
words(3) := 'longer than 5 characters'; -- Raises VALUE_ERROR
-- The assigned value is too long.
EXCEPTION
WHEN OTHERS THEN display_error;
END;
BEGIN
words('B') := 'dunno'; -- Raises VALUE_ERROR
-- The subscript (B) of a nested table must be an integer.
-- Note: Also, NULL is not allowed as a subscript.
EXCEPTION
WHEN OTHERS THEN display_error;
END;
BEGIN
words(0) := 'zero'; -- Raises SUBSCRIPT_OUTSIDE_LIMIT
-- Subscript 0 is outside the allowed subscript range.
EXCEPTION
WHEN OTHERS THEN display_error;
END;
BEGIN
words(4) := 'maybe'; -- Raises SUBSCRIPT_BEYOND_COUNT
-- The subscript (4) exceeds the number of elements in the table.
-- To add new elements, call the EXTEND method first.
EXCEPTION
WHEN OTHERS THEN display_error;
END;
BEGIN
words.DELETE(1);
IF words(1) = 'First' THEN NULL; END IF; -- Raises NO_DATA_FOUND
-- The element with subcript (1) has been deleted.
EXCEPTION
5-26
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクション例外の回避
WHEN OTHERS THEN display_error;
END;
END;
/
発生した例外はサブブロックで処理されるため、例 5-38 では、実行が継続されます。10-15
ページの「例外が呼び出された後に実行を続ける方法」を参照してください。例外処理での
SQLERRM の使用については、10-13 ページの「エラー・コードとエラー・メッセージの取得 :
SQLCODE および SQLERRM」を参照してください。
次のリストは、指定された例外が呼び出される場合を示しています。10-4 ページの「事前定義
の PL/SQL 例外のまとめ」を参照してください。
コレクションに関する例外
呼び出される場合
COLLECTION_IS_NULL
基本構造的に NULL のコレクションに対して操作を試みた
場合。
NO_DATA_FOUND
添字で、削除されている要素や結合配列の存在していない要
素が指定された場合。
SUBSCRIPT_BEYOND_COUNT
添字がコレクションの中の要素数を超えている場合。
SUBSCRIPT_OUTSIDE_LIMIT
添字が有効範囲外である場合。
VALUE_ERROR
添字が NULL か、またはキーの型に変換できない場合。こ
の例外は、キーが PLS_INTEGER の範囲として定義され、添
字がこの範囲外の場合に発生する可能性があります。
場合によっては、例外を呼び出さずに、無効な添字をメソッドに渡すことができます。たとえ
ば、添字 NULL を DELETE(n) に渡しても、何も実行されません。削除された要素に値を代入
すると、NO_DATA_FOUND を呼び出さずにその要素を置き換えることができます。これは、す
べての要素を完全に削除するパラメータを指定しない DELETE ではなく、DELETE(n) を使用
して削除された要素を指します。次に例を示します。
例 5-39 DELETE(n) による無効な添字の処理
DECLARE
TYPE NumList IS TABLE OF NUMBER;
nums NumList := NumList(10,20,30); -- initialize table
BEGIN
nums.DELETE(-1); -- does not raise SUBSCRIPT_OUTSIDE_LIMIT
nums.DELETE(3); -- delete 3rd element
DBMS_OUTPUT.PUT_LINE(nums.COUNT); -- prints 2
nums(3) := 30;
-- allowed; does not raise NO_DATA_FOUND
DBMS_OUTPUT.PUT_LINE(nums.COUNT); -- prints 3
END;
/
パッケージ・コレクション型とローカル・コレクション型には互換性がありません。たとえば、
次のパッケージ・プロシージャをコールするとします。
例 5-40 パッケージ・コレクション型とローカル・コレクション型の非互換性
CREATE PACKAGE pkg AS
TYPE NumList IS TABLE OF NUMBER;
PROCEDURE print_numlist (nums NumList);
END pkg;
/
CREATE PACKAGE BODY pkg AS
PROCEDURE print_numlist (nums NumList) IS
BEGIN
FOR i IN nums.FIRST..nums.LAST LOOP
DBMS_OUTPUT.PUT_LINE(nums(i));
PL/SQL のコレクションおよびレコードの使用
5-27
レコードの定義と宣言
END LOOP;
END;
END pkg;
/
DECLARE
TYPE NumList IS TABLE OF NUMBER;
n1 pkg.NumList := pkg.NumList(2,4); -- type from the package.
n2 NumList := NumList(6,8);
-- local type.
BEGIN
pkg.print_numlist(n1); -- type from pkg is legal
-- The packaged procedure cannot accept a value of the local type (n2)
-- pkg.print_numlist(n2); -- Causes a compilation error.
END;
/
2 番目のプロシージャ・コールは失敗します。これは、パッケージおよびローカルの VARRAY
型は定義が同一でも互換性がないためです。
レコードの定義と宣言
レコードを作成するには、RECORD 型を定義してから、その型のレコードを宣言します。目的
の値を含む表、ビューまたは PL/SQL カーソルを作成または検索し、%ROWTYPE 属性を使用し
て一致するレコードを作成することもできます。
RECORD 型は、任意の PL/SQL ブロック、サブプログラムまたはパッケージの宣言部で定義で
きます。独自の RECORD 型を定義する際は、フィールドに NOT NULL 制約を指定したり、
フィールドにデフォルト値を指定することができます。13-93 ページの「レコード定義」を参照
してください。
例 5-42 および例 5-42 に、レコード型の宣言を示します。
例 5-41 単純なレコード型の宣言および初期化
DECLARE
TYPE DeptRecTyp IS RECORD (
deptid NUMBER(4) NOT NULL := 99,
dname departments.department_name%TYPE,
loc
departments.location_id%TYPE,
region regions%ROWTYPE );
dept_rec DeptRecTyp;
BEGIN
dept_rec.dname := 'PURCHASING';
END;
/
例 5-42 レコード型の宣言および初期化
DECLARE
-- Declare a record type with 3 fields.
TYPE rec1_t IS RECORD (field1 VARCHAR2(16), field2 NUMBER, field3 DATE);
-- For any fields declared NOT NULL, we must supply a default value.
TYPE rec2_t IS RECORD (id INTEGER NOT NULL := -1,
name VARCHAR2(64) NOT NULL := '[anonymous]');
-- Declare record variables of the types declared
rec1 rec1_t;
rec2 rec2_t;
-- Declare a record variable that can hold a row from the EMPLOYEES table.
-- The fields of the record automatically match the names and
-- types of the columns.
-- Don't need a TYPE declaration in this case.
rec3 employees%ROWTYPE;
5-28
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
レコードの定義と宣言
-- Or we can mix fields that are table columns with user-defined fields.
TYPE rec4_t IS RECORD (first_name employees.first_name%TYPE,
last_name employees.last_name%TYPE,
rating NUMBER);
rec4 rec4_t;
BEGIN
-- Read and write fields using dot notation
rec1.field1 := 'Yesterday';
rec1.field2 := 65;
rec1.field3 := TRUNC(SYSDATE-1);
-- We didn't fill in the name field, so it takes the default value declared
DBMS_OUTPUT.PUT_LINE(rec2.name);
END;
/
データベースにレコードを格納する場合、そのレコードのフィールドと表の列が一致していれ
ば、INSERT 文または UPDATE 文でそのレコードを指定できます。
%TYPE を使用して、表の列の型に対応するフィールドの型を指定できます。記述したコード
は、列の型が変更された(たとえば、VARCHAR2 の長さを伸ばしたり、NUMBER の精度を高く
した)場合でも、正常に動作します。例 5-43 では、部門の情報を保持するための RECORD 型を
定義します。
例 5-43 %ROWTYPE を使用したレコードの宣言
DECLARE
-- Best: use %ROWTYPE instead of specifying each column.
-- Use <cursor>%ROWTYPE instead of <table>%ROWTYPE because
-- we only want some columns.
-- Declaring the cursor doesn't run the query, so no performance hit.
CURSOR c1 IS SELECT department_id, department_name, location_id
FROM departments;
rec1 c1%ROWTYPE;
-- Use <column>%TYPE in field declarations to avoid problems if
-- the column types change.
TYPE DeptRec2 IS RECORD (dept_id
departments.department_id%TYPE,
dept_name departments.department_name%TYPE,
dept_loc departments.location_id%TYPE);
rec2 DeptRec2;
-- Final technique, writing out each field name and specifying the type directly,
-- is clumsy and unmaintainable for working with table data.
-- Use only for all-PL/SQL code.
TYPE DeptRec3 IS RECORD (dept_id NUMBER,
dept_name VARCHAR2(14),
dept_loc VARCHAR2(13));
rec3 DeptRec3;
BEGIN
NULL;
END;
/
PL/SQL を使用すると、オブジェクト、コレクションおよびその他のレコード(ネストしたレ
コード)を含むレコードを定義できます。ただし、レコードをオブジェクト型の属性にするこ
とはできません。
PL/SQL のコレクションおよびレコードの使用
5-29
レコードの定義と宣言
プロシージャのパラメータおよびファンクションの戻り値としてのレコード
の使用
レコードは、ストアド・プロシージャを使用すると簡単に処理できます。これは、渡すパラ
メータが 1 つのみで、各フィールドに個別のパラメータを渡す必要がないためです。たとえば、
EMPLOYEES 表から表の行をフェッチしてレコードに格納し、従業員の有給休暇またはその他の
抽象的な値を計算するファンクションにその行をパラメータとして渡すと想定します。ファン
クションは、レコードのフィールドを参照することで従業員に関するすべての情報にアクセス
できます。
次の例は、ファンクションからレコードを戻す方法を示しています。複数のストアド・ファン
クションおよびストアド・プロシージャからレコード型を参照できるようにするには、パッ
ケージ仕様部でそのレコード型を宣言します。
例 5-44 ファンクションからレコードを戻す
DECLARE
TYPE EmpRecTyp IS RECORD (
emp_id
NUMBER(6),
salary
NUMBER(8,2));
CURSOR desc_salary RETURN EmpRecTyp IS
SELECT employee_id, salary FROM employees ORDER BY salary DESC;
emp_rec
EmpRecTyp;
FUNCTION nth_highest_salary (n INTEGER) RETURN EmpRecTyp IS
BEGIN
OPEN desc_salary;
FOR i IN 1..n LOOP
FETCH desc_salary INTO emp_rec;
END LOOP;
CLOSE desc_salary;
RETURN emp_rec;
END nth_highest_salary;
BEGIN
NULL;
END;
/
スカラー変数と同様に、ユーザー定義のレコードもプロシージャやファンクションの仮パラ
メータとして宣言できます。
例 5-45 プロシージャへのパラメータとしてのレコードの使用
DECLARE
TYPE EmpRecTyp IS RECORD (
emp_id
NUMBER(6),
emp_sal
NUMBER(8,2) );
PROCEDURE raise_salary (emp_info EmpRecTyp) IS
BEGIN
UPDATE employees SET salary = salary + salary * .10
WHERE employee_id = emp_info.emp_id;
END raise_salary;
BEGIN
NULL;
END;
/
ネストされたレコードを宣言し、参照できます。つまり、レコードを他のレコードの構成要素
にできます。
例 5-46 ネストされたレコードの宣言
DECLARE
TYPE TimeTyp IS RECORD ( minutes SMALLINT, hours SMALLINT );
TYPE MeetingTyp IS RECORD (
5-30
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
レコードへの値の代入
day
DATE,
time_of TimeTyp,
-- nested record
dept
departments%ROWTYPE, -- nested record representing a table row
place VARCHAR2(20),
purpose VARCHAR2(50) );
meeting MeetingTyp;
seminar MeetingTyp;
BEGIN
-- you can assign one nested record to another if they are of the same datatype
seminar.time_of := meeting.time_of;
END;
/
このような代入は、親レコードが異なるデータ型を持っている場合でもできます。
レコードへの値の代入
レコード内のすべてのフィールドにデフォルト値を設定するには、例 5-47 に示すとおり、同じ
型の初期化されていないレコードをそのフィールドに代入します。
例 5-47 レコードへのデフォルト値の代入
DECLARE
TYPE RecordTyp IS RECORD (field1 NUMBER,
field2 VARCHAR2(32) DEFAULT 'something');
rec1 RecordTyp;
rec2 RecordTyp;
BEGIN
-- At first, rec1 has the values we assign.
rec1.field1 := 100; rec1.field2 := 'something else';
-- Assigning an empty record to rec1 resets fields to their default values.
-- Field1 is NULL and field2 is 'something' due to the DEFAULT clause
rec1 := rec2;
DBMS_OUTPUT.PUT_LINE('Field1 = ' || NVL(TO_CHAR(rec1.field1),'<NULL>') || ',
field2 = ' || rec1.field2);
END;
/
ドット表記法を使用した代入文を使用して、レコードのフィールドに値を代入できます。
emp_info.last_name := 'Fields';
例 5-47 では、値は、レコードの各フィールドに個別に代入されています。代入文を使用してレ
コードに値のリストを代入することはできません。レコード用のコンストラクタのような表記
は存在しません。
レコードを同じデータ型の別のレコードに代入する場合にのみ、値をすべてのフィールドに一
度に代入できます。正確に一致するフィールドが含まれているのみでは不十分です。例 5-48 を
参照してください。
例 5-48 レコードのすべてのフィールドへの 1 文での代入
DECLARE
-- Two identical type declarations.
TYPE DeptRec1 IS RECORD ( dept_num NUMBER(2), dept_name VARCHAR2(14));
TYPE DeptRec2 IS RECORD ( dept_num NUMBER(2), dept_name VARCHAR2(14));
dept1_info DeptRec1;
dept2_info DeptRec2;
dept3_info DeptRec2;
BEGIN
-- Not allowed; different datatypes, even though fields are the same.
-dept1_info := dept2_info;
-- This assignment is OK because the records have the same type.
PL/SQL のコレクションおよびレコードの使用
5-31
レコードへの値の代入
dept2_info := dept3_info;
END;
/
フィールドの数と順序が同じで、対応するフィールドのデータ型が同じであれば、%ROWTYPE
レコードをユーザー定義のレコードに代入できます。
DECLARE
TYPE RecordTyp IS RECORD (last employees.last_name%TYPE,
id employees.employee_id%TYPE);
CURSOR c1 IS SELECT last_name, employee_id FROM employees;
-- Rec1 and rec2 have different types. But because rec2 is based on a %ROWTYPE,
-- we can assign is to rec1 as long as they have the right number of fields and
-- the fields have the right datatypes.
rec1 RecordTyp;
rec2 c1%ROWTYPE;
BEGIN
SELECT last_name, employee_id INTO rec2 FROM employees WHERE ROWNUM < 2;
rec1 := rec2;
DBMS_OUTPUT.PUT_LINE('Employee #' || rec1.id || ' = ' || rec1.last);
END;
/
SELECT 文または FETCH 文を使用して列の値をフェッチし、レコードに代入することもできま
す。選択リストの列が、レコード中のフィールドと同じ順序で並ぶようにしてください。
例 5-49 SELECT INTO を使用したレコードでの値の代入
DECLARE
TYPE RecordTyp IS RECORD (last employees.last_name%TYPE,
id employees.employee_id%TYPE);
rec1 RecordTyp;
BEGIN
SELECT last_name, employee_id INTO rec1 FROM employees WHERE ROWNUM < 2;
DBMS_OUTPUT.PUT_LINE('Employee #' || rec1.id || ' = ' || rec1.last);
END;
/
レコードの比較
レコードが NULL であるかどうかテストしたり、等しいかどうか比較することはできません。
このような比較を実行する場合は、パラメータとして 2 つのレコードを受け入れ、対応する
フィールドに対して適切なチェックまたは比較を実行する、独自のファンクションを記述しま
す。
PL/SQL レコードのデータベースへの挿入
INSERT 文の PL/SQL のみの拡張機能によって、VALUES 句で、フィールドのリストではなく
RECORD 型または %ROWTYPE 型の単一の変数を使用して、レコードをデータベース行に挿入で
きます。その結果、コードが読みやすくなり、メンテナンスが容易になります。
FORALL 文を使用して INSERT 文を発行すると、レコードのコレクション全体の値を挿入でき
ます。レコード内のフィールドの数は、INTO 句にリストされている列数と等しい必要がありま
す。また、対応するフィールドと列のデータ型には互換性が必要です。レコードと表との互換
性を確実に保持するには、変数を table_name%ROWTYPE 型として宣言することが最も便利で
す。
5-32
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
レコードへの値の代入
例 5-50 では、%ROWTYPE 修飾子を使用してレコード変数を宣言しています。この変数は、列リ
ストを指定せずに挿入できます。%ROWTYPE 宣言によって、表の列と同じ名前と型をレコード
の属性に設定できます。
例 5-50 %ROWTYPE を使用した PL/SQL レコードの挿入
DECLARE
dept_info departments%ROWTYPE;
BEGIN
-- department_id, department_name, and location_id are the table columns
-- The record picks up these names from the %ROWTYPE
dept_info.department_id := 300;
dept_info.department_name := 'Personnel';
dept_info.location_id := 1700;
-- Using the %ROWTYPE means we can leave out the column list
-- (department_id, department_name, and location_id) from the INSERT statement
INSERT INTO departments VALUES dept_info;
END;
/
PL/SQL レコード値を使用したデータベースの更新
UPDATE 文の PL/SQL のみの拡張機能によって、SET 句の右側にフィールドのリストではなく
RECORD 型または %ROWTYPE 型の単一の変数を使用して、データベース行を更新できます。
FORALL 文を使用して UPDATE 文を発行すると、レコードのコレクション全体の値を使用して
行セットを更新できます。また、UPDATE 文を使用して、RETURNING 句でレコードを指定し、
新しい値を取り出してレコードに代入することもできます。FORALL 文を使用して UPDATE 文
を発行すると、更新された行セットから値を取り出してレコードのコレクションに代入できま
す。
レコード内のフィールドの数は、SET 句にリストされている列数と等しい必要があります。ま
た、対応するフィールドと列のデータ型には互換性が必要です。
キーワード ROW を使用すると、行全体を表現できます。例 5-51 を参照してください。
例 5-51 レコードを使用した行の更新
DECLARE
dept_info departments%ROWTYPE;
BEGIN
-- department_id, department_name, and location_id are the table columns
-- The record picks up these names from the %ROWTYPE.
dept_info.department_id := 300;
dept_info.department_name := 'Personnel';
dept_info.location_id := 1700;
-- The fields of a %ROWTYPE can completely replace the table columns
-- The row will have values for the filled-in columns, and null
-- for any other columns
UPDATE departments SET ROW = dept_info WHERE department_id = 300;
END;
/
キーワード ROW を指定できる位置は、SET 句の左側のみです。SET ROW の引数には、単一の
行のみを戻す副問合せではなく、実際の PL/SQL レコードを指定する必要があります。レコー
ドには、コレクションまたはオブジェクトも含めることができます。
INSERT 文、UPDATE 文および DELETE 文には、RETURNING 句を含めることができます。この
句は、影響のある行の列値を PL/SQL レコード変数に戻します。これによって、挿入や更新の
後、または削除の前に、行を SELECT で選択する必要がなくなります。
PL/SQL のコレクションおよびレコードの使用
5-33
レコードへの値の代入
デフォルトでは、この句が使用できるのは、厳密に 1 つの行で操作する場合のみです。バルク
SQL を使用する場合、RETURNING BULK COLLECT INTO 形式を使用して、1 つ以上のコレク
ションに結果を格納できます。
例 5-52 では、従業員の給与を更新し、従業員の名前、肩書きおよび新しい給与をレコード変数
に取り出しています。
例 5-52 レコードを使用した RETURNING 句の使用
DECLARE
TYPE EmpRec IS RECORD (last_name
employees.last_name%TYPE,
salary
employees.salary%TYPE);
emp_info EmpRec;
emp_id NUMBER := 100;
BEGIN
UPDATE employees SET salary = salary * 1.1 WHERE employee_id = emp_id
RETURNING last_name, salary INTO emp_info;
DBMS_OUTPUT.PUT_LINE('Just gave a raise to ' || emp_info.last_name ||
', who now makes ' || emp_info.salary);
ROLLBACK;
END;
/
レコードの挿入 / 更新に関する制約
現在、レコードの挿入 / 更新には、次の制約があります。
■
レコード変数が使用できるのは、次の位置に限定されます。
■
UPDATE 文の SET 句の右側
■
INSERT 文の VALUES 句の中
■
RETURNING 句の INTO 副次句の中
レコード変数は、SELECT リスト、WHERE 句、GROUP BY 句または ORDER BY 句では使用
できません。
■
■
■
■
■
キーワード ROW を指定できる位置は、SET 句の左側のみです。また、ROW と副問合せは一
緒に使用できません。
UPDATE 文では、ROW が使用されている場合、許可される SET 句は 1 つのみです。
INSERT 文の VALUES 句にレコード変数が含まれている場合は、その句の中で他の変数また
は値を使用することはできません。
RETURNING 句の INTO 副次句にレコード変数が含まれている場合は、その副次句の中で他
の変数または値を使用することはできません。
次の内容はサポートされません。
■
ネストしたレコード型
■
レコードを戻すファンクション
■
EXECUTE IMMEDIATE 文を使用したレコードの挿入および更新
レコードのコレクションへのデータの問合せ
SELECT INTO 文または FETCH 文に BULK COLLECT INTO 句を使用すると、行セットを取り
出してレコードのコレクションに代入できます。
例 5-53 SELECT INTO 文での BULK COLLECT の使用
DECLARE
TYPE EmployeeSet IS TABLE OF employees%ROWTYPE;
underpaid EmployeeSet; -- Holds set of rows from EMPLOYEES table.
5-34
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
レコードへの値の代入
CURSOR c1 IS SELECT first_name, last_name FROM employees;
TYPE NameSet IS TABLE OF c1%ROWTYPE;
some_names NameSet; -- Holds set of partial rows from EMPLOYEES table.
BEGIN
-- With one query, we bring all the relevant data into the collection of records.
SELECT * BULK COLLECT INTO underpaid FROM employees
WHERE salary < 5000 ORDER BY salary DESC;
-- Now we can process the data by examining the collection, or passing it to
-- a separate procedure, instead of writing a loop to FETCH each row.
DBMS_OUTPUT.PUT_LINE(underpaid.COUNT || ' people make less than 5000.');
FOR i IN underpaid.FIRST .. underpaid.LAST
LOOP
DBMS_OUTPUT.PUT_LINE(underpaid(i).last_name || ' makes ' ||
underpaid(i).salary);
END LOOP;
-- We can also bring in just some of the table columns.
-- Here we get the first and last names of 10 arbitrary employees.
SELECT first_name, last_name BULK COLLECT INTO some_names FROM employees
WHERE ROWNUM < 11;
FOR i IN some_names.FIRST .. some_names.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Employee = ' || some_names(i).first_name || ' ' || some_
names(i).last_name);
END LOOP;
END;
/
PL/SQL のコレクションおよびレコードの使用
5-35
レコードへの値の代入
5-36
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
6
PL/SQL での SQL 操作の実行
この章では、Oracle データを操作するための SQL コマンド、ファンクションおよび演算子が
PL/SQL でどのようにサポートされているかを示します。
この章の項目は、次のとおりです。
■
PL/SQL における SQL サポートの概要
■
PL/SQL でのカーソルの管理
■
PL/SQL を使用したデータの問合せ
■
副問合せの使用
■
カーソル変数(REF CURSOR)の使用
■
カーソル式の使用
■
PL/SQL におけるトランザクション処理の概要
■
自律型トランザクションによる独立した作業単位の実行
PL/SQL での SQL 操作の実行
6-1
PL/SQL における SQL サポートの概要
PL/SQL における SQL サポートの概要
SQL を拡張した PL/SQL は、優れた性能に加えて、使いやすさも実現しています。PL/SQL
は、EXPLAIN PLAN 以外のすべての SQL データ操作文、トランザクション制御文、ファンク
ション、疑似列および演算子を完全にサポートしているため、Oracle データを柔軟かつ安全に
操作できます。PL/SQL は、現行の ANSI/ISO SQL 規格にも準拠しています。
PL/SQL では、この章で説明する静的 SQL だけでなく動的 SQL もサポートしているため、
SQL データ定義文、データ制御文、セッション制御文を動的に実行できます。第 7 章「システ
ム固有の動的 SQL を使用した SQL 操作の実行」を参照してください。
データ操作
例 6-1 に示すとおり、Oracle データを操作する場合は、INSERT 文、UPDATE 文および DELETE
文などの DML 操作を PL/SQL プログラム内に直接記述できます。特別な表記法は必要ありま
せん。SQL の COMMIT 文を PL/SQL プログラム内に直接記述することもできます。6-28 ページ
の「PL/SQL におけるトランザクション処理の概要」を参照してください。また、
『Oracle
Database SQL リファレンス』の「COMMIT」も参照してください。
例 6-1 PL/SQL を使用したデータ操作
CREATE TABLE employees_temp AS SELECT employee_id, first_name, last_name
FROM employees;
DECLARE
emp_id
employees_temp.employee_id%TYPE;
emp_first_name employees_temp.first_name%TYPE;
emp_last_name
employees_temp.last_name%TYPE;
BEGIN
INSERT INTO employees_temp VALUES(299, 'Bob', 'Henry');
UPDATE employees_temp SET first_name = 'Robert' WHERE employee_id = 299;
DELETE FROM employees_temp WHERE employee_id = 299
RETURNING first_name, last_name INTO emp_first_name, emp_last_name;
COMMIT;
DBMS_OUTPUT.PUT_LINE( emp_first_name || ' ' || emp_last_name);
END;
/
DML 文が影響を与える行の数を確認するには、例 6-2 に示すように、SQL%ROWCOUNT の値を
チェックします。
例 6-2 UPDATE 後の SQL%ROWCOUNT のチェック
CREATE TABLE employees_temp AS SELECT * FROM employees;
BEGIN
UPDATE employees_temp SET salary = salary * 1.05 WHERE salary < 5000;
DBMS_OUTPUT.PUT_LINE('Updated ' || SQL%ROWCOUNT || ' salaries.');
END;
/
例 6-3 に示すように、リテラル値またはその他のプログラミング言語のバインド変数を使用す
るすべての箇所で、PL/SQL 変数を直接置き換えることができます。
例 6-3 PL/SQL 変数の置換
CREATE TABLE employees_temp AS SELECT first_name, last_name FROM employees;
DECLARE
x VARCHAR2(20) := 'my_first_name';
y VARCHAR2(25) := 'my_last_name';
BEGIN
INSERT INTO employees_temp VALUES(x, y);
UPDATE employees_temp SET last_name = x WHERE first_name = y;
DELETE FROM employees_temp WHERE first_name = x;
6-2
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL における SQL サポートの概要
COMMIT;
END;
/
この表記法では、WHERE 句の値のかわりに変数を使用できます。表名や列名などのかわりに変
数を使用するには、7-2 ページの「PL/SQL での EXECUTE IMMEDIATE 文の使用」で説明さ
れている EXECUTE IMMEDIATE 文を使用する必要があります。
PL/SQL レコードと SQL を併用してデータを更新および挿入する手順については、5-32 ページ
の「PL/SQL レコードのデータベースへの挿入」および 5-33 ページの「PL/SQL レコード値を
使用したデータベースの更新」を参照してくたさい。
PL/SQL 変数への値の代入の詳細は、2-18 ページの「SQL 問合せ結果の PL/SQL 変数への代
入」を参照してください。
注意 : PL/SQL でデータ操作(DML)文を発行すると、場合によって
は、文の実行後に変数値が未定義になることがあります。このようになる
のは、次の場合です。
■
■
FETCH 文または SELECT 文で例外が呼び出された場合、その文の後の
定義変数値は未定義になります。
DML 文によって行が処理されない場合、DML 実行後の OUT バインド
の値は未定義になります。これは、BULK または複数行にわたる操作
には適用されません。
トランザクション制御
Oracle では、トランザクションに基づいて作業します。つまり、トランザクションを使用して
データの整合性を確保します。トランザクションとは、論理作業単位を実行する一連の SQL の
DML 文です。たとえば、2 つの UPDATE 文を使用して、ある銀行口座に入金し、別の口座から
出金します。一方の操作は成功するが他方の操作は失敗するという状態を許可しないことが重
要です。
Oracle は、データベースを変更するトランザクションの終わりに、すべての変更内容を確定ま
たは取消しします。トランザクション中にプログラムに障害が発生すると、Oracle がエラーを
検出してトランザクションをロールバックし、データベースを元の状態にリストアします。
COMMIT コマンド、ROLLBACK コマンド、SAVEPOINT コマンドおよび SET TRANSACTION コ
マンドを使用して、トランザクションを制御します。COMMIT は、カレント・トランザクショ
ン中にデータベースに加えられた変更内容を確定します。ROLLBACK は、カレント・トランザ
クションを終了させ、トランザクションの開始以降に加えられた変更をすべて取り消します。
SAVEPOINT は、トランザクション処理内の現在位置にマークを付けます。ROLLBACK と
SAVEPOINT を併用すると、トランザクションの一部のみを取り消すことができます。SET
TRANSACTION は、読取り / 書込みアクセスや分離レベルなど、トランザクションのプロパ
ティを設定します。6-28 ページの「PL/SQL におけるトランザクション処理の概要」を参照し
てください。
SQL ファンクション
例 6-4 に、SQL ファンクションをコールする問合せの一部を示します。
例 6-4 PL/SQL 内での SQL COUNT ファンクションのコール
DECLARE
job_count NUMBER;
emp_count NUMBER;
BEGIN
SELECT COUNT(DISTINCT job_id) INTO job_count FROM employees;
SELECT COUNT(*) INTO emp_count FROM employees;
END;
/
PL/SQL での SQL 操作の実行
6-3
PL/SQL における SQL サポートの概要
SQL 疑似列
PL/SQL では、SQL 擬似列 CURRVAL、LEVEL、NEXTVAL、ROWID および ROWNUM が認識され
ます。ただし、疑似列の使用には、代入または条件テストで一部の疑似列を使用できないなど
の制限があります。制限など、SQL 疑似列の使用の詳細は、
『Oracle Database SQL リファレン
ス』を参照してください。
CURRVAL と NEXTVAL
順序とは、連続的な数値を生成するスキーマ・オブジェクトのことです。順序を作成する場合
は、その初期値と増分を指定できます。CURRVAL は指定された順序の中での現在の値を戻しま
す。セッションの中で CURRVAL を参照する前に、NEXTVAL を使用して数値を生成する必要が
あります。NEXTVAL を参照すると、現在の順序番号が CURRVAL に格納されます。NEXTVAL は
順序に増分を加えて、次の値を戻します。順序の現在の値または次の値を得るには、ドット表
記法を使用します。
sequence_name.CURRVAL
sequence_name.NEXTVAL
順序の NEXTVAL 値を参照するたびに、トランザクションをコミットするかロールバックする
かにかかわらず、順序はすぐに増分され、その変化は永続的になります。
順序を作成すると、トランザクション処理の目的のために独自の順序番号を生成させることが
できます。CURRVAL および NEXTVAL は、SELECT リスト、VALUES 句および SET 句の中でし
か使用できません。例 6-5 に、新規のシーケンス番号を生成して、2 つ以上の文で同じ番号を参
照する方法を示します。
例 6-5 CURRVAL と NEXTVAL の使用
CREATE
FROM
CREATE
FROM
TABLE employees_temp AS SELECT employee_id, first_name, last_name
employees;
TABLE employees_temp2 AS SELECT employee_id, first_name, last_name
employees;
DECLARE
seq_value NUMBER;
BEGIN
-- Display initial value of NEXTVAL
-- This is invalid: seq_value := employees_seq.NEXTVAL;
SELECT employees_seq.NEXTVAL INTO seq_value FROM dual;
DBMS_OUTPUT.PUT_LINE ('Initial sequence value: ' || TO_CHAR(seq_value));
-- The NEXTVAL value is the same no matter what table you select from
-- You usually use NEXTVAL to create unique numbers when inserting data.
INSERT INTO employees_temp VALUES (employees_seq.NEXTVAL, 'Lynette', 'Smith');
-- If you need to store the same value somewhere else, you use CURRVAL
INSERT INTO employees_temp2 VALUES (employees_seq.CURRVAL, 'Morgan', 'Smith');
-- Because NEXTVAL values might be referenced by different users and
-- applications, and some NEXTVAL values might not be stored in the
-- database, there might be gaps in the sequence
-- The following uses the stored value of the CURRVAL in seq_value to specify
-- the record to delete because CURRVAL (or NEXTVAL) cannot used in a WHERE clause
-- This is invalid: WHERE employee_id = employees_seq.CURRVAL;
SELECT employees_seq.CURRVAL INTO seq_value FROM dual;
DELETE FROM employees_temp2 WHERE employee_id = seq_value;
-- The following udpates the employee_id with NEXTVAL for the specified record
UPDATE employees_temp SET employee_id = employees_seq.NEXTVAL
WHERE first_name = 'Lynette' AND last_name = 'Smith';
-- Display end value of CURRVAL
SELECT employees_seq.CURRVAL INTO seq_value FROM dual;
DBMS_OUTPUT.PUT_LINE ('Ending sequence value: ' || TO_CHAR(seq_value));
END;
/
6-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL における SQL サポートの概要
LEVEL
SELECT CONNECT BY 文で LEVEL を使用すると、データベース表の行をツリー構造に整理でき
ます。順序番号を使用して各行に一意の識別子を指定し、他の行からこれらの識別子を参照し
て親子関係を構築できます。LEVEL はツリー構造の中のノードのレベル番号を戻します。ルー
トはレベル 1、ルートの子はレベル 2、孫はレベル 3、のように続きます。
ツリーのルートを識別する条件は、START WITH 句で指定します。PRIOR 演算子を使用して、
問合せがツリーの中を移動するときの向き(ルートから下へ、または枝から上へ)を指定しま
す。
ROWID
ROWID はデータベース表の行の ROWID(バイナリ・アドレス)を戻します。UROWID 型の変
数を使用すると、ROWID を読取り可能な書式で格納できます。
物理 ROWID を選択またはフェッチして UROWID 変数に入れる場合は、バイナリ値を文字列に
変換するファンクション ROWIDTOCHAR を使用します。UPDATE 文または DELETE 文の WHERE
句の中で UROWID 変数と ROWID 疑似列を比較すると、カーソルからフェッチされた最新の行を
識別できます。例は、6-34 ページの「コミットにまたがるフェッチ」を参照してください。
ROWNUM
ROWNUM は、行が表から取り出された順番を示す番号を戻します。最初に取り出された行の
ROWNUM は 1、2 番目に取り出された行の ROWNUM は 2、のように続きます。SELECT 文に
ORDER BY 句が含まれている場合、取り出された行がソートされる前に、行に ROWNUM が割り
当てられます。ソートされた最初の n 行を取得するには、副問合せを使用します。ROWNUM の
値が増えるのは、行が取り出されたときのみです。つまり、WHERE 句で ROWNUM を使用する場
合は、次のようにする必要があります。
... WHERE ROWNUM < 定数
... WHERE ROWNUM <= 定数
例 6-6 に示すとおり、UPDATE 文で ROWNUM を使用して、表の中の個々の行に一意の値を代入
できます。また、SELECT 文の WHERE 句で ROWNUM を使用して、取り出される行の数を制
限できます
例 6-6 ROWNUM の使用
CREATE TABLE employees_temp AS SELECT * FROM employees;
DECLARE
CURSOR c1 IS SELECT employee_id, salary FROM employees_temp
WHERE salary > 2000 AND ROWNUM <= 10; -- 10 arbitrary rows
CURSOR c2 IS SELECT * FROM
(SELECT employee_id, salary FROM employees_temp
WHERE salary > 2000 ORDER BY salary DESC)
WHERE ROWNUM < 5; -- first 5 rows, in sorted order
BEGIN
-- Each row gets assigned a different number
UPDATE employees_temp SET employee_id = ROWNUM;
END;
/
SQL 演算子
PL/SQL では、SQL 文の中で、SQL の比較演算子、集合演算子および行演算子を使用できま
す。この項では、これらの演算子について簡単に説明します。詳細は、
『Oracle Database SQL
リファレンス』を参照してください。
PL/SQL での SQL 操作の実行
6-5
PL/SQL でのカーソルの管理
比較演算子
比較演算子は、通常、DML 文の WHERE 句で述語を形成するために使用します。述語は、2 つ
の式を比較して、TRUE、FALSE、NULL のいずれかに評価します。次の比較演算子は、述語の
形成に使用できます。述語は論理演算子 AND、OR および NOT を使用して結合できます。
演算子
説明
ALL
値をリストのすべての値、または副問合せが戻したすべての値と 1 つずつ比較して、
結果がすべて TRUE であれば TRUE に評価します。
ANY、SOME
値をリストのすべての値、または副問合せが戻したすべての値と 1 つずつ比較して、
結果のいずれかが TRUE であれば TRUE に評価します。
BETWEEN
値が指定範囲内かどうかをテストします。
EXISTS
副問合せが行を 1 つでも戻すと TRUE を戻します。
IN
セット・メンバーシップをテストします。
IS NULL
NULL かどうかをテストします。
LIKE
文字列が、指定したパターンと一致するかどうかをテストします。指定パターンには
ワイルドカードを使用できます。
集合演算子
集合演算子は 2 つの問合せの結果を組み合せて 1 つの結果を戻します。INTERSECT によって、
2 つの問合せの両方で選択されたすべての行を、重複するものを除いて戻します。MINUS は、1
番目の問合せによって選択されたが、2 番目の問合せでは選択されなかったすべての行を、重
複するものを除いて戻します。UNION によって、2 つの問合せのいずれかで選択されたすべて
の行を、重複するものを除いて戻します。UNION ALL は、重複した行も含めて、どちらかの問
合せによって選択されたすべての行を戻します。
行演算子
行演算子は特定の行を戻すか、または参照します。ALL によって、問合せの結果や集合式に含
まれる重複した行をそのまま残します。DISTINCT は、問合せの結果や集合式に含まれる重複
した行を削除します。PRIOR は、ツリー構造の問合せによって戻された現在行の親の行を参照
します。
PL/SQL でのカーソルの管理
PL/SQL では、暗黙カーソルおよび明示カーソルを使用します。PL/SQL では、1 行のみを戻
す問合せを含むすべての SQL データ操作文に関して暗黙的にカーソルが宣言されます。問合せ
の処理を完全に制御する必要がある場合、PL/SQL ブロック、サブプログラムまたはパッケー
ジの宣言部の中でカーソルを明示的に宣言できます。複数の行を戻す問合せの場合は、明示
カーソルを宣言する必要があります。
暗黙カーソル
暗黙カーソルは PL/SQL で自動的に管理されるため、これらのカーソルを処理するコードを記
述する必要はありません。ただし、カーソル属性を使用して暗黙カーソルの実行情報を追跡で
きます。
暗黙カーソルの属性
暗黙カーソルの属性は、INSERT 文、UPDATE 文、DELETE 文、SELECT INTO 文、COMMIT ま
たは ROLLBACK 文など、DML および DDL 文の実行に関する情報を戻します。カーソル属性は
%FOUND、%ISOPEN、%NOTFOUND および %ROWCOUNT です。カーソル属性の値は、常に直前に
実行された SQL 文を参照しています。Oracle が SQL カーソルをオープンするまでは、暗黙
カーソルの属性の結果は NULL になります。
6-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL でのカーソルの管理
SQL カーソルには、FORALL 文で使用するために設計された %BULK_ROWCOUNT という別の属
性があります。詳細は、11-12 ページの「%BULK_ROWCOUNT 属性を持つ FORALL による影
響を受ける行カウント」を参照してください。
%FOUND カーソル属性 : DML 文で行が変更されたかどうか
SQL の DML 文が実行されるまでは、%FOUND の結果は NULL になります。その後、INSERT
文、UPDATE 文または DELETE 文が 1 行または複数の行に作用するか、または SELECT INTO
文が 1 行または複数の行を戻すと、%FOUND の結果は TRUE になります。それ以外の場合、
%FOUND の結果は FALSE になります。例 6-7 では、%FOUND を使用して、削除に成功した場合
に行を挿入するようにしています。
例 6-7 SQL%FOUND の使用
CREATE TABLE dept_temp AS SELECT * FROM departments;
DECLARE
dept_no NUMBER(4) := 270;
BEGIN
DELETE FROM dept_temp WHERE department_id = dept_no;
IF SQL%FOUND THEN -- delete succeeded
INSERT INTO dept_temp VALUES (270, 'Personnel', 200, 1700);
END IF;
END;
/
%ISOPEN カーソル属性 : 暗黙カーソルの場合は常に FALSE
Oracle は、SQL カーソルに対応付けられた SQL 文の実行を終了すると、この SQL カーソルを
自動的にクローズします。その結果、%ISOPEN の結果は常に FALSE になります。
%NOTFOUND 属性 : DML 文で行の変更が失敗したかどうか
%NOTFOUND は、論理的に %FOUND の逆です。INSERT 文、UPDATE 文または DELETE 文がどの
行にも作用しないか、または SELECT INTO 文がどの行も戻さない場合、%NOTFOUND の結果は
TRUE になります。それ以外の場合、%NOTFOUND の結果は FALSE になります。
%ROWCOUNT 属性 : これまでに影響を受けた行数
%ROWCOUNT の結果は、INSERT 文、UPDATE 文または DELETE 文の影響を受けた行、または
SELECT INTO 文に戻された行の数になります。INSERT 文、UPDATE 文または DELETE 文がど
の行にも作用しないか、または SELECT INTO 文がどの行も戻さないと、%ROWCOUNT の結果は
0 になります。例 6-8 では、%ROWCOUNT は削除された行数を戻します。
例 6-8 SQL%ROWCOUNT の使用
CREATE TABLE employees_temp AS SELECT * FROM employees;
DECLARE
mgr_no NUMBER(6) := 122;
BEGIN
DELETE FROM employees_temp WHERE manager_id = mgr_no;
DBMS_OUTPUT.PUT_LINE('Number of employees deleted: ' || TO_CHAR(SQL%ROWCOUNT));
END;
/
SELECT INTO 文が複数の行を戻した場合、PL/SQL によって事前定義の例外 TOO_MANY_ROWS
が呼び出され、%ROWCOUNT は、問合せを満たす行の実数ではなく、1 になります。
SQL%ROWCOUNT 属性の値は、PL/SQL から直前に実行された SQL 文を参照しています。属性
の値を保存して後で使用する場合は、値をローカル変数に直接代入してください。
SQL%ROWCOUNT 属性はトランザクションの状態には無関係です。セーブポイントへのロール
バックが実行されても、SQL%ROWCOUNT の値が、セーブポイントに達する前の古い値に戻るこ
とはありません。また、自律型トランザクションが終了しても、SQL%ROWCOUNT が親トランザ
クション内の元の値に戻ることはありません。
PL/SQL での SQL 操作の実行
6-7
PL/SQL でのカーソルの管理
暗黙カーソルの属性を使用する場合のガイドライン
次に、暗黙カーソルの属性を使用する場合の考慮事項を示します。
■
■
カーソル属性の値は、常に直前に実行された SQL 文を参照します(その文の場所とは無関
係です)
。文が別の有効範囲に存在する場合もあります(サブブロックなど)。属性の値を
保存して後で使用する場合は、値をローカル変数に直接代入してください。プロシー
ジャ・コールなどの他の操作を実行すると、変数値がテスト前に変更される可能性があり
ます。
%NOTFOUND 属性は、SELECT INTO 文と組み合せて使用しても効果がありません。
–
SELECT INTO 文が行を戻せなかった場合は、PL/SQL によって事前定義済の例外
NO_DATA_FOUND がただちに呼び出され、%NOTFOUND をチェックする前に制御フ
ローが中断されます。
–
SQL 集計関数をコールする SELECT INTO 文は、常に値または NULL を戻します。こ
のような文の後では、%NOTFOUND 属性の値は常に FALSE になるため、属性をチェッ
クする必要はありません。
明示カーソル
問合せの処理を完全に制御する必要がある場合、PL/SQL ブロック、サブプログラムまたは
パッケージの宣言部の中でカーソルを明示的に宣言できます。
カーソルの制御には、OPEN、FETCH および CLOSE の 3 つのコマンドを使用します。まず、結
果セットを識別する OPEN 文でカーソルを初期化します。次に、FETCH を繰り返し実行して、
すべての行を取り出します。または BULK COLLECT 句を使用して、すべての行を一度にフェッ
チします。最後の行の処理が終わってから、CLOSE 文でカーソルを解放します。
この方法では、暗黙カーソルの FOR ループなどの他の方法より多くのコードが必要になりま
す。この方法のメリットは柔軟性があるということです。この方法では次の操作を実行できま
す。
■
■
複数のカーソルを宣言してオープンすることで、複数の問合せをパラレルで処理できます。
1 回のループで複数の行を処理したり、行をスキップしたり、処理を複数のループに分割す
ることができます。
カーソルの宣言
他の文でカーソルを参照するときは、事前に宣言する必要があります。カーソルに名前を付け、
特定の問合せと関連付けます。オプションで、カーソルの戻り型(table_name%ROWTYPE な
ど)を宣言することもできます。また、オプションで、ローカル変数を参照するかわりに
WHERE 句で使用するパラメータを指定することもできます。これらのパラメータには、デフォ
ルト値を設定できます。例 6-9 に、カーソルの宣言方法を示します。
例 6-9 カーソルの宣言
DECLARE
my_emp_id
NUMBER(6);
-- variable for employee_id
my_job_id
VARCHAR2(10); -- variable for job_id
my_sal
NUMBER(8,2);
-- variable for salary
CURSOR c1 IS SELECT employee_id, job_id, salary FROM employees
WHERE salary > 2000;
my_dept departments%ROWTYPE; -- variable for departments row
CURSOR c2 RETURN departments%ROWTYPE IS
SELECT * FROM departments WHERE department_id = 110;
カーソルは PL/SQL 変数ではありません。カーソルに値を代入したり、カーソルを式の中で使
用することはできません。カーソルと変数は、同じ有効範囲規則に従います。データベース表
に基づいてカーソルに名前を付けることができますが、お薦めしません。
6-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL でのカーソルの管理
カーソルはパラメータを取ることができます。カーソルのパラメータは、カーソルに結び付け
られた問合せの中で、定数が使用可能な位置であればどこででも使用できます。カーソルの仮
パラメータは IN パラメータにする必要があります。このパラメータは問合せに値を提供しま
すが、問合せから値を戻しません。カーソル・パラメータに NOT NULL 制約を課すことはでき
ません。
次の例に示すように、カーソルのパラメータをデフォルト値に初期化できます。初期化すると、
必要に応じてデフォルト値を受け入れたり上書きすることで、カーソルの実パラメータに様々
な数値を渡すことができます。また、カーソルへの既存の参照を変更しなくても、新しい仮パ
ラメータを追加できます。
DECLARE
CURSOR c1 (low NUMBER DEFAULT 0, high NUMBER DEFAULT 99) IS
SELECT * FROM departments WHERE department_id > low
AND department_id < high;
カーソルのパラメータは、カーソル宣言で指定されている問合せの範囲からしか参照できませ
ん。パラメータ値は、カーソルがオープンされているときに、カーソルに関連付けられた問合
せから使用できます。
カーソルのオープン
カーソルをオープンすると、問合せが実行され、結果セットが識別されます(結果セットは、
問合せの検索条件に一致するすべての行で構成されています)
。FOR UPDATE 句を使用して宣言
されたカーソルの場合、OPEN 文はこれらの行のロックもします。OPEN 文の例を次に示しま
す。
DECLARE
CURSOR c1 IS SELECT employee_id, last_name, job_id, salary FROM employees
WHERE salary > 2000;
BEGIN
OPEN C1;
結果セット内の行は、OPEN 文の実行時ではなく、FETCH によって取り出されます。
カーソルを使用したフェッチ
BULK COLLECT 句(6-9 ページの「カーソルを使用したフェッチ」で説明)を使用していない
場合は、FETCH 文によって結果セットの行が一度に 1 行ずつ取り出されます。各 FETCH 文は
現在の行を取り出してから、カーソルを結果セットの次の行に進めます。各列を個別の変数に
格納したり、行全体を適切なフィールドを持つレコード(通常は %ROWTYPE を使用して宣言す
る)に格納することができます。
カーソルと関連付けられた問合せが戻す列の値に対しては、INTO リストの中に、対応する、型
互換の変数が存在している必要があります。例 6-10 に示すとおり、通常、FETCH 文は LOOP 文
および EXIT WHEN .. NOTFOUND 文とともに使用します。問合せ内の組込み正規表現ファン
クションの使用に注意してください。
例 6-10 カーソルを使用したフェッチ
DECLARE
v_jobid
employees.job_id%TYPE;
-- variable for job_id
v_lastname employees.last_name%TYPE; -- variable for last_name
CURSOR c1 IS SELECT last_name, job_id FROM employees
WHERE REGEXP_LIKE (job_id, 'S[HT]_CLERK');
v_employees employees%ROWTYPE;
-- record variable for row
CURSOR c2 is SELECT * FROM employees
WHERE REGEXP_LIKE (job_id, '[ACADFIMKSA]_M[ANGR]');
BEGIN
OPEN c1; -- open the cursor before fetching
LOOP
FETCH c1 INTO v_lastname, v_jobid; -- fetches 2 columns into variables
EXIT WHEN c1%NOTFOUND;
PL/SQL での SQL 操作の実行
6-9
PL/SQL でのカーソルの管理
DBMS_OUTPUT.PUT_LINE( RPAD(v_lastname, 25, ' ') || v_jobid );
END LOOP;
CLOSE c1;
DBMS_OUTPUT.PUT_LINE( '-------------------------------------' );
OPEN c2;
LOOP
FETCH c2 INTO v_employees; -- fetches entire row into the v_employees record
EXIT WHEN c2%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( RPAD(v_employees.last_name, 25, ' ') ||
v_employees.job_id );
END LOOP;
CLOSE c2;
END;
/
問合せは、有効範囲内にある PL/SQL 変数を参照できます。問合せの中の変数は、カーソルが
オープンされたときにのみ評価されます。例 6-11 では、factor は、FETCH 文が実行される
たびに増加しますが、取り出された給与はそれぞれ 2 倍されます。
例 6-11 有効範囲内の PL/SQL 変数の参照
DECLARE
my_sal employees.salary%TYPE;
my_job employees.job_id%TYPE;
factor INTEGER := 2;
CURSOR c1 IS
SELECT factor*salary FROM employees WHERE job_id = my_job;
BEGIN
OPEN c1; -- factor initially equals 2
LOOP
FETCH c1 INTO my_sal;
EXIT WHEN c1%NOTFOUND;
factor := factor + 1; -- does not affect FETCH
END LOOP;
CLOSe c1;
END;
/
結果セットや問合せの中の変数の値を変更する場合は、カーソルをクローズし、入力変数を新
しい値に設定して、再オープンする必要があります。ただし、同じカーソルを使用して、別々
の FETCH 文で、異なる INTO リストを使用できます。例 6-12 に示すとおり、個々の FETCH
文で別の行を取り出し、ターゲット変数に値を代入します
例 6-12 同じカーソルの異なる変数へのフェッチ
DECLARE
CURSOR c1 IS SELECT last_name FROM employees ORDER BY last_name;
name1 employees.last_name%TYPE;
name2 employees.last_name%TYPE;
name3 employees.last_name%TYPE;
BEGIN
OPEN c1;
FETCH c1 INTO name1; -- this fetches first row
FETCH c1 INTO name2; -- this fetches second row
FETCH c1 INTO name3; -- this fetches third row
CLOSE c1;
END;
/
FETCH 文を実行した時点で結果セットに行が残っていなかった場合、ターゲット変数の値は未
定義になります。結果として、FETCH 文は行を戻すことに失敗します。この状況が発生して
も、例外は呼び出されません。失敗を検出するには、カーソル属性 %FOUND または
%NOTFOUND を使用します。詳細は、6-27 ページの「カーソル式の使用」を参照してください。
6-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL でのカーソルの管理
カーソルを使用したバルク・データのフェッチ
BULK COLLECT 句を使用すると、結果セットのすべての行を一度にフェッチできます。11-15
ページの「BULK COLLECT 句を使用した、問合せ結果のコレクションへの取出し」を参照し
てください。例 6-13 では、1 つのカーソルから 2 つのコレクションにバルク・フェッチを実行
します。
例 6-13 カーソルを使用したバルク・データのフェッチ
DECLARE
TYPE IdsTab IS TABLE OF employees.employee_id%TYPE;
TYPE NameTab IS TABLE OF employees.last_name%TYPE;
ids IdsTab;
names NameTab;
CURSOR c1 IS
SELECT employee_id, last_name FROM employees WHERE job_id = 'ST_CLERK';
BEGIN
OPEN c1;
FETCH c1 BULK COLLECT INTO ids, names;
CLOsE c1;
-- Here is where you process the elements in the collections
FOR i IN ids.FIRST .. ids.LAST
LOOP
IF ids(i) > 140 THEN
DBMS_OUTPUT.PUT_LINE( ids(i) );
END IF;
END LOOP;
FOR i IN names.FIRST .. names.LAST
LOOP
IF names(i) LIKE '%Ma%' THEN
DBMS_OUTPUT.PUT_LINE( names(i) );
END IF;
END LOOP;
END;
/
カーソルのクローズ
CLOSE 文によってカーソルは使用禁止になり、結果セットは未定義になります。クローズされ
たカーソルは、再オープンできます。これによって、WHERE 句で参照されたカーソル・パラ
メータおよび変数の最新の値を使用して、問合せが再度実行されます。クローズされたカーソ
ルに対してこれ以外の操作を実行すると、事前定義の例外 INVALID_CURSOR が呼び出されま
す。
明示カーソルの属性
どの明示カーソルおよびカーソル変数にも %FOUND、%ISOPEN、%NOTFOUND および
%ROWCOUNT の 4 つの属性があります。これらの属性をカーソルまたはカーソル変数名に付加す
ると、SQL 文の実行について役立つ情報が戻されます。カーソル属性は、プロシージャ文では
使用できますが、SQL 文では使用できません。
明示カーソルの属性は、複数行の問合せの実行に関する情報を戻します。明示カーソルまたは
カーソル変数をオープンすると、対応する問合せを満たす行が識別され、結果セットが形成さ
れます。行は、結果セットから取り出されます。
%FOUND カーソル属性 : 1 行がフェッチされたかどうか
カーソルまたはカーソル変数のオープン後、最初のフェッチが実行されるまでは、%FOUND は
NULL を戻します。フェッチが実行された後、直前のフェッチが行を戻した場合は TRUE を、直
前のフェッチが行を戻さなかった場合は FALSE を戻します。例 6-14 では、%FOUND を使用し
てアクションを選択します。
PL/SQL での SQL 操作の実行
6-11
PL/SQL でのカーソルの管理
例 6-14 %FOUND の使用
DECLARE
CURSOR c1 IS SELECT last_name, salary FROM employees WHERE ROWNUM < 11;
my_ename employees.last_name%TYPE;
my_salary employees.salary%TYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO my_ename, my_salary;
IF c1%FOUND THEN -- fetch succeeded
DBMS_OUTPUT.PUT_LINE('Name = ' || my_ename || ', salary = ' || my_salary);
ELSE -- fetch failed, so exit loop
EXIT;
END IF;
END LOOP;
END;
/
カーソルまたはカーソル変数をオープンしていない場合、%FOUND でカーソルまたはカーソル
変数を参照すると、事前定義の例外 INVALID_CURSOR が呼び出されます。
%ISOPEN カーソル属性 : カーソルがオープンしているかどうか
%ISOPEN は、カーソルまたはカーソル変数をオープンしている場合は TRUE を、他の場合は
FALSE を戻します。例 6-15 では、%ISOPEN を使用してアクションを選択します。
例 6-15 %ISOPEN の使用
DECLARE
CURSOR c1 IS SELECT last_name, salary FROM employees WHERE ROWNUM < 11;
the_name employees.last_name%TYPE;
the_salary employees.salary%TYPE;
BEGIN
IF c1%ISOPEN = FALSE THEN -- cursor was not already open
OPEN c1;
END IF;
FETCH c1 INTO the_name, the_salary;
CLOSE c1;
END;
/
%NOTFOUND カーソル属性 : フェッチが失敗したかどうか
%NOTFOUND は、論理的に %FOUND の逆です。%NOTFOUND は、直前の取出しが行を戻した場合
は FALSE に、直前の取出しが行を戻さなかった場合は TRUE になります。例 6-16 では、
%NOTFOUND を使用して、FETCH が行を戻さなくなった場合に、ループが終了するようにして
います。
例 6-16 %NOTFOUND の使用
DECLARE
CURSOR c1 IS SELECT last_name, salary FROM employees WHERE ROWNUM < 11;
my_ename employees.last_name%TYPE;
my_salary employees.salary%TYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO my_ename, my_salary;
IF c1%NOTFOUND THEN -- fetch failed, so exit loop
-- Another form of this test is "EXIT WHEN c1%NOTFOUND OR c1%NOTFOUND IS NULL;"
EXIT;
ELSE -- fetch succeeded
DBMS_OUTPUT.PUT_LINE('Name = ' || my_ename || ', salary = ' || my_salary);
END IF;
6-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL でのカーソルの管理
END LOOP;
END;
/
最初のフェッチの前は、%NOTFOUND は NULL を戻します。FETCH が正常に実行されない場合、
EXIT WHEN 文は WHEN 条件が TRUE の場合にのみ実行されるため、ループは終了しません。安
全のために、次の EXIT 文をかわりに使用できます。
EXIT WHEN c1%NOTFOUND OR c1%NOTFOUND IS NULL;
カーソルまたはカーソル変数をオープンしていない場合、%NOTFOUND でカーソルまたはカーソ
ル変数を参照すると、例外 INVALID_CURSOR が呼び出されます。
%ROWCOUNT カーソル属性 : これまでにフェッチされた行数
カーソルまたはカーソル変数をオープンしている場合、%ROWCOUNT は 0(ゼロ)になります。
最初のフェッチの前は、%ROWCOUNT の評価結果は 0 です。その後は、これまでにフェッチし
た行の数になります。この値は、直前のフェッチが行を戻した場合に増分されます。例 6-17 で
は、%ROWCOUNT を使用して、フェッチされた行が 10 行を超えたかどうかをテストしています。
例 6-17 %ROWCOUNT の使用
DECLARE
CURSOR c1 IS SELECT last_name FROM employees WHERE ROWNUM < 11;
name employees.last_name%TYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO name;
EXIT WHEN c1%NOTFOUND OR c1%NOTFOUND IS NULL;
DBMS_OUTPUT.PUT_LINE(c1%ROWCOUNT || '. ' || name);
IF c1%ROWCOUNT = 5 THEN
DBMS_OUTPUT.PUT_LINE('--- Fetched 5th record ---');
END IF;
END LOOP;
CLOSE c1;
END;
/
カーソルまたはカーソル変数をオープンしていない場合、%ROWCOUNT でカーソルまたはカーソ
ル変数を参照すると、INVALID_CURSOR が呼び出されます。
表 6-1 に、OPEN 文、FETCH 文または CLOSE 文を実行する前後での、各カーソル属性が戻す値
を示します。
表 6-1 カーソル属性値
OPEN
最初の FETCH
以降の FETCH
最後の FETCH
CLOSE
%FOUND
%ISOPEN
%NOTFOUND
%ROWCOUNT
前
例外
FALSE
例外
例外
後
NULL
TRUE
NULL
0
前
NULL
TRUE
NULL
0
後
TRUE
TRUE
FALSE
1
前
TRUE
TRUE
FALSE
1
後
TRUE
TRUE
FALSE
データに依存
前
TRUE
TRUE
FALSE
データに依存
後
FALSE
TRUE
TRUE
データに依存
前
FALSE
TRUE
TRUE
データに依存
後
例外
FALSE
例外
例外
PL/SQL での SQL 操作の実行
6-13
PL/SQL を使用したデータの問合せ
次に示す内容は、表 6-1 の情報に適用されます。
■
■
カーソルをオープンする前またはカーソルをクローズした後で、%FOUND、%NOTFOUND ま
たは %ROWCOUNT を参照すると、INVALID_CURSOR が呼び出されます。
最初の FETCH の後、結果セットが空の場合、%FOUND は FALSE、%NOTFOUND は TRUE、
%ROWCOUNT は 0 になります。
PL/SQL を使用したデータの問合せ
PL/SQL を使用すると、問合せ(SQL の SELECT 文)を実行し、結果セットの個別のフィール
ドまたはすべての行にアクセスできます。従来のデータベース・プログラミングでは、カーソ
ルと呼ばれる内部データ構造を使用して問合せの結果を処理していました。PL/SQL では、ほ
とんどの場合にカーソルを管理できるため、問合せの結果を処理するコードが単純で小型にな
ります。この項では、PL/SQL によってすべてが管理される単純な問合せと、自分でカーソル
を使用する複雑な問合せを処理する方法について説明します。
1 行のみの選択 : SELECT INTO 文
問合せが 1 行のみを戻すと予測している場合、通常の SQL の SELECT 文に、結果を保持する
PL/SQL 変数を指定する INTO 句を追加して記述できます。
問合せが複数の行を戻す可能性があり、そのうち最初の値以外は必要ない場合、ROWNUM の値
と比較することで、結果セットを 1 行に制限できます。問合せが行を戻さない可能性がある場
合、例外ハンドラを使用して、データが見つからない場合のアクションを指定します。
使用するデータに条件が存在するかどうかのチェックのみを行う場合、COUNT(*) 演算子を使
用して問合せを記述できます。この演算子は常に数値を戻すため、NO_DATA_FOUND 例外は発
生しません。
複数行の選択 : BULK COLLECT 句
1 回に 1 行ずつ結果セットをループするのではなく、ローカルの PL/SQL 変数に大量のデータ
を代入する必要がある場合、BULK COLLECT 句を使用できます。特定の列のみを問い合せる場
合、各列に対するすべての結果を個別のコレクション変数に格納できます。表のすべての列を
問い合せる場合は、レコードのコレクションに結果セット全体を格納できます。これによって、
結果のループ処理および別の列への参照が簡単になります。6-11 ページの例 6-13「カーソルを
使用したバルク・データのフェッチ」を参照してください。
この方法では非常に高速に処理されますが、メモリーも集中的に使用されます。この方法を頻
繁に使用する場合は、より多くの処理を SQL で実行すると、コードのパフォーマンスを向上で
きます。
■
■
■
6-14
結果セットを 1 回のみループする場合、FOR ループを使用します(これ以降の項を参照)。
この方法を使用すると、結果セットのコピーを格納する際のメモリーのオーバーヘッドを
回避できます。
結果セットをループして特定の値をスキャンしたり、結果をフィルタリングしてより小さ
い結果セットにする場合、かわりに元の問合せでスキャンまたはフィルタリングを行いま
す。簡単な場合であれば WHERE 句を追加できます。また、複数の結果セットを比較する場
合は、INTERSECT や MINUS などの集合演算子を使用できます。
結果セットをループして、各結果行に対して別の問合せまたは DML 文を実行する場合は、
より効率的な方法があります。問合せの場合、元の問合せに副問合せまたは EXISTS 句や
NOT EXISTS 句を含めることを検討してください。DML 文の場合、通常のループ内部で
これらの文をコーディングするより高速な FORALL 文を使用することを検討してください。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL を使用したデータの問合せ
複数行のループ : カーソル FOR ループ
最も一般的な問合せは、SELECT 文を発行し、結果セットの行に対してただちにループを 1 回
実行することす。PL/SQL では、単純な FOR ループを使用してこのような種類の問合せを実行
できます。
FOR ループのイテレータ変数は、事前に宣言する必要はありません。イテレータ変数は、
フィールド名が問合せの列名に一致する %ROWTYPE レコードです。この変数は、ループ中にの
み存在します。明示的な列名ではなく式を使用する場合、列の別名を使用すると、ループ内の
対応する値を参照できます。
複雑な問合せの処理の実行 : 明示カーソル
問合せの処理を完全に制御するには、OPEN 文、FETCH 文および CLOSE 文と明示カーソルを組
み合せて使用します。
ある場所で問合せを指定し、他のサブプログラム内などの別の場所に行を取り出す必要がある
場合があります。また、状況に応じて、ORDER BY 句や GROUP BY 句など、別の問合せパラ
メータを選択する必要がある場合もあります。さらに、一部の行に対して他の行とは異なる処
理を行うために、より複雑なループが必要な場合もあります。
明示カーソルは非常に柔軟性があるため、必要に応じて様々な表記法から選択できます。次の
項では、明示カーソルのすべての問合せ処理機能について説明します。
PL/SQL を使用したデータの問合せ : 暗黙カーソルの FOR ループ
PL/SQL を使用すると、問合せの発行、結果の各行の %ROWTYPE レコードへの取出し、および
ループ内の各行の処理を簡単に実行できます。
■
■
■
FOR ループ内に、問合せのテキストを直接含めます。
PL/SQL によって、結果セットの列に対応するフィールドを持つレコード変数が作成され
ます。
ループ内でこのレコード変数のフィールドを参照します。テストや計算、出力の表示また
は他の場所への結果の格納を実行できます。
SQL*Plus での実行例を次に示します。この例では、120 よりも大きなマネージャ ID を持つ従
業員の名前およびジョブ ID を取得する問合せを実行します。
BEGIN
FOR item IN
( SELECT last_name, job_id FROM employees WHERE job_id LIKE '%CLERK%'
AND manager_id > 120 )
LOOP
DBMS_OUTPUT.PUT_LINE('Name = ' || item.last_name || ', Job = ' ||
item.job_id);
END LOOP;
END;
/
FOR ループを反復する前に、PL/SQL は暗黙的に宣言したレコードに取り出した値を格納しま
す。ループの中の一連の文は、問合せを満たす 1 つの行について 1 回実行されます。ループを
終了させると、カーソルは自動的にクローズされます。EXIT 文または GOTO 文を使用して、す
べての行がフェッチされる前にループを終了させた場合やループの内側から例外が呼び出され
た場合も、カーソルはクローズされます。13-71 ページの「LOOP 文」を参照してください。
PL/SQL での SQL 操作の実行
6-15
副問合せの使用
PL/SQL を使用したデータの問合せ : 明示カーソルの FOR ループ
同じプロシージャの別の部分から同じ問合せを参照する必要がある場合、その問合せを指定す
るカーソルを宣言し、FOR ループを使用して結果を処理できます。
DECLARE
CURSOR c1 IS SELECT last_name, job_id FROM employees
WHERE job_id LIKE '%CLERK%' AND manager_id > 120;
BEGIN
FOR item IN c1
LOOP
DBMS_OUTPUT.PUT_LINE('Name = ' || item.last_name || ', Job = ' ||
item.job_id);
END LOOP;
END;
/
13-71 ページの「LOOP 文」を参照してください。
カーソル FOR ループ内の式の別名の定義
カーソル FOR ループでは、PL/SQL によって、結果セットの列に対応するフィールドを持つ
%ROWTYPE レコードが作成されます。フィールドは、SELECT リストの中の対応する列と同じ
名前を持ちます。
選択リストには、列と定数、連結された 2 つの列などの式が含まれる場合があります。この場
合、列の別名を使用して、適切な列に一意の名前を付けます。
例 6-18 では、full_name および dream_salary が問合せの中で式の別名として使用されてい
ます。
例 6-18 問合せ内での式の別名の使用
BEGIN
FOR item IN
( SELECT first_name || ' ' || last_name AS full_name,
salary * 10 AS dream_salary FROM employees WHERE ROWNUM <= 5 )
LOOP
DBMS_OUTPUT.PUT_LINE(item.full_name || ' dreams of making ' ||
item.dream_salary);
END LOOP;
END;
/
副問合せの使用
副問合せは、別の SQL DML 文内に出現する問合せであり、多くの場合カッコで囲まれていま
す。文は、副問合せで戻された 1 つの値または複数の値の集合に対して実行されます。次に例
を示します。
■
■
■
■
■
6-16
副問合せを使用して列の MAX()、MIN() または AVG() の値を検索し、この単一の値を使用
して WHERE 句の中で比較を行うことができます。
副問合せを使用して値の集合を検索し、その値を使用して WHERE 句の中で IN または NOT
IN の比較を行うことができます。この方法を使用すると、結合を回避できます。
副問合せを使用して値の集合をフィルタリングし、外部の問合せで ORDER BY や GROUP BY
などの別の操作を適用できます。
問合せの FROM 句で、表名のかわりに副問合せを使用できます。この方法を使用すると、
表全体を結合するかわりに、表と別の表から取り出した小さい行セットを結合できます。
副問合せで定義した行セットを使用して、表を作成したり、表へ挿入することができます。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
副問合せの使用
例 6-19 に、カーソル宣言で使用される 2 つの副問合せを示します。
例 6-19 カーソルでの副問合せの使用
DECLARE
CURSOR c1 IS
-- main query returns only rows where the salary is greater than the average
SELECT employee_id, last_name FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
CURSOR c2 IS
-- subquery returns all the rows in descending order of salary
-- main query returns just the top 10 highest-paid employees
SELECT * FROM
(SELECT last_name, salary FROM employees ORDER BY salary DESC, last_name)
WHERE ROWNUM < 11;
BEGIN
FOR person IN c1
LOOP
DBMS_OUTPUT.PUT_LINE('Above-average salary: ' || person.last_name);
END LOOP;
FOR person IN c2
LOOP
DBMS_OUTPUT.PUT_LINE('Highest paid: ' || person.last_name ||
' $' || person.salary);
END LOOP;
-- subquery identifies a set of rows to use with CREATE TABLE or INSERT
END;
/
FROM 句の中で副問合せを使用した例 6-20 の問合せでは、従業員が 5 人以上の部門の番号と名
称を戻します。
例 6-20 FROM 句での副問合せの使用
DECLARE
CURSOR c1 IS
SELECT t1.department_id, department_name, staff
FROM departments t1,
( SELECT department_id, COUNT(*) as staff
FROM employees GROUP BY department_id) t2
WHERE
t1.department_id = t2.department_id
AND staff >= 5;
BEGIN
FOR dept IN c1
LOOP
DBMS_OUTPUT.PUT_LINE('Department = ' || dept.department_name ||
', staff = ' || dept.staff);
END LOOP;
END;
/
相関副問合せの使用
副問合せが各表につき 1 回しか評価されないのに対し、相関副問合せは各行につき 1 回評価さ
れます。例 6-21 では、給与が部門平均を上回っている従業員の名前と給与を戻しています。相
関副問合せでは、表の各行について、対応する部門の平均給与を計算します。
例 6-21 相関副問合せの使用
DECLARE
-- For each department, find the average salary. Then find all the employees in
-- that department making more than that average salary.
PL/SQL での SQL 操作の実行
6-17
副問合せの使用
CURSOR c1 IS
SELECT department_id, last_name, salary FROM employees t
WHERE salary >
( SELECT AVG(salary) FROM employees WHERE t.department_id = department_id )
ORDER BY department_id;
BEGIN
FOR person IN c1
LOOP
DBMS_OUTPUT.PUT_LINE('Making above-average salary = ' || person.last_name);
END LOOP;
END;
/
メンテナンス可能な PL/SQL 問合せの作成
ローカル変数を参照するかわりに、パラメータを受け入れるカーソルを宣言し、カーソルを
オープンしたときにそれらのパラメータの値を渡すことができます。問合せが通常、特定の値
を使用して発行される場合、それらの値をデフォルトとして指定できます。パラメータの値を
渡すには、位置表記法および名前表記法のいずれも使用できます。
例 6-22 に、指定された部門内で、給与が指定額を超える従業員の給与を示します。
例 6-22 カーソル FOR ループへのパラメータの引渡し
DECLARE
CURSOR c1 (job VARCHAR2, max_wage NUMBER) IS
SELECT * FROM employees WHERE job_id = job AND salary > max_wage;
BEGIN
FOR person IN c1('CLERK', 3000)
LOOP
-- process data record
DBMS_OUTPUT.PUT_LINE('Name = ' || person.last_name || ', salary = ' ||
person.salary || ', Job Id = ' || person.job_id );
END LOOP;
END;
/
例 6-23 に、カーソルをオープンする方法の例を示します。
例 6-23 明示カーソルへのパラメータの引渡し
DECLARE
emp_job
employees.job_id%TYPE := 'ST_CLERK';
emp_salary employees.salary%TYPE := 3000;
my_record employees%ROWTYPE;
CURSOR c1 (job VARCHAR2, max_wage NUMBER) IS
SELECT * FROM employees WHERE job_id = job and salary > max_wage;
BEGIN
-- Any of the following statements opens the cursor:
-- OPEN c1('ST_CLERK', 3000); OPEN c1('ST_CLERK', emp_salary);
-- OPEN c1(emp_job, 3000); OPEN c1(emp_job, emp_salary);
OPEN c1(emp_job, emp_salary);
LOOP
FETCH c1 INTO my_record;
EXIT WHEN c1%NOTFOUND;
-- process data record
DBMS_OUTPUT.PUT_LINE('Name = ' || my_record.last_name || ', salary = ' ||
my_record.salary || ', Job Id = ' || my_record.job_id );
END LOOP;
END;
/
6-18
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
カーソル変数(REF CURSOR)の使用
混同を避けるために、カーソルのパラメータとそれらのパラメータに渡す PL/SQL 変数には異
なる名前を使用します。
デフォルト値で宣言された仮パラメータには、対応する実パラメータがなくてもかまいません。
実パラメータを省略した場合、仮パラメータは、OPEN 文の実行時にデフォルト値を取ります。
カーソル変数(REF
CURSOR)の使用
)の使用
カーソル変数(
カーソルと同じように、カーソル変数は複数行の問合せの結果セットの中の現在行を指します。
カーソル変数は、特定の問合せと結合されないため、より柔軟性があります。カーソル変数は、
正しい列セットを戻す任意の問合せに対してオープンできます。
カーソル変数は、パラメータとしてローカル・サブプログラムおよびストアド・サブプログラ
ムに渡します。1 つのサブプログラム内でカーソル変数をオープンし、別のサブプログラム内
でこの変数を処理することで、データ検索を集中的に実行できます。この方法は、PL/SQL サ
ブプログラムが別の言語(Java や Visual Basic など)で記述されたサブプログラムへ結果セッ
トを戻す可能性がある、複数言語のアプリケーションでも役立ちます。
カーソル変数は、すべての PL/SQL クライアントで使用します。たとえば、OCI や Pro*C プロ
グラムなどの PL/SQL ホスト環境の中でカーソル変数を宣言し、それを入力ホスト変数(バイ
ンド変数)として PL/SQL に渡すことができます。PL/SQL エンジンを備えた Oracle Forms な
どのアプリケーション開発ツールでは、クライアント側でカーソル変数を完全に使用できます。
また、クライアントとデータベース・サーバーの間で、リモート・プロシージャ・コールを介
してカーソル変数をやり取りできます。
カーソル変数(REF
CURSOR)
)
カーソル変数(
カーソル変数は、結果セットへのポインタに類似しています。1 つのサブプログラム内で問合
せを実行する際にカーソル変数を使用して、問合せ結果を別のサブプログラム(別の言語で記
述されている場合もある)で処理します。カーソル変数のデータ型は REF CURSOR であり、通
称で REF CURSOR と呼ばれます。
常に同じ問合せ作業領域を参照する明示カーソルとは異なり、カーソル変数は異なる作業領域
を参照できます。カーソルを使用する予定の場所では、カーソル変数を使用できません。逆の
場合も同じです。
変数を使用する理由
カーソル変数は、PL/SQL のストアド・サブプログラムと様々なクライアントとの間で問合せ
の結果セットを渡すために使用します。PL/SQL とそのクライアントは、結果セットが格納さ
れている問合せ作業領域を指すポインタを共有します。たとえば、OCI クライアント、Oracle
Forms アプリケーションおよび Oracle データベース・サーバーがすべて同じ作業領域を参照す
る可能性があります。
カーソル変数の値は、1 つの有効範囲から別の有効範囲に渡すことができるため、問合せ作業
領域は、それを指すカーソル変数が存在するかぎりアクセス可能になります。たとえば、Pro*C
プログラムに組み込まれた PL/SQL ブロックにホスト・カーソル変数を渡す場合、カーソル変
数が指す作業領域は、そのブロックの終了後もアクセス可能な状態のままです。
クライアント側に PL/SQL エンジンがあれば、クライアントからサーバーへのコールに課され
る制限はありません。たとえば、クライアント側でカーソル変数を宣言し、それをサーバー側
でオープンしてフェッチした後で、クライアント側で引き続きフェッチすることができます。
また、PL/SQL ブロックを使用して複数のホスト・カーソル変数を 1 回の往復でオープンまた
はクローズすることで、ネットワークの通信量を削減できます。
PL/SQL での SQL 操作の実行
6-19
カーソル変数(REF CURSOR)の使用
REF CURSOR 型およびカーソル変数の宣言
カーソル変数を作成するには、REF CURSOR 型を定義してから、その型のカーソル変数を宣言
します。REF CURSOR 型は、任意の PL/SQL ブロック、サブプログラムまたはパッケージの中
で定義できます。次の例では、DEPARTMENTS 表から取り出した結果セットを表す REF
CURSOR 型を宣言しています。
DECLARE
TYPE DeptCurTyp IS REF CURSOR RETURN departments%ROWTYPE;
REF CURSOR 型には、強い(戻り型を持つ)ものと弱い(戻り型を持たない)ものがあります。
強い REF CURSOR 型の方が、エラー発生の可能性は少なくなります。これは、PL/SQL コンパ
イラの場合、強い型指定のカーソル変数は正しい列セットを戻す問合せにのみ関連付けること
ができるためです。弱い REF CURSOR 型は、より柔軟です。弱い型指定のカーソル変数は、ど
の問合せにも関連付けることができます。弱い REF CURSOR に対しては、型のチェックが行わ
れないため、すべての弱い型は互換性があります。新しい型を作成するかわりに、事前定義の
SYS_REFCURSOR 型を使用することもできます。
REF CURSOR 型を宣言すると、PL/SQL ブロックまたはサブプログラムで、その型のカーソル
変数を宣言できます。
DECLARE
TYPE empcurtyp IS REF CURSOR RETURN employees%ROWTYPE; -- strong
TYPE genericcurtyp IS REF CURSOR; -- weak
cursor1 empcurtyp;
cursor2 genericcurtyp;
my_cursor SYS_REFCURSOR; -- didn't need to declare a new type
TYPE deptcurtyp IS REF CURSOR RETURN departments%ROWTYPE;
dept_cv deptcurtyp; -- declare cursor variable
REF CURSOR 型を使用する各サブプログラムでその同じ型を宣言することを回避するために、
パッケージ仕様部で REF CURSOR を宣言できます。その型のカーソル変数は、対応するパッ
ケージ本文、または独自のファンクションやプロシージャ内で宣言できます。
例 6-24 に示すとおり、REF CURSOR 型定義の RETURN 句では、%ROWTYPE を使用して、強い型
指定のカーソル変数を参照できます。
例 6-24 %ROWTYPE 変数を戻すカーソル変数
DECLARE
TYPE TmpCurTyp IS
tmp_cv TmpCurTyp;
TYPE EmpCurTyp IS
emp_cv EmpCurTyp;
REF
-REF
--
CURSOR RETURN employees%ROWTYPE;
declare cursor variable
CURSOR RETURN tmp_cv%ROWTYPE;
declare cursor variable
例 6-25 に示すとおり、%ROWTYPE を使用して、レコード変数のデータ型を与えることもできま
す。
例 6-25 %ROWTYPE 属性を使用したデータ型の指定
DECLARE
dept_rec departments%ROWTYPE; -- declare record variable
TYPE DeptCurTyp IS REF CURSOR RETURN dept_rec%TYPE;
dept_cv DeptCurTyp; -- declare cursor variable
例 6-26 では、RETURN 句の中でユーザー定義の RECORD 型を指定しています。
例 6-26 レコード型を戻すカーソル変数
DECLARE
TYPE EmpRecTyp IS RECORD (
employee_id NUMBER,
last_name VARCHAR2(25),
salary NUMBER(8,2));
6-20
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
カーソル変数(REF CURSOR)の使用
TYPE EmpCurTyp IS REF CURSOR RETURN EmpRecTyp;
emp_cv EmpCurTyp; -- declare cursor variable
パラメータとしてのカーソル変数の引渡し
カーソル変数はファンクションまたはプロシージャの仮パラメータとして宣言できます。例
6-27 では、REF CURSOR 型を定義し、その型のカーソル変数を仮パラメータとして宣言してい
ます。
例 6-27 REF CURSOR のパラメータとしての引渡し
DECLARE
TYPE empcurtyp IS REF CURSOR RETURN employees%ROWTYPE;
emp empcurtyp;
-- after result set is built, process all the rows inside a single procedure
-- rather than calling a procedure for each row
PROCEDURE process_emp_cv (emp_cv IN empcurtyp) IS
person employees%ROWTYPE;
BEGIN
DBMS_OUTPUT.PUT_LINE('-----');
DBMS_OUTPUT.PUT_LINE('Here are the names from the result set:');
LOOP
FETCH emp_cv INTO person;
EXIT WHEN emp_cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Name = ' || person.first_name ||
' ' || person.last_name);
END LOOP;
END;
BEGIN
-- First find 10 arbitrary employees.
OPEN emp FOR SELECT * FROM employees WHERE ROWNUM < 11;
process_emp_cv(emp);
CLOSE emp;
-- find employees matching a condition.
OPEN emp FOR SELECT * FROM employees WHERE last_name LIKE 'R%';
process_emp_cv(emp);
CLOSE emp;
END;
/
すべてのポインタと同様に、カーソル変数によってパラメータのエイリアシング機能を拡張で
きます。8-10 ページの「サブプログラム名のオーバーロード」を参照してください。
カーソル変数の制御 : OPEN-FOR、
、FETCH および CLOSE
カーソル変数の制御には、OPEN-FOR、FETCH および CLOSE の 3 つの文を使用します。まず、
OPEN-FOR 文でカーソル変数を複数行問合せ用にオープンします。次に、FETCH 文で結果セッ
トから行を取り出します。すべての行が処理された後に、CLOSE 文でカーソル変数をクローズ
します。
カーソル変数のオープン
OPEN-FOR 文を使用すると、カーソル変数を複数行の問合せに結び付けたり、問合せを実行し
たり、結果セットを識別することができます。カーソル変数は、PL/SQL 内、または OCI プロ
グラムなどの PL/SQL ホスト環境で直接宣言できます。OPEN-FOR 文の構文は、13-81 ページ
の「OPEN-FOR 文」を参照してください。
問合せの SELECT 文は、文中に直接コーディングすることも、文字列変数または文字列リテラ
ルにすることもできます。文字列を問合せとして使用する場合、文字列にバインド変数用のプ
レースホルダを含め、USING 句を使用して対応する値を指定できます。
PL/SQL での SQL 操作の実行
6-21
カーソル変数(REF CURSOR)の使用
この項では静的 SQL の場合について説明します。ここでは select_statement を使用しま
す。動的 SQL の場合は dynamic_string が使用されます。13-81 ページの「OPEN-FOR 文」
を参照してください。
カーソルとは異なり、カーソル変数はパラメータを取りません。かわりに、カーソル変数には
パラメータのみでなく問合せ全体を渡すことができます。問合せでは、ホスト変数、PL/SQL
変数、パラメータおよびファンクションを参照できます。
例 6-28 では、カーソル変数をオープンします。カーソルの属性(%FOUND、%NOTFOUND、
%ISOPEN、%ROWCOUNT)をカーソル変数に適用できることに注意してください。
例 6-28 カーソル変数がオープンしているかどうかのチェック
DECLARE
TYPE empcurtyp IS REF CURSOR RETURN employees%ROWTYPE;
emp_cv empcurtyp;
BEGIN
IF NOT emp_cv%ISOPEN THEN -- open cursor variable
OPEN emp_cv FOR SELECT * FROM employees;
END IF;
CLOSE emp_cv;
END;
/
その他の OPEN-FOR 文は、異なる複数の問合せ用に同じカーソル変数をオープンできます。
カーソル変数を再オープンする場合、その前にクローズする必要はありません。静的カーソル
を OPEN 文で連続してオープンすると、事前定義の例外 CURSOR_ALREADY_OPEN が呼び出さ
れます。別の問合せ用にカーソル変数を再オープンすると、前の問合せは失われます。
一般に、カーソル変数をオープンするときは、カーソル変数である IN OUT パラメータを宣言
するストアド・プロシージャにそのカーソル変数を渡します。例 6-29 では、カーソル変数を
オープンしています。
例 6-29 REF CURSOR をオープンするストアド・プロシージャ
CREATE PACKAGE emp_data AS
TYPE empcurtyp IS REF CURSOR RETURN employees%ROWTYPE;
PROCEDURE open_emp_cv (emp_cv IN OUT empcurtyp);
END emp_data;
/
CREATE PACKAGE BODY emp_data AS
PROCEDURE open_emp_cv (emp_cv IN OUT EmpCurTyp) IS
BEGIN
OPEN emp_cv FOR SELECT * FROM employees;
END open_emp_cv;
END emp_data;
/
スタンドアロン・ストアド・プロシージャを使用してカーソル変数をオープンする方法もあり
ます。パッケージの中で REF CURSOR 型を定義して、ストアド・プロシージャのパラメータ宣
言でその型を参照します。
データ検索を集中的に実行するために、ストアド・プロシージャの中で型互換性のある問合せ
をグループにまとめることができます。例 6-30 では、パッケージ・プロシージャは仮パラメー
タの 1 つとして選択子を宣言しています。コールされた場合、プロシージャは選択された問合
せに対してカーソル変数 emp_cv をオープンします。
例 6-30 別の問合せで REF CURSOR をオープンするストアド・プロシージャ
CREATE PACKAGE emp_data AS
TYPE empcurtyp IS REF CURSOR RETURN employees%ROWTYPE;
PROCEDURE open_emp_cv (emp_cv IN OUT empcurtyp, choice INT);
END emp_data;
/
6-22
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
カーソル変数(REF CURSOR)の使用
CREATE PACKAGE BODY emp_data AS
PROCEDURE open_emp_cv (emp_cv IN OUT empcurtyp, choice INT) IS
BEGIN
IF choice = 1 THEN
OPEN emp_cv FOR SELECT * FROM employees WHERE commission_pct IS NOT NULL;
ELSIF choice = 2 THEN
OPEN emp_cv FOR SELECT * FROM employees WHERE salary > 2500;
ELSIF choice = 3 THEN
OPEN emp_cv FOR SELECT * FROM employees WHERE department_id = 100;
END IF;
END;
END emp_data;
/
例 6-31 に示すとおり、柔軟性を高めるために、異なる戻り型を指定した問合せをストアド・プ
ロシージャで実行できます。
例 6-31 異なる戻り型を持つカーソル変数
CREATE PACKAGE admin_data AS
TYPE gencurtyp IS REF CURSOR;
PROCEDURE open_cv (generic_cv IN
END admin_data;
/
CREATE PACKAGE BODY admin_data AS
PROCEDURE open_cv (generic_cv IN
BEGIN
IF choice = 1 THEN
OPEN generic_cv FOR SELECT
ELSIF choice = 2 THEN
OPEN generic_cv FOR SELECT
ELSIF choice = 3 THEN
OPEN generic_cv FOR SELECT
END IF;
END;
END admin_data;
/
OUT gencurtyp, choice INT);
OUT gencurtyp, choice INT) IS
* FROM employees;
* FROM departments;
* FROM jobs;
ホスト変数としてのカーソル変数の使用
OCI や Pro*C プログラムなどの PL/SQL ホスト環境で、カーソル変数を宣言できます。カーソ
ル変数を使用する場合は、ホスト変数として PL/SQL に渡す必要があります。次の Pro*C の例
では、ホスト・カーソル変数と選択子を PL/SQL ブロックに渡すことで、選択した問合せ用の
カーソル変数をオープンしています。
EXEC SQL BEGIN DECLARE SECTION;
...
/* Declare host cursor variable. */
SQL_CURSOR generic_cv;
int
choice;
EXEC SQL END DECLARE SECTION;
...
/* Initialize host cursor variable. */
EXEC SQL ALLOCATE :generic_cv;
...
/* Pass host cursor variable and selector to PL/SQL block. */
EXEC SQL EXECUTE
BEGIN
IF :choice = 1 THEN
OPEN :generic_cv FOR SELECT * FROM employees;
ELSIF :choice = 2 THEN
OPEN :generic_cv FOR SELECT * FROM departments;
PL/SQL での SQL 操作の実行
6-23
カーソル変数(REF CURSOR)の使用
ELSIF :choice = 3 THEN
OPEN :generic_cv FOR SELECT * FROM jobs;
END IF;
END;
END-EXEC;
ホスト・カーソル変数はすべての問合せの戻り型と互換性があります。ホスト・カーソル変数
は、弱い型指定の PL/SQL カーソル変数と同じように動作します。
カーソル変数からのフェッチ
FETCH 文は、複数行の問合せの結果セットから、行を取り出します。この文は、カーソル変数
でも明示カーソルの場合と同様に機能します。例 6-32 では、カーソル変数からレコードへ一度
に 1 行ずつ行をフェッチしています。
例 6-32 カーソル変数からレコードへのフェッチ
DECLARE
TYPE empcurtyp IS REF CURSOR RETURN employees%ROWTYPE;
emp_cv empcurtyp;
emp_rec employees%ROWTYPE;
BEGIN
OPEN emp_cv FOR SELECT * FROM employees WHERE employee_id < 120;
LOOP
FETCH emp_cv INTO emp_rec; -- fetch from cursor variable
EXIT WHEN emp_cv%NOTFOUND; -- exit when last row is fetched
-- process data record
DBMS_OUTPUT.PUT_LINE('Name = ' || emp_rec.first_name || ' ' ||
emp_rec.last_name);
END LOOP;
CLOSE emp_cv;
END;
/
例 6-33 に示すとおり、BULK COLLECT 句を使用して、1 つのカーソル変数から 1 つ以上のコレ
クションに行のバルク・フェッチを行います。
例 6-33 カーソル変数からコレクションへのフェッチ
DECLARE
TYPE empcurtyp IS REF CURSOR;
TYPE namelist IS TABLE OF employees.last_name%TYPE;
TYPE sallist IS TABLE OF employees.salary%TYPE;
emp_cv empcurtyp;
names namelist;
sals sallist;
BEGIN
OPEN emp_cv FOR SELECT last_name, salary FROM employees
WHERE job_id = 'SA_REP';
FETCH emp_cv BULK COLLECT INTO names, sals;
CLOSE emp_cv;
-- loop through the names and sals collections
FOR i IN names.FIRST .. names.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Name = ' || names(i) || ', salary = ' || sals(i));
END LOOP;
END;
/
6-24
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
カーソル変数(REF CURSOR)の使用
カーソル変数がオープンしている場合のみ、対応付けられた問合せの中の変数が評価されます。
結果セットや問合せの中の変数の値を変更する場合は、カーソル変数を新しい値に設定して再
オープンします。同じカーソル変数を使用して、別々の FETCH 文で、異なる INTO 句を使用
できます。各 FETCH 文で同じ結果セットから別の行をフェッチします。
PL/SQL では、カーソル変数の戻り型が、必ず FETCH 文の INTO 句と互換性を持ちます。互換
性がない場合、カーソル変数が強い型指定の場合はコンパイル時に、弱い型指定の場合は実行
時にエラーが発生します。実行時に、PL/SQL は最初の取出しの前に、事前定義の例外
ROWTYPE_MISMATCH を呼び出します。エラーをトラップし、異なる(互換性のある)INTO 句
を使用して FETCH 文を実行すると、行は失われません。
カーソル変数を、そのカーソル変数からフェッチするサブプログラムの仮パラメータとして宣
言する場合は、IN または IN OUT モードを指定する必要があります。サブプログラムがカーソ
ル変数もオープンする場合は、IN OUT モードを指定する必要があります。
クローズしている、または一度もオープンされていないカーソル変数からフェッチを実行する
と、PL/SQL によって事前定義の例外 INVALID_CURSOR が呼び出されます。
カーソル変数のクローズ
CLOSE 文によってカーソル変数は使用禁止になり、関連する結果セットは未定義になります。
最後の行が処理された後でカーソル変数をクローズします。
カーソル変数を、そのカーソル変数をクローズするサブプログラムの仮パラメータとして宣言
する場合は、IN または IN OUT モードを指定する必要があります。すでにクローズされている
か、1 度もオープンされたことのないカーソル変数をクローズすると、PL/SQL によって事前
定義の例外 INVALID_CURSOR が呼び出されます。
ホスト・カーソル変数を PL/SQL に渡すときのネットワークの通信量の削減
ホスト・カーソル変数を PL/SQL に渡す場合、OPEN-FOR 文をグループ化することでネット
ワークの通信量を削減できます。たとえば、次の PL/SQL ブロックでは、1 回の往復で複数の
カーソル変数をオープンします。
/* anonymous PL/SQL block in host environment */
BEGIN
OPEN :emp_cv FOR SELECT * FROM employees;
OPEN :dept_cv FOR SELECT * FROM departments;
OPEN :loc_cv FOR SELECT * FROM locations;
END;
/
この方法は Oracle Forms で便利です(たとえば、マルチブロック・フォームにデータを入れる
場合)
。ホスト・カーソル変数を PL/SQL ブロックに渡してオープンする場合、ホスト・カー
ソル変数が指す問合せ作業領域は、ブロックの終了後もアクセス可能な状態のままです。その
ため、OCI や Pro*C プログラムで、通常のカーソル操作用にその作業領域を使用できます。例
では、1 回の往復でこのような作業領域をいくつかオープンします。
BEGIN
OPEN :c1 FOR SELECT 1 FROM dual;
OPEN :c2 FOR SELECT 1 FROM dual;
OPEN :c3 FOR SELECT 1 FROM dual;
END;
/
c1、c2 および c3 に代入されたカーソルは通常どおり動作し、あらゆる用途に使用できます。
終了すると、次のようにカーソルを解放します。
BEGIN
CLOSE :c1; CLOSE :c2; CLOSE :c3;
END;
/
PL/SQL での SQL 操作の実行
6-25
カーソル変数(REF CURSOR)の使用
カーソル変数でのエラーの回避
代入に関係する両方のカーソル変数が強い型指定である場合は、両方が同じデータ型であるこ
とが必要です(同じ戻り型であるのみでは不十分です)
。一方または両方のカーソル変数が弱い
型指定である場合は、データ型が異なってもかまいません。
問合せ作業領域を指していないカーソル変数に対して取出しまたはクローズを実行するか、
カーソルの属性を参照すると、PL/SQL によって例外 INVALID_CURSOR が呼び出されます。
カーソル変数(またはパラメータ)が問合せ作業領域を指すようにするには、次の 2 通りの方
法があります。
■
■
OPEN-FOR 文でカーソル変数を問合せ用にオープンします。
OPEN 文ですでにオープンされたホスト・カーソル変数または PL/SQL カーソル変数の値
を、カーソル変数に代入します。
オープンされていないカーソル変数を別のカーソル変数に代入すると、1 番目のカーソル変数
をオープンした後も、2 番目のカーソル変数は無効のままです。
カーソル変数をパラメータとして渡す場合は注意が必要です。実パラメータと仮パラメータの
戻り型に互換性がないと、実行時に PL/SQL によって ROWTYPE_MISMATCH が呼び出されま
す。
カーソル変数の制限
現在、カーソル変数には次の制限があります。
■
■
■
■
■
■
パッケージ仕様部ではカーソル変数を宣言できません(例 6-34 を参照)
。
ホスト・カーソル変数を OCI クライアントから PL/SQL にバインドする場合は、同じサー
バー・コールで変数をオープンしないかぎり、サーバー側で変数からフェッチできません。
比較演算子を使用して、カーソル変数が等しいかどうか、または NULL かどうかをテスト
できません。
データベースの列にカーソル変数の値を格納できません。CREATE TABLE 文の中で使用す
るための等価の型は存在しません。
カーソル変数を、結合配列、ネストした表または VARRAY に格納できません。
カーソルとカーソル変数には相互操作性がありません。つまり、一方の値が期待されてい
る場所で、もう一方が使用できません。たとえば、カーソル FOR ループの中ではカーソル
変数を参照できません。
例 6-34 パッケージでのカーソル変数の宣言
CREATE PACKAGE emp_data AS
TYPE EmpCurTyp IS REF CURSOR RETURN employees%ROWTYPE;
-- emp_cv EmpCurTyp; -- not allowed
PROCEDURE open_emp_cv;
END emp_data;
/
CREATE PACKAGE BODY emp_data AS
-- emp_cv EmpCurTyp; -- not allowed
PROCEDURE open_emp_cv IS
emp_cv EmpCurTyp; -- this is legal
BEGIN
OPEN emp_cv FOR SELECT * FROM employees;
END open_emp_cv;
END emp_data;
/
6-26
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
カーソル式の使用
注意 :
■
■
サーバー間 RPC で REF CURSOR 変数を使用すると、エラーが発生しま
す。ただし、リモート・アドレスがプロシージャ・ゲートウェイを介
してアクセスされる、Oracle 以外のデータベースである場合は、サー
バー間 RPC で REF CURSOR 変数を使用できます。
サーバー間 RPC では LOB パラメータを使用できません。
カーソル式の使用
カーソル式はネストしたカーソルを戻します。結果セットの各行には、通常の値の他に、行内
の他の値に関係する副問合せで生成されるカーソルも含まれることがあります。1 つの問合せ
で、複数の表から取り出された関連値の大きな集合を戻すことができます。結果セットは、最
初にその行から、次に各行でネストしたカーソルからフェッチするネステッド・ループで処理
できます。
PL/SQL では、カーソルの宣言、REF CURSOR の宣言および REF CURSOR 変数の一部として、
カーソル式を持つ問合せがサポートされます。また、カーソル式は動的 SQL 問合せにも使用で
きます。次に構文を示します。
CURSOR(subquery)
ネストしたカーソルは、それを含んでいる行が親カーソルからフェッチされるときに暗黙的に
オープンされます。ネストしたカーソルがクローズされるのは、次の場合のみです。
■
ネストしたカーソルをユーザーが明示的にクローズしたとき。
■
親カーソルが再実行されるとき。
■
親カーソルがクローズされるとき。
■
親カーソルが取り消されるとき。
■
親カーソルの 1 つのフェッチ中にエラーが呼び出されるとき。ネストしたカーソルはク
リーンアップの一部としてクローズされます。
カーソル式の制限
次に、カーソル式に関する制限を示します。
■
カーソル式は、暗黙カーソルとは併用できません。
■
カーソル式を使用できるのは、次の場合のみです。
■
■
カーソル式自体が副問合せである場合を除き、他の問合せの式の中でネストされてい
ない SELECT 文中。
SELECT 文の FROM 句で、テーブル・ファンクションの引数として。
■
カーソル式を使用できるのは、問合せ仕様部の最も外側の SELECT リスト内のみです。
■
カーソル式はビュー宣言には使用できません。
■
カーソル式の BIND および EXECUTE 操作は実行できません。
PL/SQL での SQL 操作の実行
6-27
PL/SQL におけるトランザクション処理の概要
カーソル式の例
例 6-35 では、指定した所在地 ID と、その所在地にある全部門をフェッチできるカーソルを検
索します。各部門の名前をフェッチすると、別の表から関連する従業員詳細をフェッチできる、
もう 1 つのカーソルも取得します。
例 6-35 カーソル式の使用
DECLARE
TYPE emp_cur_typ IS REF CURSOR;
emp_cur emp_cur_typ;
dept_name departments.department_name%TYPE;
emp_name employees.last_name%TYPE;
CURSOR c1 IS SELECT
department_name,
-- second item in the result set is another result set,
-- which is represented as a ref cursor and labelled "employees".
CURSOR
( SELECT e.last_name FROM employees e
WHERE e.department_id = d.department_id) employees
FROM departments d WHERE department_name like 'A%';
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO dept_name, emp_cur;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Department: ' || dept_name);
-- for each row in the result set, the result set from a subquery is processed
-- the set could be passed to a procedure for processing rather than the loop
LOOP
FETCH emp_cur INTO emp_name;
EXIT WHEN emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('-- Employee: ' || emp_name);
END LOOP;
END LOOP;
CLOSE c1;
END;
/
カーソル副問合せを使用した REF CURSOR の構成
カーソル副問合せはカーソル式とも呼ばれ、ファンクションにパラメータとして行セットを渡
すことができます。たとえば、次の文では、StockPivot ファンクションにパラメータを渡して
おり、このファンクションはカーソル副問合せから戻される行を表す REF CURSOR で構成され
ています。
SELECT * FROM TABLE(StockPivot(
CURSOR(SELECT * FROM StockTable)));
カーソル副問合せは、通常はテーブル・ファンクションと併用されます。11-31 ページの「パイ
プライン・ファンクションによる変換の設定」を参照してください。
PL/SQL におけるトランザクション処理の概要
この項では、データベースの整合性を確保する、SQL の COMMIT、SAVEPOINT および
ROLLBACK 文を使用した、PL/SQL によるトランザクション処理について説明します。SQL 文
は、PL/SQL プログラム内に直接記述できます。トランザクション処理は Oracle の機能で、す
べてのプログラミング言語で使用できます。これらの機能によって、複数のユーザーがデータ
ベース上で同時に作業できます。また、各ユーザーが参照するデータのバージョンに一貫性が
あり、すべての変更が正しい順序で適用されることが保証されます。
6-28
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL におけるトランザクション処理の概要
通常、複数のユーザーがデータに同時にアクセスすることによって発生する問題を防ぐために、
追加のコードを記述する必要はありません。Oracle では、ロックを使用してデータへの同時ア
クセスを制御します。Oracle は、必要最小限のデータのみを、できるかぎり短い時間ロックし
ます。表または行のロックは、どうしてもこのレベルの制御が必要な場合に要求できます。行
の共有および排他のような数種類のロッキングのモードから選択できます。
トランザクションの詳細は、
『Oracle Database 概要』を参照してください。SQL の COMMIT、
SAVEPOINT および ROLLBACK 文の詳細は、『Oracle Database SQL リファレンス』を参照して
ください。
PL/SQL での COMMIT の使用
COMMIT 文は、カレント・トランザクションを終了し、トランザクション中に加えられた変更
を永続的なものにして、他のユーザーから参照できるようにします。トランザクションは、
PL/SQL の BEGIN-END ブロックとは結び付けられません。ブロックは複数のトランザクショ
ンを含むことができます。また、トランザクションは複数のブロックにまたがることができま
す。
例 6-36 に、銀行口座の間で振替えを実行するトランザクションを示します。一方の口座から現
金が出金され、同時に他方の口座に現金が入金されることが重要です。そうでない場合、処理
の途中で問題が発生すると、両方の口座からその金額の現金が消失したり、両方の口座でその
金額の現金が重複する可能性があります。
例 6-36 WRITE 句と COMMIT の併用
CREATE TABLE accounts (account_id NUMBER(6), balance NUMBER (10,2));
INSERT INTO accounts VALUES (7715, 6350.00);
INSERT INTO accounts VALUES (7720, 5100.50);
DECLARE
transfer NUMBER(8,2) := 250;
BEGIN
UPDATE accounts SET balance = balance - transfer WHERE account_id = 7715;
UPDATE accounts SET balance = balance + transfer WHERE account_id = 7720;
COMMIT COMMENT 'Transfer From 7715 to 7720' WRITE IMMEDIATE NOWAIT;
END;
/
オプションの COMMENT 句を使用すると、分散トランザクションに対応付けるコメントを指定
できます。コミット中にネットワークやマシンに障害が発生した場合、分散トランザクション
が認識されないかまたはインダウトの状態になる可能性があります。この場合、Oracle は、
COMMENT で指定されたテキストをトランザクション ID とともにデータ・ディクショナリに格
納します。
非同期コミットでは、WRITE 句を使用してユーザーをより詳細に制御できます。このオプショ
ンは、コミット操作によって生成された REDO 情報を REDO ログに書き込む場合の優先順位
を指定します。
COMMIT の使用の詳細は、『Oracle Database アプリケーション開発者ガイド - 基礎編』のトラン
ザクションのコミットに関する項を参照してください。分散トランザクションの詳細は、
『Oracle Database 概要』を参照してください。13-23 ページの「COMMIT 文」を参照してくだ
さい。
PL/SQL での ROLLBACK の使用
ROLLBACK 文は、カレント・トランザクションを終了し、トランザクション中に加えられたす
べての変更を取り消します。表からの間違った行の削除などの誤操作を行った場合に、ロール
バックは元のデータをリストアできます。例外が呼び出されたり SQL 文が失敗したためにトラ
ンザクションを終了できない場合は、ロールバックを使用すると、対処措置を行い、実行しな
おすことができます。
PL/SQL での SQL 操作の実行
6-29
PL/SQL におけるトランザクション処理の概要
例 6-37 では、3 つの異なるデータベース表に従業員に関する情報を挿入しています。INSERT
文で重複する従業員番号を格納すると、事前定義の例外 DUP_VAL_ON_INDEX が呼び出されま
す。すべての 3 つの表に対する変更が取り消されたことを確認するために、例外ハンドラが
ROLLBACK を実行します。
例 6-37 ROLLBACK の使用
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
TABLE emp_name AS SELECT employee_id, last_name FROM employees;
UNIQUE INDEX empname_ix ON emp_name (employee_id);
TABLE emp_sal AS SELECT employee_id, salary FROM employees;
UNIQUE INDEX empsal_ix ON emp_sal (employee_id);
TABLE emp_job AS SELECT employee_id, job_id FROM employees;
UNIQUE INDEX empjobid_ix ON emp_job (employee_id);
DECLARE
emp_id
NUMBER(6);
emp_lastname VARCHAR2(25);
emp_salary
NUMBER(8,2);
emp_jobid
VARCHAR2(10);
BEGIN
SELECT employee_id, last_name, salary, job_id INTO emp_id, emp_lastname,
emp_salary, emp_jobid FROM employees WHERE employee_id = 120;
INSERT INTO emp_name VALUES (emp_id, emp_lastname);
INSERT INTO emp_sal VALUES (emp_id, emp_salary);
INSERT INTO emp_job VALUES (emp_id, emp_jobid);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('Inserts have been rolled back');
END;
/
13-101 ページの「ROLLBACK 文」を参照してください。
PL/SQL での SAVEPOINT の使用
SAVEPOINT は、トランザクション処理内の現在位置に名前とマークを付けます。セーブポイン
トを使用すると、トランザクション全体をロールバックするのではなく、トランザクションの
一部をロールバックできます。セッションごとのアクティブなセーブポイントの数には、制限
がありません。
例 6-38 では、挿入する前にセーブポイントをマークしています。INSERT 文で employee_id
列に重複した値を格納しようとすると、事前定義の例外 DUP_VAL_ON_INDEX が呼び出されま
す。この場合は、セーブポイントまでロールバックして、その挿入のみを取り消すことができ
ます。
例 6-38 ROLLBACK と SAVEPOINT の併用
CREATE TABLE emp_name AS SELECT employee_id, last_name, salary FROM employees;
CREATE UNIQUE INDEX empname_ix ON emp_name (employee_id);
DECLARE
emp_id
employees.employee_id%TYPE;
emp_lastname employees.last_name%TYPE;
emp_salary
employees.salary%TYPE;
BEGIN
SELECT employee_id, last_name, salary INTO emp_id, emp_lastname,
emp_salary FROM employees WHERE employee_id = 120;
UPDATE emp_name SET salary = salary * 1.1 WHERE employee_id = emp_id;
DELETE FROM emp_name WHERE employee_id = 130;
SAVEPOINT do_insert;
INSERT INTO emp_name VALUES (emp_id, emp_lastname, emp_salary);
EXCEPTION
6-30
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL におけるトランザクション処理の概要
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK TO do_insert;
DBMS_OUTPUT.PUT_LINE('Insert has been rolled back');
END;
/
あるセーブポイントまでロールバックすると、そのセーブポイント以降にマークされたセーブ
ポイントはすべて消去されます。ロールバック先のセーブポイントは消去されません。単純な
ロールバックまたはコミットではすべてのセーブポイントが消去されます。
再帰的サブプログラムの中でセーブポイントをマークすると、再帰しながら進む過程で、各レ
ベルで SAVEPOINT 文の新しいインスタンスが実行されます。ただし、ロールバックできるの
は直前にマークされたセーブポイントまでです。
セーブポイント名は未宣言の識別子です。セーブポイント名を再利用すると、セーブポイント
はトランザクションの中の古い位置から現在の位置に移動します。つまり、例 6-39 に示すとお
り、セーブポイントへのロールバックは、トランザクションの現在の部分のみに影響を与えま
す。
例 6-39 ROLLBACK による SAVEPOINT の再使用
CREATE TABLE emp_name AS SELECT employee_id, last_name, salary FROM employees;
CREATE UNIQUE INDEX empname_ix ON emp_name (employee_id);
DECLARE
emp_id
employees.employee_id%TYPE;
emp_lastname employees.last_name%TYPE;
emp_salary
employees.salary%TYPE;
BEGIN
SELECT employee_id, last_name, salary INTO emp_id, emp_lastname,
emp_salary FROM employees WHERE employee_id = 120;
SAVEPOINT my_savepoint;
UPDATE emp_name SET salary = salary * 1.1 WHERE employee_id = emp_id;
DELETE FROM emp_name WHERE employee_id = 130;
SAVEPOINT my_savepoint; -- move my_savepoint to current poin
INSERT INTO emp_name VALUES (emp_id, emp_lastname, emp_salary);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK TO my_savepoint;
DBMS_OUTPUT.PUT_LINE('Transaction rolled back.');
END;
/
13-104 ページの「SAVEPOINT 文」を参照してください。
Oracle による暗黙的なロールバックの実行方法
INSERT 文、UPDATE 文または DELETE 文を実行する前に、Oracle は(ユーザーが利用できな
い)暗黙的なセーブポイントをマークします。文の実行に失敗すると、Oracle はこのセーブポ
イントまでロールバックします。通常は、トランザクション全体ではなく、失敗した SQL 文の
みがロールバックされます。その文が原因で未処理例外が呼び出された場合は、ホスト環境に
よってロールバックの対象が決まります。
Oracle では、デッドロックを解消するために SQL 文を 1 文のみロールバックすることもできま
す。Oracle は関係しているトランザクションの 1 つにエラーを戻し、そのトランザクション中
の現在の文をロールバックします。
SQL 文を実行する前に、Oracle はその文を解析する必要があります。すなわち、その文が構文
規則に従っているかどうかや、有効なスキーマ・オブジェクトを参照しているかどうかを確認
する必要があります。SQL 文の実行時に検出されたエラーはロールバックを引き起こします
が、文の解析の際に検出されたエラーはロールバックを引き起こしません。
ストアド・サブプログラムを未処理例外で終了すると、PL/SQL は値を OUT パラメータに代入
せず、ロールバックを実行しません。
PL/SQL での SQL 操作の実行
6-31
PL/SQL におけるトランザクション処理の概要
トランザクションの終了
すべてのトランザクションは、明示的にコミットまたはロールバックする必要があります。コ
ミットを発行するか、または PL/SQL プログラムまたはクライアント・プログラムでロール
バックするかは、アプリケーション・ロジックによって決まります。トランザクションを明示
的にコミットまたはロールバックしなかった場合は、クライアント環境によって最終的な状態
が決定されます。
たとえば、SQL*Plus 環境で、PL/SQL ブロックに COMMIT 文または ROLLBACK 文がない場合、
トランザクションの最終状態はそのブロックの実行後に行うことによって決まります。ユー
ザーがデータ定義文、データ制御文または COMMIT 文を実行するか、EXIT コマンド、
DISCONNECT コマンドまたは QUIT コマンドを発行すると、Oracle はトランザクションをコ
ミットします。ROLLBACK 文を実行するか SQL*Plus セッションを中断すると、Oracle はトラ
ンザクションをロールバックします。
SET TRANSACTION を使用したトランザクション・プロパティの設定
SET TRANSACTION 文を使用すると、読取り専用または読取り / 書込みトランザクションの開
始、分離レベルの確立、指定したロールバック・セグメントへのカレント・トランザクション
の割当てができます。読取り専用トランザクションは、他のユーザーが更新している表に対し
て複数の問合せを実行する場合に便利です。
読取り専用トランザクションでは、複数の表と複数の問合せで構成された読取り一貫性のある
ビューが作成され、すべての問合せがデータベースの同一のスナップショットを参照します。
他のユーザーは、通常の方法でデータの問合せや更新ができます。コミットまたはロールバッ
クするとトランザクションが終了します。例 6-40 では、スーパーマーケットの店長が、読取り
専用トランザクションを使用して、当日、先週および先月の注文総数を調べています。トラン
ザクションの途中で他のユーザーがデータベースを更新しても、注文総数には影響がありませ
ん。
例 6-40 SET TRANSACTION を使用した読取り専用トランザクションの開始
DECLARE
daily_order_total NUMBER(12,2);
weekly_order_total NUMBER(12,2);
monthly_order_total NUMBER(12,2);
BEGIN
COMMIT; -- ends previous transaction
SET TRANSACTION READ ONLY NAME 'Calculate Order Totals';
SELECT SUM (order_total) INTO daily_order_total FROM orders
WHERE order_date = SYSDATE;
SELECT SUM (order_total) INTO weekly_order_total FROM orders
WHERE order_date = SYSDATE - 7;
SELECT SUM (order_total) INTO monthly_order_total FROM orders
WHERE order_date = SYSDATE - 30;
COMMIT; -- ends read-only transaction
END;
/
SET TRANSACTION 文は、読取り専用トランザクションの最初の SQL 文である必要があり、1
つのトランザクションで 1 回しか使用できません。トランザクションを READ ONLY に設定する
と、それ以降の問合せからはトランザクションの開始前にコミットされた変更内容しか見えま
せん。READ ONLY を使用しても、他のユーザーや他のトランザクションには影響がありませ
ん。
SET TRANSACTION の制限
読取り専用トランザクションに使用できるのは、SELECT INTO、OPEN、FETCH、CLOSE、
LOCK TABLE、COMMIT および ROLLBACK 文のみです。問合せは FOR UPDATE にはできません。
6-32
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL におけるトランザクション処理の概要
デフォルトのロックの上書き
デフォルトで、Oracle はデータ構造を自動的にロックします。これは Oracle データベースの最
も重要なメリットです。様々なアプリケーションでは、相互のデータに悪影響を与えたりデー
タを同調させることなく、同じデータの読取りおよび書込みを実行できます。
デフォルトのロックを上書きする必要がある場合は、特定の行や表全体のデータ・ロックを要
求できます。明示的なロックによって、トランザクション中の表に対するアクセスを拒否でき
ます。
■
■
LOCK TABLE 文を使用すると、明示的に表全体をロックできます。
SELECT FOR UPDATE 文を使用すると、表の特定の行を明示的にロックし、行を読み取った
後に行が変更されないようにできます。この方法によって、文を発行する前に、UPDATE
文または DELETE 文が影響を与える行およびその数を確認できます。この間、他のアプリ
ケーションは行を変更できません。
FOR UPDATE の使用
UPDATE 文または DELETE 文の CURRENT OF 句で参照されるカーソルを宣言する場合は、FOR
UPDATE 句を使用して排他的な行ロックを取得する必要があります。次に例を示します。
DECLARE
CURSOR c1 IS SELECT employee_id, salary FROM employees
WHERE job_id = 'SA_REP' AND commission_pct > .10
FOR UPDATE NOWAIT;
SELECT ... FOR UPDATE 文は、更新または削除する行を識別し、結果セット内の各行をロック
します。これは、行の中の既存の値に基づいて更新する場合に便利です。この場合、更新の前
に他のユーザーが行を変更しないようにする必要があります。
オプションのキーワード NOWAIT を指定すると、Oracle は他のユーザーが要求された行をロッ
クしていても待機しません。制御はただちにプログラムに戻されるため、他の処理を行ってか
ら、改めてロックを試みてください。キーワード NOWAIT を省略すると、Oracle は行が利用で
きるようになるまで待ちます。
カーソルをオープンしたときにすべての行がロックされるのであり、行がフェッチされるとき
にロックされるのではありません。また、トランザクションをコミットまたはロールバックす
ると、行のロックは解除されます。行がロックされていないため、コミットの後で FOR
UPDATE カーソルからフェッチすることはできません。回避策の詳細は、6-34 ページの「コ
ミットにまたがるフェッチ」を参照してください。
複数の表に対して問合せを実行する場合は、FOR UPDATE 句を使用して、ロックを特定の表に
制限できます。表の行は、FOR UPDATE OF 句でその表の列を参照する場合にのみロックされま
す。たとえば、次の問合せでは表 employees の行はロックされますが、表 departments の
行はロックされません。
DECLARE
CURSOR c1 IS SELECT last_name, department_name FROM employees, departments
WHERE employees.department_id = departments.department_id
AND job_id = 'SA_MAN'
FOR UPDATE OF salary;
カーソルからフェッチされた最新の行を参照するには、例 6-41 に示すように、UPDATE 文また
は DELETE 文で CURRENT OF 句を使用します。
例 6-41 CURRENT OF を使用した、カーソルからフェッチされた最新行の更新
DECLARE
my_emp_id
my_job_id
my_sal
CURSOR c1
BEGIN
OPEN c1;
LOOP
NUMBER(6);
VARCHAR2(10);
NUMBER(8,2);
IS SELECT employee_id, job_id, salary FROM employees FOR UPDATE;
PL/SQL での SQL 操作の実行
6-33
PL/SQL におけるトランザクション処理の概要
FETCH c1 INTO my_emp_id, my_job_id, my_sal;
IF my_job_id = 'SA_REP' THEN
UPDATE employees SET salary = salary * 1.02 WHERE CURRENT OF c1;
END IF;
EXIT WHEN c1%NOTFOUND;
END LOOP;
END;
/
LOCK TABLE の使用
LOCK TABLE 文を使用して、指定されたロック・モードでデータベース表全体をロックすると、
表へのアクセスを共有または拒否できます。行共有ロックでは表に対する同時アクセスができ
ます。つまり、他のユーザーが排他的使用のために表全体をロックしないようにします。表
ロックは、トランザクションがコミットまたはロールバックを発行したときに解除されます。
LOCK TABLE employees IN ROW SHARE MODE NOWAIT;
ロック・モードによって、表に対して他にどのようなロックを使用できるかが決まります。た
とえば、1 つの表に対して多くのユーザーが同時に行共用ロックを取得できますが、排他ロッ
クを取得できるのは一度に 1 人のユーザーのみです。あるユーザーが表に対して排他ロックを
かけていると、他のユーザーはその表に対して行の挿入、更新、削除を実行できません。ロッ
ク・モードの詳細は、
『Oracle Database アプリケーション開発者ガイド - 基礎編』を参照して
ください。
表がロックされていても、他のユーザーは表に対して問合せできますが、問合せを実行しても
表のロックを取得できません。2 つの異なるトランザクションが同じ行を変更した場合のみ、
一方のトランザクションがもう一方のトランザクションの終了を待ちます。
コミットにまたがるフェッチ
コミットの後で FOR UPDATE カーソルからのフェッチを試行すると、PL/SQL によって例外が
呼び出されます。FOR UPDATE 句によって、カーソルをオープンすると行がロックされ、コ
ミットすると行のロックが解除されます。
DECLARE
-- if "FOR UPDATE OF salary" is included on following line, an error is raised
CURSOR c1 IS SELECT * FROM employees;
emp_rec employees%ROWTYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO emp_rec; -- FETCH fails on the second iteration with FOR UPDATE
EXIT WHEN c1%NOTFOUND;
IF emp_rec.employee_id = 105 THEN
UPDATE employees SET salary = salary * 1.05 WHERE employee_id = 105;
END IF;
COMMIT; -- releases locks
END LOOP;
END;
/
複数のコミットにまたがってフェッチする場合は、ROWID 擬似列を使用して CURRENT OF 句と
同じ処理を実行します。各行の ROWID を選択して、UROWID 変数に入れます。その後、更新
や削除のときに、ROWID を使用して現在行を識別します。
例 6-42 ROWID を使用した COMMIT 間のフェッチ
DECLARE
CURSOR c1 IS
my_lastname
my_jobid
my_rowid
BEGIN
6-34
SELECT last_name, job_id, rowid FROM employees;
employees.last_name%TYPE;
employees.job_id%TYPE;
UROWID;
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
自律型トランザクションによる独立した作業単位の実行
OPEN c1;
LOOP
FETCH c1 INTO my_lastname, my_jobid, my_rowid;
EXIT WHEN c1%NOTFOUND;
UPDATE employees SET salary = salary * 1.02 WHERE rowid = my_rowid;
-- this mimics WHERE CURRENT OF c1
COMMIT;
END LOOP;
CLOSE c1;
END;
/
フェッチされた行は、FOR UPDATE 句によってロックされていないため、他のユーザーによっ
て意識せずに変更内容が上書きされる可能性があります。読取り一貫性のために必要な追加領
域は、カーソルがクローズされるまで解放されません。そのため、大規模な更新では処理速度
が低下する場合があります。
ROWID 疑似列を参照するカーソルで %ROWTYPE 属性を使用する例を次に示します。
DECLARE
CURSOR c1 IS SELECT employee_id, last_name, salary, rowid FROM employees;
emp_rec c1%ROWTYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO emp_rec;
EXIT WHEN c1%NOTFOUND;
IF emp_rec.salary = 0 THEN
DELETE FROM employees WHERE rowid = emp_rec.rowid;
END IF;
END LOOP;
CLOSE c1;
END;
/
自律型トランザクションによる独立した作業単位の実行
自律型トランザクションは、別の、メイン・トランザクションによって開始される独立したト
ランザクションです。自律型トランザクションは、メイン・トランザクションをコミットまた
はロールバックせずに、SQL 操作を実行してコミットまたはロールバックします。たとえば、
監査データをログ表に書き込む場合、監査操作が後で失敗しても、監査データをコミットする
必要がある場合があります。すなわち、監査データの記録で問題が発生しても、メイン操作が
ロールバックされないようにする必要があります。
図 6-1 に、メイン・トランザクション(MT)から自律型トランザクション(AT)へ制御がど
のように流れ、また戻るかを示します。
図 6-1 トランザクション制御の流れ
PL/SQL での SQL 操作の実行
6-35
自律型トランザクションによる独立した作業単位の実行
自律型トランザクションのメリット
自律型トランザクションは、開始すると完全に独立します。ロック、リソースまたはコミット
依存関係をメイン・トランザクションと共有することはありません。メイン・トランザクショ
ンがロールバックする場合でも、イベントや増分再試行カウンタなどのログを取ることができ
ます。
さらに重要な点は、自律型トランザクションは再利用可能なソフトウェア・コンポーネントで
あるモジュール構造の作成に役立つということです。自律型トランザクションは、ストアド・
プロシージャ内部でカプセル化できます。コール側のアプリケーションは、そのストアド・プ
ロシージャによって実行された操作が成功したか失敗したかを知る必要はありません。
自律型トランザクションの定義
自律型トランザクションを定義するには、AUTONOMOUS_TRANSACTION プラグマ(コンパイ
ラ・ディレクティブ)を使用します。プラグマはルーチンを自律型(独立型)としてマークす
るように PL/SQL コンパイラに指示します。このコンテキストでは、ルーチンには次のものが
含まれます。
■
トップレベル(ネストしていない)の無名 PL/SQL ブロック
■
ローカル、スタンドアロンおよびパッケージのファンクションとプロシージャ
■
SQL オブジェクト型のメソッド
■
データベース・トリガー
プラグマは、ルーチンの宣言部の任意の場所でコーディングできます。ただし、見やすくする
ために、セクションの先頭にプラグマをコーディングしてください。構文は、PRAGMA
AUTONOMOUS_TRANSACTION です。
例 6-43 では、パッケージ・ファンクションを自律型としてマークします。パッケージのすべて
のサブプログラム(またはオブジェクト型のすべてのメソッド)を自律型としてマークするた
めにプラグマを使用することはできません。自律型としてマークできるのは、個々のルーチン
のみです。
例 6-43 パッケージでの自律型ファンクションの宣言
CREATE OR REPLACE PACKAGE emp_actions AS -- package specification
FUNCTION raise_salary (emp_id NUMBER, sal_raise NUMBER) RETURN NUMBER;
END emp_actions;
/
CREATE OR REPLACE PACKAGE BODY emp_actions AS -- package body
-- code for function raise_salary
FUNCTION raise_salary (emp_id NUMBER, sal_raise NUMBER) RETURN NUMBER IS
PRAGMA AUTONOMOUS_TRANSACTION;
new_sal NUMBER(8,2);
BEGIN
UPDATE employees SET salary = salary + sal_raise WHERE employee_id = emp_id;
COMMIT;
SELECT salary INTO new_sal FROM employees WHERE employee_id = emp_id;
RETURN new_sal;
END raise_salary;
END emp_actions;
/
例 6-44 では、スタンドアロン・プロシージャを自律型としてマークします。
例 6-44 自立型スタンドアロン・プロシージャの宣言
CREATE PROCEDURE lower_salary (emp_id NUMBER, amount NUMBER) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE employees SET salary = salary - amount WHERE employee_id = emp_id;
6-36
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
自律型トランザクションによる独立した作業単位の実行
COMMIT;
END lower_salary;
/
例 6-45 では、PL/SQL ブロックを自律型としてマークします。ただし、ネストした PL/SQL ブ
ロックは自律型としてマークできません。
例 6-45 自律型 PL/SQL ブロックの宣言
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
emp_id NUMBER(6);
amount NUMBER(6,2);
BEGIN
emp_id := 200;
amount := 200;
UPDATE employees SET salary = salary - amount WHERE employee_id = emp_id;
COMMIT;
END;
/
例 6-46 では、データベース・トリガーを自律型としてマークします。通常のトリガーとは異な
り、自律型トリガーには、COMMIT や ROLLBACK などのトランザクション制御文を含めること
ができます。
例 6-46 自律型トリガーの宣言
CREATE TABLE emp_audit ( emp_audit_id NUMBER(6), up_date DATE,
new_sal NUMBER(8,2), old_sal NUMBER(8,2) );
CREATE OR REPLACE TRIGGER audit_sal
AFTER UPDATE OF salary ON employees FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
-- bind variables are used here for values
INSERT INTO emp_audit VALUES( :old.employee_id, SYSDATE,
:new.salary, :old.salary );
COMMIT;
END;
/
自律型トランザクションとネストしたトランザクションの比較
自律型トランザクションは別のトランザクションによって開始されますが、これはネストした
トランザクションではありません。その理由は次のとおりです。
■
■
■
■
ロックなどのトランザクション・リソースをメイン・トランザクションと共有しません。
メイン・トランザクションに依存しません。たとえば、メイン・トランザクションがロー
ルバックする場合は、ネストしたトランザクションがロールバックするのに対し、自律型
トランザクションはロールバックしません。
コミットされた変更を、他のトランザクションからすぐに参照できます。
(ネストしたトラ
ンザクションのコミットされた変更は、メイン・トランザクションがコミットするまで他
のトランザクションからは参照できません。
)
自律型トランザクションで例外が呼び出されると、文レベルのロールバックではなくトラ
ンザクション・レベルのロールバックが発生します。
PL/SQL での SQL 操作の実行
6-37
自律型トランザクションによる独立した作業単位の実行
トランザクション・コンテキスト
メイン・トランザクションはそのコンテキストをネストしたルーチンと共有しますが、自律型
トランザクションとは共有しません。ある自律型ルーチンが別の自律型ルーチンを(または自
身を再帰的に)コールする場合、ルーチンはトランザクション・コンテキストを共有しません。
ある自律型ルーチンが自律型ではないルーチンをコールする場合、ルーチンは同じトランザク
ション・コンテキストを共有します。
トランザクションの可視性
自律型トランザクションによって行われた変更は、自律型トランザクションがコミットすると、
他のトランザクションから参照できるようになります。分離レベルが READ COMMITTED(デ
フォルト)に設定されている場合、メイン・トランザクションが再開すると、これらの変更を
メイン・トランザクションから参照できるようになります。
メイン・トランザクションの分離レベルを SERIALIZABLE に設定すると、その自律型トラン
ザクションによって行われた変更は、再開してもメイン・トランザクションからは参照できま
せん。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
自律型トランザクションの制御
自律型ルーチンの最初の SQL 文でトランザクションが開始されます。1 つのトランザクション
が終了すると、次の SQL 文で別のトランザクションが開始されます。カレント・トランザク
ションは、最後のコミットまたはロールバックよりも後に実行されたすべての SQL 文で構成さ
れます。自律型トランザクションを制御するには、次の文を使用します。これは現在の(アク
ティブな)トランザクションのみに適用されます。
■
COMMIT
■
ROLLBACK [TO savepoint_name]
■
SAVEPOINT savepoint_name
■
SET TRANSACTION
注意 :
■
■
メイン・トランザクションで設定されたトランザクションのプロパ
ティは、そのトランザクションのみに適用され、自律型トランザク
ションには適用されません。逆の場合も同じです。
カーソル属性は自律型トランザクションの影響を受けません。
開始と終了
自律型ルーチンの実行部に入ると、メイン・トランザクションは停止します。ルーチンを終了
すると、メイン・トランザクションは再開します。
正常に終了するには、すべての自律型トランザクションを明示的にコミットまたはロールバッ
クする必要があります。ルーチン(またはそれによってコールされたルーチン)に保留中のト
ランザクションがある場合は、例外が呼び出され、保留中のトランザクションはロールバック
されます。
コミットとロールバック
COMMIT と ROLLBACK はアクティブな自律型トランザクションを終了しますが、自律型ルーチ
ンから抜けるわけではありません。1 つのトランザクションが終了すると、次の SQL 文で別の
トランザクションが開始されます。1 つの自律型ルーチンは、複数の COMMIT 文を発行する場
合、複数の自律型トランザクションを含むことができます。
6-38
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
自律型トランザクションによる独立した作業単位の実行
セーブポイントの使用
セーブポイントの有効範囲は、それが定義されたトランザクションです。メイン・トランザク
ション内で定義されたセーブポイントは、その自律型トランザクション内で定義されたセーブ
ポイントとは無関係です。実際、メイン・トランザクションと自律型トランザクションのセー
ブポイントには、同じ名前を使用できます。
ロールバックできるのは、カレント・トランザクション内でマークされたセーブポイントまで
です。自律型トランザクション内では、メイン・トランザクション内でマークされたセーブポ
イントまではロールバックできません。メイン・トランザクションのセーブポイントまでロー
ルバックするには、自律型ルーチンを抜けてメイン・トランザクションを再開する必要があり
ます。
メイン・トランザクション内では、自律型トランザクションを開始する前にマークされたセー
ブポイントまでロールバックしても、自律型トランザクションはロールバックされません。自
律型トランザクションは、メイン・トランザクションからは完全に独立していることに注意し
てください。
自律型トランザクションでのエラーの回避
一般的なエラーを回避するには、次の事項を考慮してください。
■
■
■
メイン・トランザクションが保持するリソースに、自律型トランザクションがアクセスし
ようとすると、デッドロックが発生します。この場合、Oracle は自律型トランザクション
で例外を呼び出します。例外が未処理になった場合、自律型トランザクションはロール
バックされます。
Oracle 初期化パラメータ TRANSACTIONS は、同時トランザクションの最大数を指定しま
す。自律型トランザクションはメイン・トランザクションと同時に実行されるため、この
最大数を超える場合があります。
コミットまたはロールバックせずにアクティブな自律型トランザクションを終了しようと
すると、Oracle は例外を呼び出します。例外が未処理になった場合、トランザクションは
ロールバックされます。
自律型トリガーの使用
データベース・トリガーを使用してイベントのログを透過的に取ることができます。ある表に
対するすべての挿入を、ロールバックするものも含めて追跡するとします。例 6-47 では、トリ
ガーを使用して、重複する行をシャドウ表に挿入します。トリガーは自律型であるため、メイ
ンの表への変更をコミットするかどうかに関係なく、シャドウ表への変更をコミットできます。
例 6-47 自律型トリガーの使用
CREATE TABLE emp_audit ( emp_audit_id NUMBER(6), up_date DATE,
new_sal NUMBER(8,2), old_sal NUMBER(8,2) );
-- create an autonomous trigger that inserts into the audit table before
-- each update of salary in the employees table
CREATE OR REPLACE TRIGGER audit_sal
BEFORE UPDATE OF salary ON employees FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO emp_audit VALUES( :old.employee_id, SYSDATE,
:new.salary, :old.salary );
COMMIT;
END;
/
-- update the salary of an employee, and then commit the insert
UPDATE employees SET salary = salary * 1.05 WHERE employee_id = 115;
COMMIT;
-- update another salary, then roll back the update
PL/SQL での SQL 操作の実行
6-39
自律型トランザクションによる独立した作業単位の実行
UPDATE employees SET salary = salary * 1.05 WHERE employee_id = 116;
ROLLBACK;
-- show that both committed and rolled-back updates add rows to audit table
SELECT * FROM emp_audit WHERE emp_audit_id = 115 OR emp_audit_id = 116;
通常のトリガーとは異なり、自律型トリガーはシステム固有の動的 SQL を使用して、DDL 文
を実行できます(第 7 章「システム固有の動的 SQL を使用した SQL 操作の実行」を参照)
。次
の例では、表 emp_audit に行が挿入された後に、トリガー drop_temp_table が一時データ
ベース表を削除します。
CREATE TABLE emp_audit ( emp_audit_id NUMBER(6), up_date DATE,
new_sal NUMBER(8,2), old_sal NUMBER(8,2) );
CREATE TABLE temp_audit ( emp_audit_id NUMBER(6), up_date DATE);
CREATE OR REPLACE TRIGGER drop_temp_table
AFTER INSERT ON emp_audit
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE temp_audit';
COMMIT;
END;
/
データベース・トリガーの詳細は、
『Oracle Database アプリケーション開発者ガイド - 基礎編』
を参照してください。
SQL からの自律型ファンクションのコール
SQL 文からコールされるファンクションは、副作用を制御するための特定の規則に従う必要が
あります。8-23 ページの「PL/SQL サブプログラムの副作用の制御」を参照してください。こ
の規則に違反していないかどうかを確認するには、RESTRICT_REFERENCES プラグマを使用で
きます。プラグマは、ファンクションがデータベース表またはパッケージ変数に対する読込み
または書込みを行っていないことを示します。詳細は、
『Oracle Database アプリケーション開
発者ガイド - 基礎編』を参照してください。
ただし、自律型ルーチンの動作に関係なく、データベースに読込み禁止状態(RNDS)および
データベースへの書込み禁止状態(WNDS)の規則に違反しないように定義できます。例 6-48
に示すように、これは便利な機能です。問合せからパッケージ・ファンクション log_msg を
コールすると、データベースへの書込み禁止状態の規則に違反することなく、データベース表
debug_output にメッセージが挿入されます。
例 6-48 自律型ファンクションのコール
-- create the debug table
CREATE TABLE debug_output (msg VARCHAR2(200));
-- create the package spec
CREATE PACKAGE debugging AS
FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2;
PRAGMA RESTRICT_REFERENCES(log_msg, WNDS, RNDS);
END debugging;
/
-- create the package body
CREATE PACKAGE BODY debugging AS
FUNCTION log_msg (msg VARCHAR2) RETURN VARCHAR2 IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
-- the following insert does not violate the constraint
-- WNDS because this is an autonomous routine
INSERT INTO debug_output VALUES (msg);
COMMIT;
6-40
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
自律型トランザクションによる独立した作業単位の実行
RETURN msg;
END;
END debugging;
/
-- call the packaged function from a query
DECLARE
my_emp_id
NUMBER(6);
my_last_name VARCHAR2(25);
my_count
NUMBER;
BEGIN
my_emp_id := 120;
SELECT debugging.log_msg(last_name) INTO my_last_name FROM employees
WHERE employee_id = my_emp_id;
-- even if you roll back in this scope, the insert into 'debug_output' remains
-- committed because it is part of an autonomous transaction
ROLLBACK;
END;
/
PL/SQL での SQL 操作の実行
6-41
自律型トランザクションによる独立した作業単位の実行
6-42
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
7
システム固有の動的 SQL を使用した
SQL 操作の実行
この章では、PL/SQL でシステム固有の動的 SQL(動的 SQL)を使用して、SQL 文を実行時に
記述および処理することによってプログラムをより柔軟に使用できるようにする方法を説明し
ます。
動的 SQL では、データ定義文およびデータ制御文を含む、ほぼすべてのタイプの SQL 文を直
接実行できます。表名、WHERE 句およびその他の情報が事前に不明でも、文を記述できます。
この章の項目は、次のとおりです。
■
PL/SQL で動的 SQL を使用する場合
■
PL/SQL での EXECUTE IMMEDIATE 文の使用
■
PL/SQL でのバルク動的 SQL の使用
■
PL/SQL での動的 SQL 使用のガイドライン
動的 SQL の詳細は、『Oracle Database アプリケーション開発者ガイド - 基礎編』を参照してく
ださい。
システム固有の動的 SQL を使用した SQL 操作の実行
7-1
PL/SQL で動的 SQL を使用する場合
PL/SQL で動的 SQL を使用する場合
動的 SQL を使用すると、SQL 文を実行時に動的に作成できます。コンパイル時に SQL 文が完
全ではない場合があるため、動的 SQL を使用することによってより汎用的で柔軟なアプリケー
ションを作成できます。
動的 SQL 文を処理するには、ほとんどの場合 EXECUTE IMMEDIATE 文を使用します。複数行
の問合せ(SELECT 文)を処理する場合は、OPEN-FOR 文、FETCH 文および CLOSE 文を使用し
ます。
動的 SQL は、次のような場合に必要になります。
■
■
■
SQL データ定義文(CREATE など)、データ制御文(GRANT など)またはセッション制御文
(ALTER SESSION など)を実行する場合。INSERT 文、UPDATE 文および DELETE 文とは
異なり、これらの文は PL/SQL プログラム内に直接含めることができません。
柔軟性が必要な場合。たとえば、スキーマ・オブジェクトの名前をパラメータとしてプロ
シージャに渡す場合があります。また、SELECT 文の WHERE 句に対して異なる検索条件を
記述する場合があります。
列の数、名前またはデータ型が事前に不明な状態で問合せを発行する場合。この場合、
OPEN-FOR 文ではなく DBMS_SQL パッケージを使用します。
古いコードで DBMS_SQL パッケージを使用している場合、この章で説明されているとおり
EXECUTE IMMEDIATE および OPEN-FOR を使用すると、通常パフォーマンスが向上し、コード
が読みやすくなり、オブジェクトおよびコレクションのサポートなどの追加機能が提供されま
す。
動的 SQL と DBMS_SQL の比較は、『Oracle Database アプリケーション開発者ガイド - 基礎編』
を参照してください。DBMS_SQL パッケージの詳細は、『Oracle Database PL/SQL パッケー
ジ・プロシージャおよびタイプ・リファレンス』を参照してください。
注意 : EXECUTE IMMEDIATE および OPEN-FOR 文を使用するシステム固
有の動的 SQL は、DBMS_SQL パッケージよりも高速で、コーディングが
少なくてすみます。ただし、次の場合には DBMS_SQL パッケージを使用す
る必要があります。
■
■
入力変数または出力変数の数(問合せで返される列値の数など)が不
明な場合。動的 SQL 文(動的 SQL のメソッド 4)で使用します。
動的コードが大きすぎて 32K バイト内の VARCHAR2 変数を使用できな
い場合。
PL/SQL での EXECUTE IMMEDIATE 文の使用
EXECUTE IMMEDIATE 文は、動的 SQL 文または無名 PL/SQL ブロックを準備(解析)し、即
時に実行します。EXECUTE IMMEDIATE の主な引数は、実行する SQL 文を含む文字列です。
連結を使用して文字列を記述するか、または事前定義の文字列を使用できます。
複数行の問合せの場合を除いて、動的文字列には任意の SQL 文または任意の PL/SQL ブロック
を含めることができます。また、バインド引数のプレースホルダ(接頭辞にコロンが付いた任
意の名前)を含めることもできます。この場合、INTO 句、USING 句および RETURNING INTO
句を使用して、プレースホルダに対応する PL/SQL 変数を指定します。
動的文字列に単一の SQL 文を記述する場合、引用符の内側の最後にセミコロン(;)を置かな
いでください。無名 PL/SQL ブロックを記述する場合、各 PL/SQL 文の文末および無名ブロッ
クの最後にセミコロンを置きます。文字列リテラルの終了直前、もう一つは終了一重引用符の
後にセミコロンを置くことになります。
プレースホルダは、WHERE 句の条件テストなど、SQL 文の中で変数を置き換えることができる
場所にのみ使用できます。スキーマ・オブジェクトの名前としてプレースホルダを使用するこ
とはできません。正しい方法は、7-8 ページの「パラメータとしてのスキーマ・オブジェクト名
の引渡し」を参照してください。
7-2
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL での EXECUTE IMMEDIATE 文の使用
INTO 句は単一行の問合せの場合に使用され、検索された列の値を入れる変数またはレコードを
指定します。問合せによって取り出された値それぞれに対して、INTO 句の中に、対応する型互
換性変数が存在している必要があります。
RETURNING INTO 句は、RETURNING 句のある(BULK COLLECT 句のない)DML 文の場合にの
み使用され、列の値が戻される変数を指定します。DML 文によって戻された値それぞれに対し
て、RETURNING INTO 句の中に、対応する型互換性変数が存在している必要があります。
バインド引数は、すべて USING 句に入れることができます。デフォルトのパラメータ・モード
は IN です。RETURNING 句を持つ DML 文の場合は、パラメータ・モードを指定しなくても、
OUT 引数を RETURNING INTO 句に入れることができます。USING 句と RETURNING INTO 句の
両方を使用する場合、USING 句には IN 引数のみを含めることができます。
実行時に、バインド引数は動的文字列内の対応するプレースホルダを置き換えます。すべての
プレースホルダを USING 句内または RETURNING INTO 句内(あるいはその両方)のバインド
引数に関連付ける必要があります。数値リテラル、文字リテラルおよび文字列リテラルはバイ
ンド引数として使用できますが、ブール・リテラル(TRUE、FALSE および NULL)は使用でき
ません。動的文字列に NULL を渡すには、回避策を使用する必要があります。7-10 ページの
「動的 SQL への NULL の引渡し」を参照してください。
動的 SQL はすべての SQL データ型をサポートしています。たとえば、定義変数やバインド引
数をコレクション、LOB、オブジェクト型のインスタンスおよび ref とすることができます。
通常、動的 SQL は PL/SQL 固有の型をサポートしていません。たとえば、定義変数やバインド
引数をブールまたは結合配列にすることはできません。例外として、PL/SQL レコードを INTO
句に入れることができます。
動的 SQL 文は、バインド引数の新しい値を使用して繰り返し実行できます。ただし、EXECUTE
IMMEDIATE は実行のたびに動的文字列を準備するため、オーバーヘッドが発生します。
EXECUTE IMMEDIATE の詳細は、13-40 ページの「EXECUTE IMMEDIATE 文」を参照してくだ
さい。
例 7-1 に、動的 SQL の使用例をいくつか示します。
例 7-1 動的 SQL の例
CREATE OR REPLACE PROCEDURE raise_emp_salary (column_value NUMBER,
emp_column VARCHAR2, amount NUMBER) IS
v_column VARCHAR2(30);
sql_stmt VARCHAR2(200);
BEGIN
-- determine if a valid column name has been given as input
SELECT COLUMN_NAME INTO v_column FROM USER_TAB_COLS
WHERE TABLE_NAME = 'EMPLOYEES' AND COLUMN_NAME = emp_column;
sql_stmt := 'UPDATE employees SET salary = salary + :1 WHERE '
|| v_column || ' = :2';
EXECUTE IMMEDIATE sql_stmt USING amount, column_value;
IF SQL%ROWCOUNT > 0 THEN
DBMS_OUTPUT.PUT_LINE('Salaries have been updated for: ' || emp_column
|| ' = ' || column_value);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('Invalid Column: ' || emp_column);
END raise_emp_salary;
/
DECLARE
plsql_block
VARCHAR2(500);
BEGIN
-- note the semi-colons (;) inside the quotes '...'
plsql_block := 'BEGIN raise_emp_salary(:cvalue, :cname, :amt); END;';
EXECUTE IMMEDIATE plsql_block USING 110, 'DEPARTMENT_ID', 10;
EXECUTE IMMEDIATE 'BEGIN raise_emp_salary(:cvalue, :cname, :amt); END;'
システム固有の動的 SQL を使用した SQL 操作の実行
7-3
PL/SQL での EXECUTE IMMEDIATE 文の使用
USING 112, 'EMPLOYEE_ID', 10;
END;
/
DECLARE
sql_stmt
VARCHAR2(200);
v_column
VARCHAR2(30) := 'DEPARTMENT_ID';
dept_id
NUMBER(4) := 46;
dept_name
VARCHAR2(30) := 'Special Projects';
mgr_id
NUMBER(6) := 200;
loc_id
NUMBER(4) := 1700;
BEGIN
-- note that there is no semi-colon (;) inside the quotes '...'
EXECUTE IMMEDIATE 'CREATE TABLE bonus (id NUMBER, amt NUMBER)';
sql_stmt := 'INSERT INTO departments VALUES (:1, :2, :3, :4)';
EXECUTE IMMEDIATE sql_stmt USING dept_id, dept_name, mgr_id, loc_id;
EXECUTE IMMEDIATE 'DELETE FROM departments WHERE ' || v_column || ' = :num'
USING dept_id;
EXECUTE IMMEDIATE 'ALTER SESSION SET SQL_TRACE TRUE';
EXECUTE IMMEDIATE 'DROP TABLE bonus';
END;
/
例 7-2 では、スタンドアロン・プロシージャはデータベース表の名前とオプションの WHERE 句
条件を受け入れます。条件を省略すると、プロシージャは表の中のすべての行を削除します。
条件が省略されていなければ、プロシージャは条件を満たす行のみを削除します。
例 7-2 表名および WHERE 句を受け入れる動的 SQL プロシージャ
CREATE TABLE employees_temp AS SELECT * FROM employees;
CREATE OR REPLACE PROCEDURE delete_rows (
table_name IN VARCHAR2,
condition IN VARCHAR2 DEFAULT NULL) AS
where_clause VARCHAR2(100) := ' WHERE ' || condition;
v_table
VARCHAR2(30);
BEGIN
-- first make sure that the table actually exists; if not, raise an exception
SELECT OBJECT_NAME INTO v_table FROM USER_OBJECTS
WHERE OBJECT_NAME = UPPER(table_name) AND OBJECT_TYPE = 'TABLE';
IF condition IS NULL THEN where_clause := NULL; END IF;
EXECUTE IMMEDIATE 'DELETE FROM ' || v_table || where_clause;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('Invalid table: ' || table_name);
END;
/
BEGIN
delete_rows('employees_temp', 'employee_id = 111');
END;
/
動的 SQL 文字列におけるバインド変数のパラメータ・モードの指定
USING 句を使用すると、モードはデフォルトで IN に設定されるため、入力バインド引数のパ
ラメータ・モードを指定する必要はありません。
RETURNING INTO 句を使用すると、パラメータ・モードは OUT になるため、出力バインド引数
のパラメータ・モードを指定できません。
7-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL でのバルク動的 SQL の使用
次のようにより複雑な場合は、パラメータ・モードを指定する必要があります。ここでは、動
的 PL/SQL ブロックからプロシージャをコールしています。
CREATE PROCEDURE create_dept (
deptid IN OUT NUMBER,
dname IN VARCHAR2,
mgrid IN NUMBER,
locid IN NUMBER) AS
BEGIN
SELECT departments_seq.NEXTVAL INTO deptid FROM dual;
INSERT INTO departments VALUES (deptid, dname, mgrid, locid);
END;
/
動的 PL/SQL ブロックからプロシージャをコールするには、例 7-3 で示すように、仮パラメー
タ deptid に対応付けられたバインド引数に、IN OUT モードを指定する必要があります。
例 7-3 IN OUT バインド引数を使用した置換の指定
DECLARE
plsql_block VARCHAR2(500);
new_deptid NUMBER(4);
new_dname VARCHAR2(30) := 'Advertising';
new_mgrid NUMBER(6) := 200;
new_locid NUMBER(4) := 1700;
BEGIN
plsql_block := 'BEGIN create_dept(:a, :b, :c, :d); END;';
EXECUTE IMMEDIATE plsql_block
USING IN OUT new_deptid, new_dname, new_mgrid, new_locid;
END;
/
PL/SQL でのバルク動的 SQL の使用
バルク SQL では、個々の要素ではなくコレクション全体がやり取りされます。この手法では、
PL/SQL エンジンと SQL エンジンの間のコンテキスト切替えの回数を最小限に抑えることに
よって、パフォーマンスを向上させます。すべての反復で SQL 文を発行するループではなく、
1 つの文を使用できます。
次のコマンド、句およびカーソル属性を使用すると、アプリケーションでバルク SQL 文を作成
して、実行時に動的に実行できます。
BULK FETCH 文
BULK EXECUTE IMMEDIATE 文
FORALL 文
COLLECT INTO 句
RETURNING INTO 句
%BULK_ROWCOUNT カーソル属性
前述の文、句およびカーソル属性の静的バージョンについては、11-8 ページの「バルク SQL に
よる、DML 文および問合せのループ・オーバーヘッドの削減」を参照してください。背景情報
も記載されています。
動的 SQL とバルク SQL の使用
バルク・バインドを使用すると、SQL 文の変数を値のコレクションにバインドできます。コレ
クション型には、任意の PL/SQL コレクション型(索引付き表、ネストした表または
VARRAY)を使用できます。コレクション要素には、CHAR、DATE、NUMBER などの SQL デー
タ型が必要です。バルク動的バインドがサポートされる文は、EXECUTE IMMEDIATE、FETCH
および FORALL です。
システム固有の動的 SQL を使用した SQL 操作の実行
7-5
PL/SQL でのバルク動的 SQL の使用
EXECUTE IMMEDIATE
EXECUTE IMMEDIATE 文に BULK COLLECT INTO 句を使用すると、問合せの結果セットの各
列の値を個別のコレクションに格納できます。
EXECUTE IMMEDIATE 文に RETURNING BULK COLLECT INTO 句を使用すると、INSERT 文、
UPDATE 文または DELETE 文の結果をコレクション・セットに格納できます。
FETCH
FETCH 文に BULK COLLECT INTO 句を使用すると、カーソルの各列からフェッチした値を個
別のコレクションに格納できます。
FORALL
FORALL 文には、EXECUTE IMMEDIATE 文に RETURNING BULK COLLECT INTO を指定して含
めることができます。INSERT 文、UPDATE 文または DELETE 文のすべての結果を、コレク
ション・セットに格納できます。
USING 句を使用して、EXECUTE IMMEDIATE 文に添字付きのコレクション要素を渡すことが
できます。添字付きの要素は、EXECUTE IMMEDIATE の文字列引数に直接連結できません。た
とえば、表名のコレクションを構築し、それぞれの反復が異なる表に適用される FORALL 文を
記述することはできません。
バルク動的バインドの例
この項では動的バルクのバインの例を示します。BULK COLLECT INTO 句を使用して、動的問
合せの定義変数をバインドできます。例 7-4 で示すように、この句をバルク FETCH 文またはバ
ルク EXECUTE IMMEDIATE 文に使用できます。
例 7-4 BULK COLLECT INTO 句を使用した動的 SQL
DECLARE
TYPE EmpCurTyp IS REF CURSOR;
TYPE NumList IS TABLE OF NUMBER;
TYPE NameList IS TABLE OF VARCHAR2(25);
emp_cv EmpCurTyp;
empids NumList;
enames NameList;
sals NumList;
BEGIN
OPEN emp_cv FOR 'SELECT employee_id, last_name FROM employees';
FETCH emp_cv BULK COLLECT INTO empids, enames;
CLOSE emp_cv;
EXECUTE IMMEDIATE 'SELECT salary FROM employees'
BULK COLLECT INTO sals;
END;
/
出力バインド変数を使用できるのは、INSERT、UPDATE および DELETE 文のみです。例 7-5 で
示すように、EXECUTE IMMEDIATE 文に RETURNING BULK COLLECT INTO 句を指定して、変
数をバルク・バインドします。
例 7-5 RETURNING BULK COLLECT INTO 句を使用した動的 SQL
DECLARE
TYPE NameList IS TABLE OF VARCHAR2(15);
enames
NameList;
bonus_amt NUMBER := 50;
sql_stmt VARCHAR(200);
BEGIN
sql_stmt := 'UPDATE employees SET salary = salary + :1
RETURNING last_name INTO :2';
EXECUTE IMMEDIATE sql_stmt
7-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL での動的 SQL 使用のガイドライン
USING bonus_amt RETURNING BULK COLLECT INTO enames;
END;
/
SQL 文中で入力変数をバインドするには、例 7-6 で示すように、FORALL 文と USING 句を使用
できます。SQL 文を問合せにすることはできません。
例 7-6 FORALL 文中の動的 SQL
DECLARE
TYPE NumList IS TABLE OF NUMBER;
TYPE NameList IS TABLE OF VARCHAR2(15);
empids NumList;
enames NameList;
BEGIN
empids := NumList(101,102,103,104,105);
FORALL i IN 1..5
EXECUTE IMMEDIATE
'UPDATE employees SET salary = salary * 1.04 WHERE employee_id = :1
RETURNING last_name INTO :2'
USING empids(i) RETURNING BULK COLLECT INTO enames;
END;
/
PL/SQL での動的 SQL 使用のガイドライン
この項では、動的 SQL を十分に活用する方法、および頻繁に発生する問題を回避する方法につ
いて説明します。
注意 : PL/SQL で動的 SQL を使用する場合は、SQL インジェクションの
リスクを認識しておく必要があります。SQL インジェクションによって、
セキュリティの問題が発生する可能性があります。SQL インジェクション
および発生する可能性がある問題の詳細は、
『Oracle Database アプリケー
ション開発者ガイド - 基礎編』を参照してください。SQL インジェクショ
ンについては、Oracle Technology Network の
http://www.oracle.com/technology で検索することもできます。
動的 SQL を使用した動的問合せの構築
動的な複数行の問合せを処理するには、OPEN-FOR 文、FETCH 文および CLOSE 文の 3 つの文
を使用します。まず、OPEN-FOR 文でカーソル変数を複数行問合せ用にオープンします。次に、
FETCH 文で結果セットから一度に 1 行ずつ行を取り出します。すべての行が処理された後に、
CLOSE 文でカーソル変数をクローズします。カーソル変数の詳細は、6-19 ページの「カーソル
変数(REF CURSOR)の使用」を参照してください。
動的 SQL でのセミコロンの使用または省略
単一の SQL 文を 1 つの文字列として記述する場合、文末にセミコロンを置かないでください。
無名 PL/SQL ブロックを記述する場合、各 PL/SQL 文の文末および無名ブロックの最後にセミ
コロンを置きます。次に例を示します。
BEGIN
EXECUTE IMMEDIATE 'BEGIN DBMS_OUTPUT.PUT_LINE(''semicolons''); END;';
END;
/
システム固有の動的 SQL を使用した SQL 操作の実行
7-7
PL/SQL での動的 SQL 使用のガイドライン
バインド変数を使用した動的 SQL のパフォーマンスの向上
PL/SQL に INSERT 文、UPDATE 文、DELETE 文および SELECT 文を直接コーディングすると、
PL/SQL は、これらの文が SQL で効率的に動作するように、変数を自動的にバインド変数に変
換します。このような文を動的 SQL に記述した場合、同等のパフォーマンスを得るには、自分
でバインド変数を指定する必要があります。
次の例では、Oracle は emp_id の個別値ごとに異なるカーソルをオープンしています。この場
合、各文が解析およびキャッシュされるため、リソースの競合およびパフォーマンスの低下が
発生する可能性があります。
CREATE PROCEDURE fire_employee (emp_id NUMBER) AS
BEGIN
EXECUTE IMMEDIATE
'DELETE FROM employees WHERE employee_id = ' || TO_CHAR(emp_id);
END;
/
バインド変数を使用すると、パフォーマンスが向上します。これによって、Oracle は emp_id
の異なる値に対して同じカーソルを再利用できるようになります。
CREATE PROCEDURE fire_employee (emp_id NUMBER) AS
BEGIN
EXECUTE IMMEDIATE
'DELETE FROM employees WHERE employee_id = :id' USING emp_id;
END;
/
パラメータとしてのスキーマ・オブジェクト名の引渡し
任意のデータベース表の名前を受け入れ、その表をスキーマから削除するプロシージャが必要
だとします。この場合、オブジェクト名を含む文で文字列を記述し、EXECUTE IMMEDIATE を
使用してその文を実行する必要があります。
CREATE TABLE employees_temp AS SELECT last_name FROM employees;
CREATE PROCEDURE drop_table (table_name IN VARCHAR2) AS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || table_name;
END;
/
USING 句を使用して、表名をバインド変数として渡すのではなく、連結を使用して文字列を記
述します。
さらに、名前が実行時まで不明なプロシージャをコールする必要がある場合は、そのプロシー
ジャを指定するパラメータを渡すことができます。たとえば、次のプロシージャでは、実行時
にプロシージャ名を指定して、別のプロシージャ(drop_table)をコールできます。
CREATE PROCEDURE run_proc (proc_name IN VARCHAR2, table_name IN VARCHAR2) AS
BEGIN
EXECUTE IMMEDIATE 'CALL "' || proc_name || '" ( :proc_name )' using table_name;
END;
/
drop_table で表を削除する場合は、次のようにプロシージャを実行できます。プロシージャ
名が大文字である点に注意してください。
CREATE TABLE employees_temp AS SELECT last_name FROM employees;
BEGIN
run_proc('DROP_TABLE', 'employees_temp');
END;
/
7-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL での動的 SQL 使用のガイドライン
動的 SQL での重複するプレースホルダの使用
動的 SQL 文のプレースホルダは、USING 句内のバインド引数に、名前ではなく位置によって対
応付けられます。プレースホルダの順序を、:a、:a、:b、:b のように指定した場合、USING
句に 4 つの項目を含める必要があります。たとえば、次のような動的文字列があるとします。
sql_stmt := 'INSERT INTO payroll VALUES (:x, :x, :y, :x)';
x という名前が繰り返されていることは重要ではありません。4 つの異なるバインド変数を使用
して、対応する USING 句をコーディングできます。
EXECUTE IMMEDIATE sql_stmt USING a, a, b, a;
動的 SQL 文が PL/SQL ブロックを表している場合、重複するプレースホルダには異なる規則が
適用されます。一意の各プレースホルダは、USING 句の 1 つの項目にマップされます。同じプ
レースホルダが 2 回以上指定されている場合、その名前に対するすべての参照が USING 句内の
1 つのバインド引数に対応します。例 7-7 では、プレースホルダ x に対するすべての参照が最
初のバインド引数 a に対応し、2 番目の一意のプレースホルダ y が 2 番目のバインド引数 b に
対応しています。
例 7-7 動的 SQL での重複するプレースホルダの使用
CREATE PROCEDURE calc_stats(w NUMBER, x NUMBER, y NUMBER, z NUMBER) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(w + x + y + z);
END;
/
DECLARE
a NUMBER := 4;
b NUMBER := 7;
plsql_block VARCHAR2(100);
BEGIN
plsql_block := 'BEGIN calc_stats(:x, :x, :y, :x); END;';
EXECUTE IMMEDIATE plsql_block USING a, b;
END;
/
動的 SQL でのカーソル属性の使用
SQL のカーソル属性 %FOUND、%ISOPEN、%NOTFOUND および %ROWCOUNT は、動的 SQL の中
で INSERT 文、UPDATE 文、DELETE 文または 1 行の SELECT 文を発行した場合に機能します。
BEGIN
EXECUTE IMMEDIATE 'DELETE FROM employees WHERE employee_id > 1000';
DBMS_OUTPUT.PUT_LINE('Number of employees deleted: ' || TO_CHAR(SQL%ROWCOUNT));
END;
/
同様に、カーソル変数名にカーソル属性を追加すると、複数行の問合せの実行に関する情報が
戻されます。
例 7-8 明示カーソルの %ROWCOUNT へのアクセス
DECLARE
TYPE cursor_ref IS REF CURSOR;
c1 cursor_ref;
TYPE emp_tab IS TABLE OF employees%ROWTYPE;
rec_tab emp_tab;
rows_fetched NUMBER;
BEGIN
OPEN c1 FOR 'SELECT * FROM employees';
FETCH c1 BULK COLLECT INTO rec_tab;
システム固有の動的 SQL を使用した SQL 操作の実行
7-9
PL/SQL での動的 SQL 使用のガイドライン
rows_fetched := c1%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE('Number of employees fetched: ' || TO_CHAR(rows_fetched));
END;
/
カーソル属性の詳細は、6-6 ページの「PL/SQL でのカーソルの管理」を参照してください。
動的 SQL への NULL の引渡し
リテラル NULL は、USING 句の中では使用できません。この制限を回避するには、キーワード
NULL を未初期化の変数で置き換えます。
CREATE TABLE employees_temp AS SELECT * FROM EMPLOYEES;
DECLARE
a_null CHAR(1); -- set to NULL automatically at run time
BEGIN
EXECUTE IMMEDIATE 'UPDATE employees_temp SET commission_pct = :x' USING a_null;
END;
/
動的 SQL でのデータベース・リンクの使用
PL/SQL サブプログラムは、データベース・リンクを使用してリモート・データベースにある
オブジェクトを参照する動的 SQL 文を実行できます。
CREATE PROCEDURE delete_dept (db_link VARCHAR2, dept_id INTEGER) IS
BEGIN
EXECUTE IMMEDIATE 'DELETE FROM departments@' || db_link ||
' WHERE department_id = :num' USING dept_id;
END;
/
-- delete department id 41 in the departments table on the remote DB hr_db
CALL delete_dept('hr_db', 41);
リモート・プロシージャ・コール(RPC)のターゲットは、動的 SQL 文を含むことができま
す。たとえば、表内の行の数を戻す次のスタンドアロン・ファンクションが、ロンドンの
hr_db データベースに常駐するとします。
CREATE FUNCTION row_count (tab_name VARCHAR2) RETURN NUMBER AS
rows NUMBER;
BEGIN
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || tab_name INTO rows;
RETURN rows;
END;
/
-- From an anonymous block, you might call the function remotely, as follows:
DECLARE
emp_count INTEGER;
BEGIN
emp_count := row_count@hr_db('employees');
DBMS_OUTPUT.PUT_LINE(emp_count);
END;
/
7-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL での動的 SQL 使用のガイドライン
動的 SQL での実行者権限の使用
動的 SQL を使用すると、スキーマ管理プロシージャを記述できます。このプロシージャは、1
つのスキーマ内に集中させ、他のスキーマからコールしたり、他のスキーマ内のオブジェクト
に対して操作を実行することができます。たとえば、このプロシージャを使用して、すべての
種類のデータベース・オブジェクトを削除できます。
CREATE OR REPLACE PROCEDURE drop_it (kind IN VARCHAR2, name IN VARCHAR2)
AUTHID CURRENT_USER AS
BEGIN
EXECUTE IMMEDIATE 'DROP ' || kind || ' ' || name;
END;
/
このプロシージャが、HR スキーマの一部であると想定します。AUTHID 句を指定しない場合、
プロシージャは、どのスキーマからコールされたかにかかわらず常に HR スキーマ内のオブ
ジェクトを削除します。オブジェクトの完全修飾名を渡した場合でも、このプロシージャは他
のスキーマを変更する権限を持ちません。
AUTHID 句を使用することで、これらの制限を回避できます。これによって、プロシージャは
起動したユーザーの権限で実行され、未修飾の参照はそのスキーマ内のオブジェクトを参照し
ます。
詳細は、8-15 ページの「実行者権限と定義者権限の使用(AUTHID 句)
」を参照してください。
動的 SQL での RESTRICT_REFERENCES プラグマの使用
SQL 文からコールされるファンクションは、副作用を制御するための特定の規則に従う必要が
あります。
(8-23 ページの「PL/SQL サブプログラムの副作用の制御」を参照。
)この規則に違
反していないかどうかを確認するには、RESTRICT_REFERENCES プラグマを使用できます。プ
ラグマは、ファンクションがデータベース表またはパッケージ変数に対する読込みまたは書込
みを行っていないことを示します(詳細は、
『Oracle Database アプリケーション開発者ガイド 基礎編』を参照。
)
ファンクション本体に動的 INSERT 文、UPDATE 文または DELETE 文が含まれている場合、そ
のファンクションは常にデータベースへの書込み禁止状態(WNDS)およびデータベースに読込
み禁止状態(RNDS)の規則に違反します。PL/SQL では、これらの副作用を自動的に検出でき
ません。これは、動的 SQL 文がコンパイル時ではなく実行時にチェックされるためです。
EXECUTE IMMEDIATE 文内では、INTO 句のみがコンパイル時に RNDS の規則に違反していない
かどうかがチェックされます。
動的 SQL でのデッドロックの回避
まれに、SQL データ定義文の実行によってデッドロックが発生することがあります。たとえ
ば、次のプロシージャは自身を削除しようとしているため、デッドロックが発生します。デッ
ドロックを回避するには、サブプログラムまたはパッケージを、使用中に ALTER で変更した
り、DROP で削除しないでください。
CREATE OR REPLACE PROCEDURE calc_bonus (emp_id NUMBER) AS
BEGIN
EXECUTE IMMEDIATE 'DROP PROCEDURE calc_bonus'; -- deadlock!
END;
/
USING 句の下位互換性
動的 INSERT 文、UPDATE 文または DELETE 文に RETURNING 句がある場合、出力バインド引
数を RETURNING INTO 句または USING 句に入れることができます。新しいアプリケーション
では、RETURNING INTO 句を使用します。古いアプリケーションでは、USING 句を引き続き使
用できます。
システム固有の動的 SQL を使用した SQL 操作の実行
7-11
PL/SQL での動的 SQL 使用のガイドライン
PL/SQL のレコードおよびコレクションでの動的 SQL の使用
レコードおよびコレクションで動的 SQL を使用できます。例 7-9 で示すように、動的な複数行
の問合せの結果セットから行をフェッチしてレコードに入れることができます。
例 7-9 レコードへの動的 SQL フェッチ
DECLARE
TYPE EmpCurTyp IS REF CURSOR;
emp_cv EmpCurTyp;
emp_rec employees%ROWTYPE;
sql_stmt VARCHAR2(200);
v_job VARCHAR2(10) := 'ST_CLERK';
BEGIN
sql_stmt := 'SELECT * FROM employees WHERE job_id = :j';
OPEN emp_cv FOR sql_stmt USING v_job;
LOOP
FETCH emp_cv INTO emp_rec;
EXIT WHEN emp_cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Name: ' || emp_rec.last_name || ' Job Id: ' ||
emp_rec.job_id);
END LOOP;
CLOSE emp_cv;
END;
/
オブジェクト型を使用した動的 SQL の使用例は、12-11 ページの「オブジェクトでの動的 SQL
の使用」を参照してください。
7-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
8
PL/SQL のサブプログラムの使用
この章では、文の集合を、再利用可能なサブプログラムとして作成する方法について説明しま
す。サブプログラムは、メンテナンスしやすいモジュール構造のアプリケーションを構成する
ビルディング・ブロックと似ています。
この章の項目は、次のとおりです。
■
サブプログラム
■
PL/SQL サブプログラムのメリット
■
PL/SQL プロシージャ
■
PL/SQL ファンクション
■
ネストした PL/SQL サブプログラムの宣言
■
PL/SQL サブプログラムへのパラメータの引渡し
■
サブプログラム名のオーバーロード
■
サブプログラムのコールの解決方法
■
実行者権限と定義者権限の使用(AUTHID 句)
■
PL/SQL での再帰の使用
■
外部サブプログラムのコール
■
PL/SQL サブプログラムの副作用の制御
■
サブプログラムのパラメータのエイリアシングの理解
PL/SQL のサブプログラムの使用
8-1
サブプログラム
サブプログラム
サブプログラムは、パラメータの組を指定してコールできる、名前の付けられた PL/SQL ブ
ロックです。PL/SQL にはプロシージャとファンクションの 2 種類のサブプログラムがありま
す。一般に、プロシージャはアクションを実行するために使用し、ファンクションは値を計算
するために使用します。
無名ブロックと同様に、サブプログラムは次の部分から構成されます。
■
宣言部 : 型、カーソル、定数、変数、例外およびネストされたサブプログラムを宣言しま
す。これらの項目はローカルで、サブプログラムを終了すると消去されます。
■
実行部 : 値の代入、実行の制御および Oracle データの操作を実行する文があります。
■
オプションの例外処理部 : ランタイム・エラー状態を処理します。
例 8-1 に、入力パラメータと出力パラメータの両方を受け取り、潜在的なエラーを処理する文
字列操作プロシージャ double の例を示します。
例 8-1 単純な PL/SQL プロシージャ
DECLARE
in_string VARCHAR2(100) := 'This is my test string.';
out_string VARCHAR2(200);
PROCEDURE double ( original IN VARCHAR2, new_string OUT VARCHAR2 ) AS
BEGIN
new_string := original || ' + ' || original;
EXCEPTION
WHEN VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('Output buffer not long enough.');
END;
BEGIN
double(in_string, out_string);
DBMS_OUTPUT.PUT_LINE(in_string || ' - ' || out_string);
END;
/
例 8-2 に、一時的な結果を保持するローカル変数を宣言し、終了時に値を戻す数値ファンク
ション square を示します。
例 8-2 単純な PL/SQL ファンクション
DECLARE
FUNCTION square(original NUMBER)
RETURN NUMBER AS original_squared NUMBER;
BEGIN
original_squared := original * original;
RETURN original_squared;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE(square(100));
END;
/
8-2
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL プロシージャ
注意 :
■
■
■
SQL の CREATE FUNCTION 文を使用すると、Oracle データベースに格
納するスタンドアロン・ファンクションを作成できます。詳細は、
『Oracle Database SQL リファレンス』の「CREATE FUNCTION」を参
照してください。
SQL の CREATE PROCEDURE 文を使用すると、データベースに格納す
るスタンドアロン・プロシージャを作成できます。詳細は、
『Oracle
Database SQL リファレンス』の「CREATE PROCEDURE」を参照して
ください。
CREATE FUNCTION 文または CREATE PROCEDURE 文は、SQL*Plus ま
たはシステム固有の動的 SQL を使用したプログラムから対話式で実
行できます。第 7 章「システム固有の動的 SQL を使用した SQL 操作
の実行」を参照してください。
PL/SQL サブプログラムのメリット
サブプログラムを使用すると、PL/SQL 言語を拡張できます。プロシージャは新しい文のよう
に機能します。ファンクションは新しい式および演算子のように機能します。
サブプログラムを使用すると、プログラムを管理の容易な、正しく定義されたモジュールに分
けることができます。この特性を利用すると、トップダウン設計と段階的詳細化アプローチに
よって問題を解決できます。
サブプログラムによって、再利用性が向上します。テスト済のサブプログラムは、いくつもの
アプリケーションで再利用できます。PL/SQL サブプログラムは、多くの異なる環境からコー
ルできます。そのため、新しい言語または API を使用してデータベースにアクセスするたびに
サブプログラムを最初から作成しなおす必要はありません。
サブプログラムによって、メンテナンス性が向上します。コール元のサブプログラムを変更す
ることなく、サブプログラムの内部を変更できます。パッケージやオブジェクト型などの、メ
ンテナンス性を向上する他の機能においても、サブプログラムは重要な役割を果たします。
ダミーのサブプログラム(スタブ)を使用すると、メイン・プログラムのテストが終了するま
で、プロシージャまたはファンクションを定義しないで済ますことができます。処理の詳細に
とらわれることなく、抽象的な思考方法によるトップダウン手法でアプリケーションを設計で
きます。
PL/SQL サブプログラムを使用して API を定義する場合は、サブプログラムを PL/SQL パッ
ケージにグループ化することで、コードをさらに再利用しやすく、メンテナンス性の高いもの
にできます。パッケージの詳細は、第 9 章「PL/SQL パッケージの使用」を参照してください。
PL/SQL プロシージャ
プロシージャとは、特定のアクションを実行するサブプログラムのことです。プロシージャの
名前、パラメータ、ローカル変数および BEGIN-END ブロック(コードを含み、例外を処理す
る)を指定します。PROCEDURE 宣言の構文は、13-89 ページの「プロシージャ宣言」を参照し
てください。
各パラメータでは、次の内容を指定します。
■
■
名前。
パラメータ・モード(IN、OUT または IN OUT)
。パラメータ・モードを省略した場合、デ
フォルトは IN です。オプションの NOCOPY キーワードを指定すると、サイズの大きい
OUT パラメータまたは IN OUT パラメータの処理がスピードアップします。
■
データ型。型のみを指定し、長さや精度の制約は指定しません。
■
デフォルト値(オプション)
。
PL/SQL のサブプログラムの使用
8-3
PL/SQL ファンクション
プロシージャの実行時に、プロシージャを定義したユーザーのスキーマおよび権限を使用する
か、プロシージャをコールするユーザーのスキーマおよび権限を使用するかを指定できます。
詳細は、8-15 ページの「実行者権限と定義者権限の使用(AUTHID 句)
」を参照してください。
プロシージャをカレント・トランザクションの一部として実行するか、コール元のトランザク
ションを終了することなくプロシージャ自身のトランザクションで COMMIT または ROLLBACK
を実行するかを指定できます。詳細は、6-35 ページの「自律型トランザクションによる独立し
た作業単位の実行」を参照してください。
プロシージャには、仕様部と本体の 2 つの部分があります。プロシージャの仕様部は、キー
ワード PROCEDURE で始め、プロシージャ名またはパラメータ・リストで終わり、その後に予
約語 IS(または AS)が続きます。パラメータ宣言はオプションです。パラメータを取らない
プロシージャではカッコを書きません。
プロシージャの本体は、予約語 IS(または AS)で始め、キーワード END で終わります。END
の後には、オプションとしてプロシージャ名を続けることができます。プロシージャの本体に
は、宣言部、実行部、例外処理部(オプション)の 3 つの部分があります。
宣言部では、ローカル宣言を置きます。無名 PL/SQL ブロックで使用するキーワード
DECLARE は、プロシージャでは使用しません。実行部では、キーワード BEGIN と EXCEPTION
(または END)の間に文を置きます。プロシージャの実行部には、少なくとも 1 つの文が存在し
ている必要があります。NULL 文を使用すると、プレースホルダ・プロシージャを定義したり、
プロシージャでアクションを実行しないように指定できます。例外処理部では、キーワード
EXCEPTION と END の間に例外ハンドラを置きます。
プロシージャは PL/SQL 文としてコールされます。たとえば、プロシージャ raise_salary
は次のようにしてコールできます。
raise_salary(emp_id, amount);
PL/SQL ファンクション
ファンクションとは、値を計算するサブプログラムのことです。ファンクションとプロシー
ジャは同じような構造を持ちますが、ファンクションの方は RETURN 句を持っています。ファ
ンクションには多くのオプションのキーワードがあり、テーブル・ファンクションと呼ばれる
特別なファンクションのクラスを宣言するために使用されます。通常、これらのキーワードは、
データ・ウェアハウス・アプリケーションで大量のデータを変換する場合に使用します。
FUNCTION 宣言の構文は、13-58 ページの「ファンクション宣言」を参照してください。
AUTHID 句は、ストアド・ファンクションをその所有者(デフォルト)と現行ユーザーのどち
らの権限で実行するかという点、およびスキーマ・オブジェクトへの未修飾の参照を所有者と
現行ユーザーのどちらのスキーマで解決するかという点を決定します。CURRENT_USER を指定
すると、デフォルトの動作を変更できます。
PARALLEL_ENABLE オプションは、ストアド・ファンクションがパラレル DML 評価のスレー
ブ・セッションで安全に使用されることを宣言します。メイン(ログオン)
・セッションの状態
が、スレーブ・セッションと共有されることはありません。スレーブ・セッションごとに固有
の状態があり、セッション開始時に初期化されます。ファンクションの結果がセッション
(static)変数の状態に依存しないようにしてください。さもないと、セッションごとに結果
が異なる可能性があります。
DETERMINISTIC オプションは、オプティマイザが冗長なファンクション・コールを回避する
のに役立ちます。ストアド・ファンクションが同じ引数で事前にコールされた場合は、オプ
ティマイザは前の結果を使用できます。DETERMINISTIC オプションの詳細および制限につい
ては、
『Oracle Database SQL リファレンス』の「CREATE FUNCTION」を参照してください。
AUTONOMOUS_TRANSACTION プラグマはファンクションを自律型(独立型)としてマークする
ように PL/SQL コンパイラに指示します。自律型トランザクションを使用すると、メイン・ト
ランザクションを停止し、SQL 操作を実行してその操作をコミットまたはロールバックしてか
ら、メイン・トランザクションを再開できます。
8-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
ネストした PL/SQL サブプログラムの宣言
パラメータまたはファンクション戻り値のデータ型に、NOT NULL などで制約を課すことはで
きません。ただし、回避策を使用して、パラメータ型に間接的にサイズ制約を課すことができ
ます。8-3 ページの「PL/SQL プロシージャ」を参照してください。
プロシージャと同様に、ファンクションも仕様部と本体の 2 つの部分を持ちます。ファンク
ションの仕様部はキーワード FUNCTION で始め、戻り値のデータ型を指定する RETURN 句で終
わります。パラメータ宣言はオプションです。パラメータを取らないファンクションではカッ
コを書きません。
ファンクション本体は、キーワード IS(または AS)で始め、キーワード END で終わります。
END の後には、オプションとしてファンクション名を続けることができます。ファンクション
本体には、宣言部、実行部、例外処理部(オプション)の 3 つの部分があります。
宣言部では、キーワード IS と BEGIN の間にローカル宣言を置きます。キーワード DECLARE
は使用しません。実行部では、キーワード BEGIN と EXCEPTION(または END)の間に文を置
きます。ファンクションの実行部には、1 つまたは複数の RETURN 文が存在している必要があ
ります。例外処理部では、キーワード EXCEPTION と END の間に例外ハンドラを置きます。
ファンクションは、式の一部としてコールされます。次に例を示します。
IF sal_ok(new_sal, new_title) THEN ...
RETURN 文の使用
RETURN 文は、サブプログラムの実行を即座に終了し、コール元に制御を戻します。サブプロ
グラム・コールの直後の文から、実行が継続されます。
(この RETURN 文を、ファンクションの
仕様部の中で戻り値のデータ型を指定する RETURN 句と混同しないようにしてください。)
サブプログラムでは、複数の RETURN 文を使用できます。サブプログラムを RETURN 文で終え
る必要はありません。どの RETURN 文を実行しても、サブプログラムは即座に終了します。
プロシージャでは、RETURN 文は値を戻さないため、式を含めることはできません。RETURN
文は、プロシージャが終了する前に、コール元に制御を戻します。
ファンクションでは、RETURN 文に、RETURN 文の実行時に評価される式が含まれている必要
があります。結果として得られる値は、RETURN 句で指定された型の変数と同様の機能を持つ
ファンクション識別子に代入されます。RETURN 文の使用については、8-2 ページの例 8-2 を参
照してください。
ファンクションの RETURN 文では、任意で複雑な式も使用できます。
CREATE OR REPLACE FUNCTION half_of_square(original NUMBER)
RETURN NUMBER IS
BEGIN
RETURN (original * original)/2 + (original * 4);
END half_of_square;
/
ファンクションには、RETURN 文へ導く少なくとも 1 つの実行パスが必要です。実行パスがな
い場合は、実行時に「ファンクションが値なしで戻されました」というエラーが発生します。
ネストした PL/SQL サブプログラムの宣言
サブプログラムは、任意の PL/SQL ブロック、サブプログラムまたはパッケージの中で宣言で
きます。サブプログラムは、宣言部の末尾で他のすべての項目の後に置く必要があります。
サブプログラムは、コールする前に宣言する必要があります。このため、相互にコールする複
数のネストしたサブプログラムを宣言することは困難になります。
前方宣言を使用すると、相互に関連したネストしたサブプログラムを宣言できます。前方宣言
は、セミコロンで終わる、本体のないサブプログラム仕様部です。
PL/SQL のサブプログラムの使用
8-5
PL/SQL サブプログラムへのパラメータの引渡し
仮パラメータのリストは前方宣言の中にも指定しますが、サブプログラム本体にも必要です。
サブプログラム本体の位置は、前方宣言の後であればどこでもかまいませんが、同じプログラ
ム・ユニットの中に置く必要があります。
例 8-3 ネストしたサブプログラムの前方宣言
DECLARE
PROCEDURE proc1(number1 NUMBER); -- forward declaration
PROCEDURE proc2(number2 NUMBER) IS
BEGIN
proc1(number2); -- calls proc1
END;
PROCEDURE proc1(number1 NUMBER) IS
BEGIN
proc2 (number1); -- calls proc2
END;
BEGIN
NULL;
END;
/
PL/SQL サブプログラムへのパラメータの引渡し
この項では、パラメータを使用して PL/SQL サブプログラムと情報をやり取りする方法につい
て説明します。この項の項目は、次のとおりです。
■
サブプログラムの実パラメータと仮パラメータ
■
サブプログラムのパラメータの位置表記法、名前表記法または混合表記法
■
サブプログラムのパラメータのモードの指定
■
サブプログラムのパラメータのデフォルト値の使用
サブプログラムの実パラメータと仮パラメータ
サブプログラムはパラメータを使用して情報を渡します。
■
■
サブプログラムの仕様部で宣言され、サブプログラム本体で参照される変数は、仮パラ
メータと呼ばれます。
コール元のサブプログラムから渡される変数または式は、実パラメータと呼ばれます。
実パラメータと仮パラメータに別々の名前を付けることは、プログラミングの習慣として好ま
しいことです。
プロシージャをコールすると、実パラメータが評価され、対応する仮パラメータにその結果が
代入されます。実パラメータの値を仮パラメータに代入する前に、必要に応じて PL/SQL は値
のデータ型を変換します。たとえば、パラメータとして文字列を取るプロシージャに数値を渡
すと、PL/SQL がパラメータを変換し、プロシージャは文字列を受け取ります。
実パラメータと、それに対応する仮パラメータは、互換性のあるデータ型を持っている必要が
あります。たとえば、PL/SQL は DATE データ型と NUMBER データ型を変換できません。また、
ドル記号などの特別な文字を含む文字列を数値に変換できません。
例 8-4 内のプロシージャは、emp_id および amount の 2 つの仮パラメータを宣言し、プロ
シージャ・コールは実パラメータ emp_num および bonus を指定します。
例 8-4 仮パラメータと実パラメータ
DECLARE
emp_num NUMBER(6) := 120;
bonus NUMBER(6) := 100;
merit NUMBER(4) := 50;
PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) IS
8-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL サブプログラムへのパラメータの引渡し
BEGIN
UPDATE employees SET salary = salary + amount WHERE employee_id = emp_id;
END raise_salary;
BEGIN
raise_salary(emp_num, bonus); -- procedure call specifies actual parameters
raise_salary(emp_num, merit + bonus); -- expressions can be used as parameters
END;
/
サブプログラムのパラメータの位置表記法、名前表記法または混合表記法
サブプログラムをコールする場合、次のいずれかの方法を使用して実パラメータを指定します。
■
位置表記法。プロシージャ内で宣言されたとおりに、同じパラメータを同じ順序で指定し
ます。
この表記法は簡潔ですが、パラメータ(特にリテラル)を間違った順序で指定すると、不
具合の検出が困難になります。プロシージャのパラメータ・リストが変更された場合は、
コードを変更する必要があります。
■
名前表記法。値とともに各パラメータの名前を指定します。結合演算子は、矢印(=>)で
す。パラメータの順序は意味を持ちません。
この表記法はより冗長ですが、コードが読みやすくなり、メンテナンス性が向上します。
たとえば、パラメータの順序が変更されたり、新しいオプション・パラメータが追加され
るなど、プロシージャのパラメータ・リストが変更されたときに、コードを変更しなくて
もよい場合があります。他のユーザーの API をコールするコード、または他のユーザーが
使用できるように API を定義するコードでは、名前表記法を使用することは習慣として好
ましいことです。
■
混合表記法。まずパラメータを位置表記法で指定し、残りのパラメータを名前表記法で指
定します。
この表記法を使用して、必須パラメータの後にオプション・パラメータが続くプロシー
ジャをコールできます。
例 8-5 に、位置表記法、名前表記法または混合表記法を使用した同等なプロシージャ・コール
を示します。
例 8-5 位置表記法、名前表記法または混合表記法でのサブプログラムのコール
DECLARE
emp_num NUMBER(6) := 120;
bonus NUMBER(6) := 50;
PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) IS
BEGIN
UPDATE employees SET salary = salary + amount WHERE employee_id = emp_id;
END raise_salary;
BEGIN
raise_salary(emp_num, bonus); -- positional procedure call for actual parameters
raise_salary(amount => bonus, emp_id => emp_num); -- named parameters
raise_salary(emp_num, amount => bonus); -- mixed parameters
END;
/
PL/SQL のサブプログラムの使用
8-7
PL/SQL サブプログラムへのパラメータの引渡し
サブプログラムのパラメータのモードの指定
パラメータ・モードは、仮パラメータの動作を定義する場合に使用します。パラメータ・モー
ドには、IN(デフォルト)
、OUT および IN OUT の 3 つがあります。
任意のサブプログラムで任意のパラメータ・モードを使用できます。ファンクションでは、
OUT モードと IN OUT モードを使用しないでください。ファンクションが複数の値を戻すよう
なプログラミングは、好ましくありません。また、サブプログラム専用ではない変数の値を変
更するなどの副作用にも注意してください。
IN モードの使用
IN パラメータは、コールされるサブプログラムに値を渡すために使用します。サブプログラム
の中では、IN パラメータは定数のように取り扱われます。値は代入できません。
定数、リテラル、初期化された変数または式を IN パラメータとして渡せます。
IN パラメータはデフォルト値で初期化できます。デフォルト値は、サブプログラム・コールで
IN パラメータが省略された場合に使用されます。詳細は、8-9 ページの「サブプログラムのパ
ラメータのデフォルト値の使用」を参照してください。
OUT モードの使用
OUT パラメータは、サブプログラムのコール元に値を戻します。サブプログラムの中では、
OUT パラメータは変数のように取り扱われます。値を変更して、代入後に値を参照できます。
例 8-6 OUT モードの使用
DECLARE
emp_num
NUMBER(6) := 120;
bonus
NUMBER(6) := 50;
emp_last_name VARCHAR2(25);
PROCEDURE raise_salary (emp_id IN NUMBER, amount IN NUMBER,
emp_name OUT VARCHAR2) IS
BEGIN
UPDATE employees SET salary = salary + amount WHERE employee_id = emp_id;
SELECT last_name INTO emp_name FROM employees WHERE employee_id = emp_id;
END raise_salary;
BEGIN
raise_salary(emp_num, bonus, emp_last_name);
DBMS_OUTPUT.PUT_LINE('Salary has been updated for: ' || emp_last_name);
END;
/
OUT パラメータには変数を渡す必要があります。定数または式は渡せません。NOCOPY キー
ワードを指定していない場合、または未処理例外が発生してサブプログラムが正常に終了した
場合、以前の値は失われます。8-9 ページの「サブプログラムのパラメータのデフォルト値の使
用」を参照してください。
変数と同じように、OUT 仮パラメータは NULL に初期設定されます。OUT 仮パラメータのデー
タ型は、組込みサブタイプ NATURALN や POSITIVEN などの NOT NULL として定義されたサブ
タイプにはできません。そうしないと、サブプログラムをコールしたときに PL/SQL は
VALUE_ERROR を呼び出します。
サブプログラムを終了する前に、すべての OUT 仮パラメータに値を代入してください。そうし
ないと、対応する実パラメータの値は NULL になります。正常に終了した場合、PL/SQL は実
パラメータに値を代入します。未処理例外が発生して終了すると、PL/SQL は実パラメータに
値を代入しません。
8-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL サブプログラムへのパラメータの引渡し
IN OUT モードの使用
IN OUT パラメータは、サブプログラムに初期値を渡し、更新された値をコール元に戻します。
IN OUT パラメータに値を代入したり、その値を読み取ることができます。通常、IN OUT パ
ラメータは文字列バッファまたは数値アキュムレータであり、サブプログラム内で読み取られ
た後に更新されます。
IN OUT 仮パラメータに対応する実パラメータは、定数や式ではなく、変数である必要がありま
す。
サブプログラムを正常に終了した場合、PL/SQL は実パラメータに値を代入します。未処理例
外が発生して終了すると、PL/SQL は実パラメータに値を代入しません。
サブプログラムのパラメータのモードの概要
表 8-1 に、パラメータ・モードの概要をまとめます。
表 8-1 パラメータのモード
IN
OUT
IN OUT
デフォルト
指定する必要がある
指定する必要がある
サブプログラムに値を渡す
コール元に値を戻す
サブプログラムに初期値を渡
し、更新された値をコール元に
戻す
仮パラメータは定数のように取 仮パラメータは初期化されてな 仮パラメータは初期化された変
り扱われる
い変数のように取り扱われる
数のように取り扱われる
仮パラメータに値を代入できな 仮パラメータには値を代入する 仮パラメータには値を代入する
い
必要がある
必要がある
実パラメータには定数、リテラ 実パラメータは変数である必要 実パラメータは変数である必要
ル、初期化された変数または式 がある
がある
が使用できる
実パラメータは参照方式によっ NOCOPY が指定されていない場
て渡される(その値を指すポイ 合、実パラメータは値方式に
ンタが渡される)
よって渡される(値のコピーが
戻される)
NOCOPY が指定されていない場
合、実パラメータは値方式に
よって渡される(値のコピーが
やり取りされる)
サブプログラムのパラメータのデフォルト値の使用
IN パラメータをデフォルト値に初期化することで、サブプログラムに様々な数の実パラメータ
を渡し、省略したパラメータにはデフォルト値を指定できます。さらに、サブプログラムへの
コールを個々に変更しなくても、仮パラメータを新しく追加できます。
パラメータが省略されると、対応する仮パラメータのデフォルト値が使用されます。実パラ
メータを省略して、仮パラメータを 1 つスキップすることはできません。最初のパラメータを
省略して 2 番目のパラメータを指定するには、名前表記法を使用します。
実パラメータを省略して、初期化されていない仮パラメータに NULL を代入することはできま
せん。明示的に NULL を渡すか、または宣言部でデフォルト値に NULL を指定します。
例 8-7 に、サブプログラム・パラメータのデフォルト値の使用法を示します。
例 8-7 デフォルトのパラメータ値を使用したプロシージャ
DECLARE
emp_num NUMBER(6) := 120;
bonus NUMBER(6);
merit NUMBER(4);
PROCEDURE raise_salary (emp_id IN NUMBER, amount IN NUMBER DEFAULT 100,
extra IN NUMBER DEFAULT 50) IS
BEGIN
UPDATE employees SET salary = salary + amount + extra
WHERE employee_id = emp_id;
PL/SQL のサブプログラムの使用
8-9
サブプログラム名のオーバーロード
END raise_salary;
BEGIN
raise_salary(120); -- same as raise_salary(120, 100, 50)
raise_salary(emp_num, extra => 25); -- same as raise_salary(120, 100, 25)
END;
/
サブプログラム名のオーバーロード
PL/SQL では、サブプログラム名と型のメソッドをオーバーロードできます。仮パラメータの
数、順序またはデータ型が異なっていれば、同じ名前を複数のサブプログラムで使用できます。
パッケージ内のオーバーロードされたプロシージャの例については、9-6 ページの例 9-3 を参照
してください。
例 8-8 に、同じ名前を持つ 2 つのサブプログラムの定義方法を示します。プロシージャでは
様々な型のコレクションを初期化します。この 2 つのプロシージャは同じ処理を実行している
ため、同じ名前を与えるのが論理的です。
オーバーロードされるこの 2 つの initialize プロシージャは、同じブロック、サブプログラ
ム、パッケージまたはオブジェクト型の中に置くことができます。PL/SQL は仮パラメータを
チェックして、どちらのプロシージャをコールするかを判断します。PL/SQL が使用する
initialize のバージョンは、プロシージャを DateTabTyp パラメータまたは NumTabTyp パ
ラメータのどちらでコールするかによって異なります。
例 8-8 サブプログラム名のオーバーロード
DECLARE
TYPE DateTabTyp IS TABLE OF DATE INDEX BY PLS_INTEGER;
TYPE NumTabTyp IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
hiredate_tab DateTabTyp;
sal_tab NumTabTyp;
PROCEDURE initialize (tab OUT DateTabTyp, n INTEGER) IS
BEGIN
FOR i IN 1..n LOOP
tab(i) := SYSDATE;
END LOOP;
END initialize;
PROCEDURE initialize (tab OUT NumTabTyp, n INTEGER) IS
BEGIN
FOR i IN 1..n LOOP
tab(i) := 0.0;
END LOOP;
END initialize;
BEGIN
initialize(hiredate_tab, 50); -- calls first (DateTabTyp) version
initialize(sal_tab, 100);
-- calls second (NumTabTyp) version
END;
/
数値型のオーバーロードのガイドライン
2 つのサブプログラムの仮パラメータの違いが数値データ型のみの場合、それらのサブプログ
ラムはオーバーロードできます。この手法は、ファンクションの複数のバージョンが同じ名前
を使用し、それぞれが異なる数値型を受け取る数値演算 Application Programming Interface
(API)を記述する場合に有効です。たとえば、BINARY_FLOAT を受け取るファンクションはよ
り高速で、BINARY_DOUBLE を受け取るファンクションは精度がより高くなる場合があります。
8-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
サブプログラム名のオーバーロード
オーバーロードされたサブプログラムにパラメータを渡す場合、次のことに注意して、問題ま
たは予期しない結果を回避します。
■
■
予期されるすべてのパラメータ・セットで、目的のバージョンのサブプログラムがコール
されることを確認します。たとえば、オーバーロードされるファンクションが
BINARY_FLOAT および BINARY_DOUBLE を受け取る場合、
「5.0」のような VARCHAR2 リ
テラルを渡すと、どちらのファンクションがコールされるかを確認します。
数値リテラルを修飾したり、変換ファンクションを使用して、目的のパラメータ型を明示
します。たとえば、5.0f(BINARY_FLOAT)
、5.0d(BINARY_DOUBLE)のようなリテラ
ル、または TO_BINARY_FLOAT()、TO_BINARY_DOUBLE()、TO_NUMBER() のような変
換ファンクションを使用します。
PL/SQL が一致する数値パラメータを検索する順序は、最初に PLS_INTEGER または
BINARY_INTEGER、次に NUMBER、次に BINARY_FLOAT、最後に BINARY_DOUBLE です。指
定されたパラメータに最初に一致したオーバーロードされるサブプログラムが使用されます。
VARCHAR2 値は、NUMBER、BINARY_FLOAT または BINARY_DOUBLE パラメータに一致しま
す。
たとえば、1 つのパラメータを受け取る SQRT ファンクションについて考えます。NUMBER、
BINARY_FLOAT または BINARY_DOUBLE パラメータを受け取るオーバーロードされるファン
クションがあるとします。PLS_INTEGER パラメータを渡した場合、
(前述の順序を使用する
と)最初に一致してオーバーロードされるファンクションは、最も低速である可能性が高い
NUMBER パラメータのファンクションです。より高速なバージョンを使用するには、
TO_BINARY_FLOAT または TO_BINARY_DOUBLE ファンクションを使用して、パラメータを適
切なデータ型に変換します。
次に、同じ型の 2 つのパラメータを受け取る ATAN2 ファンクションについて考えます。同じ型
の 2 つのパラメータを渡した場合、どのオーバーロードされるバージョンが使用されるかは、
前述の例と同じ規則から決定されます。異なる型のパラメータを渡した場合(たとえば、1 つ
が PLS_INTEGER で、1 つが BINARY_FLOAT の場合)
、PL/SQL は、両方のパラメータでより
高度な型が使用されている場合に一致するものを検索します。この例では、2 つの
BINARY_FLOAT パラメータを受け取るバージョンの ATAN2 が使用されます。PLS_INTEGER
パラメータは、上位変換されます。
上位変換は、さらに複雑な状況でも適用されます。たとえば、異なる型の 2 つのパラメータを
受け取る複雑なファンクションがあるとします。オーバーロードされるバージョンの 1 つが、
PLS_INTEGER パラメータおよび BINARY_FLOAT パラメータを受け取るとします。別のオー
バーロードされるバージョンが、NUMBER パラメータおよび BINARY_DOUBLE パラメータを受
け取るとします。2 つの NUMBER パラメータを渡してこのプロシージャ名をコールします。
PL/SQL はまず上位検索し、2 つ目のパラメータが BINARY_FLOAT のオーバーロードされる
バージョンを検出します。このパラメータは、他方のオーバーロードされるバージョンの
BINARY_DOUBLE パラメータよりも一致度が高いため、次に PL/SQL は下位検索し、1 つ目の
NUMBER パラメータを PLS_INTEGER に変換します。
オーバーロードの制限
オーバーロードできるのは、ローカル・サブプログラム、パッケージ・サブプログラムまたは
型の順序のみです。スタンドアロン・サブプログラムはオーバーロードできません。
サブプログラムの仮パラメータの違いが名前またはパラメータ・モードのみの場合は、2 つの
サブプログラムをオーバーロードできません。たとえば、次の 2 つのプロシージャはオーバー
ロードできません。
例 8-9 PL/SQL プロシージャのオーバーロードに関する制限
DECLARE
PROCEDURE balance (acct_no IN INTEGER) IS
BEGIN NULL; END;
PROCEDURE balance (acct_no OUT INTEGER) IS
BEGIN NULL; END;
PL/SQL のサブプログラムの使用
8-11
サブプログラムのコールの解決方法
BEGIN
DBMS_OUTPUT.PUT_LINE('The following procedure call raises an error.');
-- balance(100); raises an error because the procedure declaration is not unique
END;
/
サブプログラムのパラメータの違いがサブタイプのみの場合は、サブプログラムをオーバー
ロードできません。たとえば、INTEGER パラメータを受け取るプロシージャと REAL パラメー
タを受け取るプロシージャは、オーバーロードできません。INTEGER と REAL は両方とも
NUMBER のサブタイプであり、同じファミリに属すためです。
戻り値のデータ型のみが異なる 2 つのファンクションは、その型のファミリが異なっている場
合でも、オーバーロードできません。たとえば、BOOLEAN を戻すファンクションと INTEGER
を戻すファンクションは、オーバーロードできません。
サブプログラムのコールの解決方法
図 8-1 に、PL/SQL コンパイラがサブプログラム・コールを解決する方法を示します。コンパ
イラがプロシージャ・コールまたはファンクション・コールを発見すると、そのコールに合う
宣言を探します。コンパイラはまず現在の有効範囲を検索し、必要ならば外側の有効範囲を順
に検索します。コールされたサブプログラムの名前と同じ名前のサブプログラム宣言が 1 つ以
上見つかると、コンパイラはさらに厳密に検索します。
同じ有効範囲のレベルに同じような名前のサブプログラムが存在する場合は、コールを解決す
るために、コンパイラは実パラメータと仮パラメータが正確に一致するものを発見する必要が
あります。パラメータは、
(いくつかの仮パラメータにデフォルト値が代入されている場合を除
き)数、順序およびデータ型が一致している必要があります。一致するものが見つからなかっ
た場合、または一致するものが複数見つかった場合、コンパイラはセマンティック・エラーを
生成します。
8-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
サブプログラムのコールの解決方法
図 8-1 PL/SQL コンパイラによるコールの解決方法
例 8-10 は、ファンクション balance から外側のプロシージャ swap をコールしています。現
在の有効範囲の中にある swap の宣言が、いずれもプロシージャ・コールと一致しないために、
コンパイラはエラーを生成します。
例 8-10 PL/SQL プロシージャ名の解決
DECLARE
PROCEDURE swap (n1 NUMBER, n2 NUMBER) IS
num1 NUMBER;
num2 NUMBER;
FUNCTION balance (bal NUMBER) RETURN NUMBER IS
x NUMBER := 10;
PROCEDURE swap (d1 DATE, d2 DATE) IS BEGIN NULL; END;
PROCEDURE swap (b1 BOOLEAN, b2 BOOLEAN) IS BEGIN NULL; END;
BEGIN
DBMS_OUTPUT.PUT_LINE('The following raises an error');
-swap(num1, num2); wrong number or types of arguments in call to 'SWAP'
RETURN x;
PL/SQL のサブプログラムの使用
8-13
サブプログラムのコールの解決方法
END balance;
BEGIN NULL;END swap;
BEGIN
NULL;
END;
/
オーバーロードと継承の相互作用
オーバーロード・アルゴリズムでは、スーパータイプである仮パラメータのかわりにサブタイ
プの値を使用できます。この機能は代替性と呼ばれます。オーバーロードされるプロシージャ
の複数のインスタンスがプロシージャ・コールと一致する場合は、どのプロシージャがコール
されるかを判断するために次の規則が適用されます。
オーバーロードされる各プロシージャのシグネチャの違いが、一部のパラメータが同じスー
パータイプ / サブタイプ階層のオブジェクト型であるということのみの場合は、最大一致のも
のが使用されます。最大一致とは、すべてのパラメータがオーバーロードされる他のインスタ
ンスと少なくとも同程度に近く、少なくとも 1 つのパラメータが近い場合を指します。この近
さは、サブタイプとスーパータイプ間の継承の深さによって決まります。
オーバーロードされる 2 つのインスタンスが一致し、オーバーロードされる一方のプロシー
ジャ内の一部の引数の型が他のインスタンス内よりも実引数に近いと、セマンティック・エ
ラーが発生します。
また、一部のパラメータの位置がオブジェクト型階層内で異なり、他のパラメータのデータ型
が異なる場合も、暗黙的な変換が必要になるため、セマンティック・エラーが発生します。
たとえば、例 8-11 に示すとおり、3 つのレベルを持つ型階層を作成してから、ファンクション
のオーバーロードされたインスタンスを 2 つ宣言します。両者の引数の型の違いは、この型階
層内での位置のみです。final_t 型の変数を宣言してから、オーバーロードされるファンク
ションをコールします。ファンクションのインスタンスのうち実行されるのは、sub_t パラ
メータを受け入れるインスタンスです。これは、その型が階層内で super_t よりも final_t
に近いためです。
例 8-11 継承による PL/SQL ファンクションの解決
CREATE OR REPLACE TYPE super_t AS OBJECT
(n NUMBER) NOT final;
/
CREATE OR REPLACE TYPE sub_t UNDER super_t
(n2 NUMBER) NOT final;
/
CREATE OR REPLACE TYPE final_t UNDER sub_t
(n3 NUMBER);
/
CREATE OR REPLACE PACKAGE p IS
FUNCTION func (arg super_t) RETURN NUMBER;
FUNCTION func (arg sub_t) RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY p IS
FUNCTION func (arg super_t) RETURN NUMBER IS BEGIN RETURN 1; END;
FUNCTION func (arg sub_t) RETURN NUMBER IS BEGIN RETURN 2; END;
END;
/
DECLARE
v final_t := final_t(1,2,3);
BEGIN
DBMS_OUTPUT.PUT_LINE(p.func(v)); -- prints 2
END;
/
8-14
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
実行者権限と定義者権限の使用(AUTHID 句)
例 8-11 では、コールするインスタンスはコンパイル時に選択されます。例 8-12 では、この選択
が動的に行われます。v を super_t のインスタンスとして宣言しますが、そこに sub_t の値
を代入するために、ファンクションの適切なインスタンスがコールされます。この機能は動的
ディスパッチと呼ばれます。
例 8-12 継承による PL/SQL ファンクションの動的な解決
CREATE TYPE super_t AS OBJECT
(n NUMBER, MEMBER FUNCTION func RETURN NUMBER) NOT final;
/
CREATE TYPE BODY super_t AS
MEMBER FUNCTION func RETURN NUMBER IS BEGIN RETURN 1; END; END;
/
CREATE OR REPLACE TYPE sub_t UNDER super_t
(n2 NUMBER,
OVERRIDING MEMBER FUNCTION func RETURN NUMBER) NOT final;
/
CREATE TYPE BODY sub_t AS
OVERRIDING MEMBER FUNCTION func RETURN NUMBER IS BEGIN RETURN 2; END; END;
/
CREATE OR REPLACE TYPE final_t UNDER sub_t
(n3 NUMBER);
/
DECLARE
v super_t := final_t(1,2,3);
BEGIN
DBMS_OUTPUT.PUT_LINE(v.func); -- prints 2
END;
/
実行者権限と定義者権限の使用(AUTHID
句)
実行者権限と定義者権限の使用(
デフォルトでは、ストアド・プロシージャおよび SQL メソッドは、現行ユーザーの権限ではな
く所有者の権限で実行します。このような定義者権限サブプログラムは、サブプログラムが存
在するスキーマにバインドされ、同じスキーマのオブジェクトを名前の修飾なしに参照できま
す。たとえば、スキーマ HR と OE の両方に表 departments がある場合、HR が所有するプロ
シージャは、HR.departments のかわりに departments を使用してその表を参照できます。
ユーザー OE が HR のプロシージャをコールした場合、プロシージャは HR が所有する
departments 表にアクセスします。
同じプロシージャを両方のスキーマでコンパイルする場合、SQL*Plus でスキーマ名を変数とし
て定義し、&schema..departments のように表を参照できます。このコードは移植性があり
ますが、コードを変更した場合はそれぞれのスキーマで再コンパイルする必要があります。
よりメンテナンス性の高い方法は、AUTHID 句を使用することです。これによって、ストアド・
プロシージャおよび SQL メソッドをコール元のユーザーの権限とスキーマ・コンテキストで実
行できます。プロシージャのインスタンスを 1 つ作成し、多くのユーザーがそのプロシージャ
をコールしてユーザー自身のデータにアクセスできます。
このような実行者権限サブプログラムは、特定のスキーマにバインドされません。たとえば、
次に示すプロシージャ create_dept は、コール元のユーザーの権限で実行され、そのユー
ザーの departments 表に行を挿入します。
例 8-13 プロシージャによる実行者権限の指定
CREATE OR REPLACE PROCEDURE create_dept (
v_deptno NUMBER,
v_dname VARCHAR2,
v_mgr
NUMBER,
v_loc
NUMBER)
AUTHID CURRENT_USER AS
PL/SQL のサブプログラムの使用
8-15
実行者権限と定義者権限の使用(AUTHID 句)
BEGIN
INSERT INTO departments VALUES (v_deptno, v_dname, v_mgr, v_loc);
END;
/
CALL create_dept(44, 'Information Technology', 200, 1700);
実行者権限のメリット
実行者権限サブプログラムを使用すると、コードを再利用し、アプリケーション・ロジックを
集中化できます。これは、異なるスキーマの同じ名前の表にデータを格納するアプリケーショ
ンで特に便利です。1 つのインスタンス内のすべてのスキーマは、集中管理された 1 つのス
キーマが所有するプロシージャをコールできます。異なるインスタンスのスキーマから、デー
タベース・リンクを使用して、集中管理されたプロシージャをコールすることもできます。
ストアド・プロシージャを使用して売上を分析する会社の場合を考えてみます。この会社に複
数のスキーマがあり、それぞれによく似た SALES 表がある場合、通常、各スキーマにストア
ド・プロシージャのコピーが必要になります。
この問題を解決するには、ストアド・プロシージャの実行者権限バージョンを集中管理された
スキーマにインストールします。これによって、他のすべてのスキーマから同じプロシージャ
をコールでき、プロシージャはそれぞれの場合に応じて適切な SALES 表を問い合せます。
実行者権限サブプログラムから、機密データを含む表への問合せまたは更新を行う定義者権限
サブプログラムをコールすることによって、機密データへのアクセスを制限できます。複数の
ユーザーが実行者権限サブプログラムをコールできますが、機密データに直接アクセスできま
せん。
AUTHID 句によるサブプログラムの権限の指定
実行者権限を実装するには、AUTHID 句を使用して、サブプログラムを所有者と現行ユーザー
のどちらの権限で実行するかを指定します。またこの句は、外部参照(サブプログラムの外側
のオブジェクトへの参照)が所有者と現行ユーザーのどちらのスキーマで解決されるかも指定
します。
AUTHID 句は、スタンドアロン・サブプログラム、パッケージ仕様部またはオブジェクト型仕
様部のヘッダーでのみ使用できます。CREATE FUNCTION 文、CREATE PROCEDURE 文、
CREATE PACKAGE 文または CREATE TYPE 文では、宣言部の先頭の IS または AS の直前に、
AUTHID CURRENT_USER または AUTHID DEFINER のいずれかを含めることができます。
DEFINER はデフォルトのオプションです。パッケージまたはオブジェクト型では、AUTHID 句
はすべてのサブプログラムに適用されます。
提供されている PL/SQL パッケージの大部分(DBMS_LOB、DBMS_PIPE、DBMS_ROWID、
DBMS_SQL および UTL_REF)は、実行者権限パッケージです。
サブプログラム実行中の現行ユーザー
一連のコールで制御が実行者権限サブプログラム内にある場合は常に、現行ユーザーとはセッ
ション・ユーザーを指します。定義者権限サブプログラムがコールされた場合は、そのサブプ
ログラムの所有者が現行ユーザーになります。新しいサブプログラムがコールされたり、サブ
プログラムが終了すると、現行ユーザーは変更されます。
USER_USERS データ・ディクショナリ・ビューを参照すると、いつでも現行ユーザーを確認で
きます。実行者権限サブプログラム内では、このビューの値は USER 組込みファンクションの
値と異なる場合があります。このファンクションは、常にセッション・ユーザーの名前を戻し
ます。
8-16
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
実行者権限と定義者権限の使用(AUTHID 句)
実行者権限サブプログラムでの外部参照の解決
AUTHID CURRENT_USER を指定すると、実行時に現行ユーザーの権限がチェックされ、外部参
照は現行ユーザーのスキーマで解決されます。ただし、これは次の文の外部参照にのみ適用さ
れます。
■
SELECT、INSERT、UPDATE および DELETE DML 文
■
LOCK TABLE トランザクション制御文
■
OPEN および OPEN-FOR カーソル制御文
■
EXECUTE IMMEDIATE および OPEN-FOR-USING 動的 SQL 文
■
DBMS_SQL.PARSE() を使用して解析された SQL 文
それ以外の文の場合は、コンパイル時に所有者の権限がチェックされ、外部参照は所有者のス
キーマで解決されます。たとえば、例 8-14 の代入文は、1-13 ページの例 1-13 に示された
emp_actions パッケージ内のパッケージ・ファンクション num_above_salary を参照しま
す。この外部参照はプロシージャ above_salary の所有者のスキーマで解決されます。
例 8-14 実行者権限サブプログラムでの外部参照の解決
CREATE PROCEDURE above_salary (emp_id IN NUMBER)
AUTHID CURRENT_USER AS
emps NUMBER;
BEGIN
emps := emp_actions.num_above_salary(emp_id);
DBMS_OUTPUT.PUT_LINE( 'Number of employees with higher salary: ' ||
TO_CHAR(emps));
END;
/
CALL above_salary(120);
実行者権限サブプログラムでのテンプレート・オブジェクトの必要性
PL/SQL コンパイラは、表および他のオブジェクトへのすべての参照をコンパイル時に解決す
る必要があります。実行者権限サブプログラムの所有者は、同じスキーマ内に正しい名前と列
のオブジェクトを持つ必要があります。オブジェクトには、データが存在していなくてもかま
いません。実行時に、コール元のスキーマ内の対応するオブジェクトは、一致する定義を持っ
ている必要があります。そうでない場合、エラーまたは予期しない結果(コール元のスキーマ
には存在するがサブプログラムを含むスキーマには存在しない表の列が無視されるなど)が発
生します。
実行者権限サブプログラムでのデフォルトの名前解決のオーバーライド
コール元のスキーマではなく特定のスキーマを参照するために、未修飾の名前が必要な場合が
あります。実行者権限サブプログラムと同じスキーマ内で、CREATE SYNONYM 文を使用して、
表、プロシージャ、ファンクションまたはその他のオブジェクトのパブリック・シノニムを作
成します。
CREATE PUBLIC SYNONYM emp FOR hr.employees;
実行者権限サブプログラムがこの名前を参照している場合、サブプログラム自身のスキーマ内
のシノニムと一致し、指定されたスキーマ内のオブジェクトへ解決されます。コール元のス
キーマに同じ名前のスキーマ・オブジェクトまたはプライベート・シノニムがすでに存在する
場合、この手法は使用できません。その場合は、実行者権限サブプログラムで参照を完全修飾
する必要があります。
PL/SQL のサブプログラムの使用
8-17
実行者権限と定義者権限の使用(AUTHID 句)
実行者権限サブプログラムに対する権限の付与
サブプログラムを直接コールするには、ユーザーはそのサブプログラムに対して EXECUTE 権
限を持っている必要があります。権限を付与することで、ユーザーに次のことを許可します。
■
サブプログラムの直接のコール
■
サブプログラムをコールするファンクションおよびプロシージャのコンパイル
現行ユーザーのスキーマで解決される外部参照の場合(DML 文内など)、現行ユーザーはサブ
プログラムが参照するスキーマ・オブジェクトへのアクセスに必要な権限を持っている必要が
あります。その他すべての外部参照(ファンクション・コールなど)の場合は、所有者の権限
がコンパイル時にチェックされ、実行時にはチェックされません。
定義者権限サブプログラムは、実行者にかかわらず、その所有者のセキュリティ・ドメインで
作動します。所有者はサブプログラムが参照するスキーマ・オブジェクトへのアクセスに必要
な権限を持っている必要があります。
複数のサブプログラムからなるプログラムを作成できます。定義者権限を持つものと実行者権
限を持つものとを混在させることもできます。この場合、EXECUTE 権限を使用して、プログラ
ムのエントリ・ポイントを制限できます。これによって、エントリ・ポイント・サブプログラ
ムのユーザーは他のサブプログラムを直接ではなく間接的に実行できます。
実行者権限サブプログラムに対する権限の付与 : 例
ユーザー UTIL が、サブプログラム FFT に対する EXECUTE 権限を、ユーザー APP に付与する
とします。
GRANT EXECUTE ON util.fft TO app;
ユーザー APP は、サブプログラム FFT をコールするファンクションおよびプロシージャをコン
パイルできるようになります。実行時には、このコールについての権限チェックは行われませ
ん。図 8-2 に示すように、ユーザー UTIL は、FFT を間接的にコールするユーザーに 1 人ずつ
EXECUTE 権限を付与する必要はありません。
サブプログラム util.fft は実行者権限サブプログラム app.entry からのみ直接コールされ
るため、ユーザー util は、EXECUTE 権限をユーザー APP にのみ付与する必要があります。
UTIL.FFT を実行すると、その現行ユーザーは APP、SCOTT または BLAKE になります。
SCOTT および BLAKE が EXECUTE 権限を付与されていない場合も同様です。
図 8-2 実行者権限サブプログラムへの間接コール
8-18
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
実行者権限と定義者権限の使用(AUTHID 句)
実行者権限サブプログラムでのロールの使用
サブプログラムでのロールの使用は、定義者権限と実行者権限のどちらで実行するかによって
異なります。定義者権限サブプログラムでは、すべてのロールが使用禁止になります。ロール
は権限チェックには使用されません。また、ロールを設定することはできません。
実行者権限サブプログラムでは、ロールは使用可能になります(サブプログラムが定義者権限
サブプログラムによって直接または間接的にコールされた場合を除きます)
。ロールは権限
チェックに使用されます。また、システム固有の動的 SQL を使用してセッションにロールを設
定できます。ただし、ロールはコンパイル時ではなく実行時に適用されるため、ロールを使用
してテンプレート・オブジェクトに権限を付与することはできません。
実行者権限サブプログラムでのビューおよびデータベース・トリガーの使用
ビュー式内で実行される実行者権限サブプログラムの場合は、ビューを問い合せているスキー
マではなく、ビューを作成したスキーマが現行ユーザーとみなされます。この規則は、データ
ベース・トリガーにも適用されます。
実行者権限サブプログラムでのデータベース・リンクの使用
データベース・リンクを作成して、実行者権限を使用できます。
CREATE DATABASE LINK link_name CONNECT TO CURRENT_USER
USING connect_string;
現行ユーザー・リンクでは、そのユーザー権限を持つ別のユーザーとしてリモート・データ
ベースに接続できます。接続するために、Oracle では現行ユーザーのユーザー名を使用します
(実行者はグローバル・ユーザーである必要があります)。ユーザー OE が所有する実行者権限
サブプログラムが、次のデータベース・リンクを参照するとします。グローバル・ユーザー HR
がそのサブプログラムをコールしていれば、現行ユーザーであるユーザー HR でデータベース
Dallas に接続します。
CREATE DATABASE LINK dallas CONNECT TO CURRENT_USER USING ...
定義者権限サブプログラムの場合、現行ユーザーは OE であり、サブプログラムはグローバル・
ユーザー OE でデータベース Dallas に接続します。
実行者権限サブプログラムでのオブジェクト型の使用
任意のスキーマで使用するオブジェクト型を定義するために、AUTHID CURRENT_USER 句を指
定します。オブジェクト型の詳細は、
『Oracle Database アプリケーション開発者ガイド - オブ
ジェクト・リレーショナル機能』を参照してください。
ユーザー HR が次のようにオブジェクト型を作成するとします。
例 8-15 AUTHID CURRENT USER によるオブジェクト型の作成
CREATE TYPE person_typ AUTHID CURRENT_USER AS OBJECT (
person_id NUMBER,
person_name VARCHAR2(30),
person_job VARCHAR2(10),
STATIC PROCEDURE new_person_typ (
person_id NUMBER, person_name VARCHAR2, person_job VARCHAR2,
schema_name VARCHAR2, table_name VARCHAR2),
MEMBER PROCEDURE change_job (SELF IN OUT NOCOPY person_typ, new_job VARCHAR2)
);
/
CREATE TYPE BODY person_typ AS
STATIC PROCEDURE new_person_typ (
person_id NUMBER, person_name VARCHAR2, person_job VARCHAR2,
schema_name VARCHAR2, table_name VARCHAR2) IS
sql_stmt VARCHAR2(200);
BEGIN
PL/SQL のサブプログラムの使用
8-19
実行者権限と定義者権限の使用(AUTHID 句)
sql_stmt := 'INSERT INTO ' || schema_name || '.'
|| table_name || ' VALUES (HR.person_typ(:1, :2, :3))';
EXECUTE IMMEDIATE sql_stmt USING person_id, person_name, person_job;
END;
MEMBER PROCEDURE change_job (SELF IN OUT NOCOPY person_typ, new_job VARCHAR2) IS
BEGIN
person_job := new_job;
END;
END;
/
次にユーザー HR は、オブジェクト型 person_typ に対する EXECUTE 権限を、ユーザー OE に
付与します。
GRANT EXECUTE ON person_typ TO OE;
最後に、ユーザー OE は、person_typ 型のオブジェクトを格納するためにオブジェクト表を
作成し、次にプロシージャ new_person_typ をコールして、その表にデータを入れます。
CONNECT oe/oe;
CREATE TABLE person_tab OF hr.person_typ;
BEGIN
hr.person_typ.new_person_typ(1001, 'Jane Smith', 'CLERK', 'oe', 'person_tab');
hr.person_typ.new_person_typ(1002, 'Joe Perkins', 'SALES','oe', 'person_tab');
hr.person_typ.new_person_typ(1003, 'Robert Lange', 'DEV','oe', 'person_tab');
END;
/
コールは成功しました。これはプロシージャがその所有者(HR)の権限ではなく現行ユーザー
(OE)の権限で実行されたためです。
オブジェクト型階層内のサブタイプには、次の規則が適用されます。
■
■
サブタイプで AUTHID 句が明示的に指定されていない場合は、スーパータイプの AUTHID
を継承します。
サブタイプで AUTHID 句が指定されている場合、その AUTHID がスーパータイプの AUTHID
と一致する必要があります。また、AUTHID が DEFINER の場合は、スーパータイプとサブ
タイプの両方が同じスキーマに作成されている必要があります。
実行者権限のインスタンス・メソッドのコール
実行者権限インスタンス・メソッドは、インスタンスの作成者ではなく、実行者の権限で実行
します。person_typ が例 8-15 で作成された実行者権限オブジェクト型で、ユーザー HR が、
型 person_typ のオブジェクトである p1 を作成するとします。例 8-16 に示すとおり、ユー
ザー OE が、オブジェクト p1 で操作を行うためのインスタンス・メソッド change_job を
コールする場合、メソッドの現行ユーザーは、HR ではなく OE です。
例 8-16 実行者権限のインスタンス・メソッドのコール
-- oe creates a procedure that calls change_job
CREATE PROCEDURE reassign (p IN OUT NOCOPY hr.person_typ, new_job VARCHAR2) AS
BEGIN
p.change_job(new_job); -- executes with the privileges of oe
END;
/
-- OE grants EXECUTE to HR on procedure reassign
GRANT EXECUTE ON reassign to HR;
CONNECT hr/hr
-- user hr passes a person_typ object to the procedure reassign
DECLARE
p1 person_typ;
BEGIN
8-20
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
外部サブプログラムのコール
p1 := person_typ(1004, 'June Washburn', 'SALES');
oe.reassign(p1, 'CLERK'); -- current user is oe, not hr
END;
/
PL/SQL での再帰の使用
再帰はアルゴリズムの設計を単純化する強力な手法です。一般に、再帰とは自己参照を意味し
ます。再帰的な数列の個々の項は、それ以前の項に計算式を適用することで得られます。フィ
ボナッチ数列(0, 1, 1, 2, 3, 5, 8, 13, 21, ...)がその一例です。この数列では、2 番以降の各項が、
すぐ前の 2 つの項の合計になっています。
再帰定義では、それ自身をさらに単純なバージョンに定義します。n の階乗(n!、1 ~ n のすべ
ての整数の積)の定義を考えてみます。
n!= n * (n - 1)!
再帰的サブプログラム
再帰的サブプログラムとは、自分自身をコールするサブプログラムのことです。再帰的コール
が行われるたびに、パラメータ、変数、カーソル、例外など、そのサブプログラムで宣言され
ているすべての項目の新しいインスタンスが作成されます。また、再帰を繰り返して進む過程
の各レベルで、SQL 文の新しいインスタンスが作成されます。
再帰的コールを入れる位置には注意してください。カーソル FOR ループの中や、OPEN 文と
CLOSE 文の間に入れると、コールのたびに新しいカーソルがオープンされます。これによっ
て、Oracle の OPEN_CURSORS 初期化パラメータによって設定された限界を超える場合があり
ます。
再帰的サブプログラムには、再帰的コールへ導くパスとそうではないパスの、少なくとも 2 つ
のパスが必要です。終了条件へ導くパスが少なくとも 1 つは必要だということです。そうでな
い場合、メモリーが足りなくなり、PL/SQL によって事前定義の例外 STORAGE_ERROR が呼び
出されるまで、再帰が続きます。
外部サブプログラムのコール
PL/SQL は強力かつ柔軟な言語ですが、他の言語を使用した方が容易に実行できる作業もあり
ます。C のような低レベルの言語は非常に高速です。Java のような広く使用されている言語に
は、共通の設計パターン用の再利用可能なライブラリが存在します。
PL/SQL のコール仕様を使用すると、別の言語で記述された外部サブプログラムを起動して、
それらの機能およびライブラリを PL/SQL から使用できます。たとえば、Java ストアド・プロ
シージャは、任意の PL/SQL ブロック、サブプログラムまたはパッケージからコールできま
す。Java ストアド・プロシージャの詳細は、
『Oracle Database Java 開発者ガイド』を参照して
ください。
次の Java クラスがデータベースに格納されている場合は、例 8-17 に示すとおり、このクラス
をコールできます。
import java.sql.*;
import oracle.jdbc.driver.*;
public class Adjuster {
public static void raiseSalary (int empNo, float percent)
throws SQLException {
Connection conn = new OracleDriver().defaultConnection();
String sql = "UPDATE employees SET salary = salary * ?
WHERE employee_id = ?";
try {
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setFloat(1, (1 + percent / 100));
pstmt.setInt(2, empNo);
PL/SQL のサブプログラムの使用
8-21
外部サブプログラムのコール
pstmt.executeUpdate();
pstmt.close();
} catch (SQLException e)
{System.err.println(e.getMessage());}
}
}
クラス Adjuster には、従業員の給与を指定のパーセンテージ分のみ増やすメソッドがありま
す。raiseSalary は void メソッドであるため、例 8-17 に示されたコール仕様を使用してプ
ロシージャとして発行してから、プロシージャ raise_salary を無名 PL/SQL ブロックから
コールできます。
例 8-17 PL/SQL からの外部プロシージャのコール
CREATE OR REPLACE PROCEDURE raise_salary (empid NUMBER, pct NUMBER)
AS LANGUAGE JAVA
NAME 'Adjuster.raiseSalary(int, float)';
/
DECLARE
emp_id NUMBER := 120;
percent NUMBER := 10;
BEGIN
-- get values for emp_id and percent
raise_salary(emp_id, percent); -- call external subprogram
END;
/
Java コール仕様はネストされたプロシージャとしては宣言できませんが、オブジェクト型の仕
様部、オブジェクト型の本体、PL/SQL パッケージの仕様部、PL/SQL パッケージの本体で指
定したり、トップレベル PL/SQL プロシージャおよびファンクションとして指定することがで
きます。
例 8-18 に、PL/SQL プロシージャからの Java ファンクションへのコールを示します。
例 8-18 PL/SQL からの Java ファンクション・コール
-- the following nested Java call spec is not valid, throws PLS-00999
-CREATE PROCEDURE sleep (milli_seconds in number) IS
-PROCEDURE java_sleep (milli_seconds IN NUMBER) AS ...
-- first, create the Java call spec, then call from a PL/SQL procedure
CREATE PROCEDURE java_sleep (milli_seconds IN NUMBER)
AS LANGUAGE JAVA NAME 'java.lang.Thread.sleep(long)';
/
CREATE PROCEDURE sleep (milli_seconds in number) IS
-- the following nested PROCEDURE spec is not legal
-- PROCEDURE java_sleep (milli_seconds IN NUMBER)
-AS LANGUAGE JAVA NAME 'java.lang.Thread.sleep(long)';
BEGIN
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.get_time());
java_sleep (milli_seconds);
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.get_time());
END;
/
外部 C サブプログラムは、組込みシステムとのインタフェース、技術的な分野の問題解決、
データの分析、リアルタイムのデバイスや処理の制御に使用します。外部 C サブプログラムを
使用すると、データベース・サーバーの機能性を拡張し、計算専用プログラムをクライアント
からサーバーに移動できます。サーバーの方が高速に処理できます。外部 C サブプログラムの
詳細は、
『Oracle Database アプリケーション開発者ガイド - 基礎編』を参照してください。
8-22
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
サブプログラムのパラメータのエイリアシングの理解
PL/SQL サブプログラムの副作用の制御
ストアド・ファンクション(およびそのファンクションによってコールされるサブプログラム)
は、次に示す副作用を制御するための純正規則に従っている場合にのみ、SQL 文からコールで
きます。
■
■
■
SELECT 文またはパラレル化 INSERT 文、UPDATE 文または DELETE 文からコールされた場
合、ファンクションはデータベース表を変更できません。
INSERT 文、UPDATE 文または DELETE 文からコールされた場合、ファンクションは、その
文によって変更されたデータベース表の問合せや変更はできません。
SELECT 文、INSERT 文、UPDATE 文または DELETE 文からコールされた場合、ファンク
ションは SQL トランザクション制御文(COMMIT など)
、セッション制御文(SET ROLE な
ど)またはシステム制御文(ALTER SYSTEM など)を実行できません。また、DDL 文
(CREATE など)には自動コミットが続くため、これも実行できません。
ファンクション本体内の SQL 文が規則に違反すると、実行時(文が解析されるとき)にエラー
が発生します。
この規則に違反していないかどうかを確認するには、RESTRICT_REFERENCES プラグマ(コン
パイラ・ディレクティブ)を使用します。プラグマは、ファンクションがデータベース表また
はパッケージ変数に対する読込みまたは書込みを行っていないことを示しますたとえば次のプ
ラグマは、パッケージ・ファンクション credit_ok がデータベースへの書込み禁止状態
(WNDS)、およびパッケージに読込み禁止状態(RNPS)であることを示します。
CREATE PACKAGE loans AS
FUNCTION credit_ok RETURN BOOLEAN;
PRAGMA RESTRICT_REFERENCES (credit_ok, WNDS, RNPS);
END loans;
/
静的 INSERT 文、UPDATE 文または DELETE 文は、常に WNDS に違反します。また、列を読み
取る場合は RNDS(データベースに読込み禁止状態)にも違反します。動的 INSERT 文、
UPDATE 文または DELETE 文は、常に WNDS および RNDS に違反します。
詳細は、13-96 ページの「RESTRICT_REFERENCES プラグマ」を参照してください。純正規則
の詳細は、
『Oracle Database アプリケーション開発者ガイド - 基礎編』を参照してください。
サブプログラムのパラメータのエイリアシングの理解
サブプログラムのコールを最適化するために、PL/SQL コンパイラでは、2 つのパラメータ引
渡し方式のいずれかを選択できます。値方式では、実パラメータの値がサブプログラムに渡さ
れます。参照方式では、値へのポインタのみが渡されます。この場合、実パラメータと仮パラ
メータとは同じ項目を参照します。
NOCOPY コンパイラ・ヒントによって、エイリアシングの可能性が高くなります(つまり、異
なる 2 つの名前が同じメモリー位置を参照するようになります)
。これは、グローバル変数がサ
ブプログラムのコールの中で実パラメータとして使用され、そのサブプログラム内で参照され
ると発生します。結果はコンパイラが選択するパラメータの引渡し方式に依存するため、予測
不能になります。
例 8-19 では、プロシージャ ADD_ENTRY は、VARRAY LEXICON をパラメータとグローバル変
数の両方として参照しています。ADD_ENTRY がコールされると、識別子 WORD_LIST および
LEXICON は同じ VARRAY を指定します。
例 8-19 NOCOPY ヒントを指定したグローバル変数の引渡しによるエイリアシング
DECLARE
TYPE Definition IS RECORD (
word
VARCHAR2(20),
meaning VARCHAR2(200));
TYPE Dictionary IS VARRAY(2000) OF Definition;
lexicon Dictionary := Dictionary();
PROCEDURE add_entry (word_list IN OUT NOCOPY Dictionary) IS
PL/SQL のサブプログラムの使用
8-23
サブプログラムのパラメータのエイリアシングの理解
BEGIN
word_list(1).word := 'aardvark';
lexicon(1).word := 'aardwolf';
END;
BEGIN
lexicon.EXTEND;
add_entry(lexicon);
DBMS_OUTPUT.PUT_LINE(lexicon(1).word);
END;
/
コンパイラが NOCOPY ヒントに従う場合、プログラムは aardwolf を出力します。
WORD_LIST への代入はポインタを通じてただちに実行され、LEXICON への代入によって上書
きされます。
NOCOPY ヒントが省略された場合またはコンパイラが NOCOPY ヒントに従わない場合、プロ
グラムは aardvark を出力します。WORD_LIST への代入には VARRAY の内部コピーが使用さ
れます。これは、プロシージャの終了時に実パラメータにコピーされます(LEXICON の内容を
上書きします)
。
エイリアシングは、1 回のサブプログラム・コールに、同じ実パラメータが 2 回以上現れる場
合にも発生します。例 8-20 では、n2 が IN OUT のパラメータであるため、実パラメータの値
は、プロシージャが終了するまで更新されません。そのため、最初の PUT_LINE は 10(n の初
期値)を出力し、3 番目の PUT_LINE は 20 を出力します。ただし、n3 は NOCOPY パラメータ
であるため、実パラメータの値はただちに更新されます。2 番目の PUT_LINE が 30 を出力する
のはこのためです。
例 8-20 同じパラメータの複数回の引渡しによるエイリアシング
DECLARE
n NUMBER := 10;
PROCEDURE do_something (
n1 IN NUMBER,
n2 IN OUT NUMBER,
n3 IN OUT NOCOPY NUMBER) IS
BEGIN
n2 := 20;
DBMS_OUTPUT.put_line(n1); -- prints 10
n3 := 30;
DBMS_OUTPUT.put_line(n1); -- prints 30
END;
BEGIN
do_something(n, n, n);
DBMS_OUTPUT.put_line(n); -- prints 20
END;
/
カーソル変数はポインタであるため、カーソル変数にもエイリアシングの可能性があります。
例 8-21 では、代入の後、emp_cv2 は emp_cv1 の別名になります。これは、両者が同じ問合せ
作業領域を指すためです。最初の 2 行はすでに emp_cv1 からフェッチされているため、
emp_cv2 からの 1 番目のフェッチは、1 番目ではなく 3 番目の行をフェッチします。emp_cv1
は閉じられているため、emp_cv2 からの 2 番目のフェッチは失敗します。
例 8-21 同じ作業領域へのカーソル変数の代入によるエイリアシング
DECLARE
TYPE EmpCurTyp IS REF CURSOR;
c1 EmpCurTyp;
c2 EmpCurTyp;
PROCEDURE get_emp_data (emp_cv1 IN OUT EmpCurTyp, emp_cv2 IN OUT EmpCurTyp) IS
emp_rec employees%ROWTYPE;
BEGIN
OPEN emp_cv1 FOR SELECT * FROM employees;
8-24
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
サブプログラムのパラメータのエイリアシングの理解
emp_cv2 := emp_cv1;
FETCH emp_cv1 INTO emp_rec; -- fetches first row
FETCH emp_cv1 INTO emp_rec; -- fetches second row
FETCH emp_cv2 INTO emp_rec; -- fetches third row
CLOSE emp_cv1;
DBMS_OUTPUT.put_line('The following raises an invalid cursor');
-- FETCH emp_cv2 INTO emp_rec; raises invalid cursor when get_emp_data is called
END;
BEGIN
get_emp_data(c1, c2);
END;
/
PL/SQL のサブプログラムの使用
8-25
サブプログラムのパラメータのエイリアシングの理解
8-26
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
9
PL/SQL パッケージの使用
この章では、互いに関連する PL/SQL コードとデータを 1 つのパッケージにまとめる方法につ
いて説明します。パッケージには、API を構成するプロシージャの集まりや、型定義と変数宣
言の集まりなどが考えられます。パッケージをコンパイルしてデータベースに格納し、その内
容を複数のアプリケーションで共有できます。
この章の項目は、次のとおりです。
■
PL/SQL パッケージ
■
PL/SQL パッケージのメリット
■
パッケージ仕様部の理解
■
パッケージ本体の理解
■
パッケージ機能の例
■
パッケージ STANDARD による PL/SQL 環境の定義
■
製品固有のパッケージの概要
■
パッケージ作成のガイドライン
■
パッケージでのカーソル仕様部と本体の分離
PL/SQL パッケージの使用
9-1
PL/SQL パッケージ
PL/SQL パッケージ
パッケージとは、論理的に関連する PL/SQL の型、変数およびサブプログラムをグループにま
とめたスキーマ・オブジェクトのことです。通常、パッケージは仕様部と本体の 2 つの部分で
構成されますが、本体が不要な場合もあります。仕様部はパッケージへのインタフェースです。
ここでは、型、変数、定数、例外、カーソル、およびパッケージの外から参照できるサブプロ
グラムを宣言します。本体は、カーソルの問合せとサブプログラムのコードを定義します。
仕様部はインタフェース、本体はブラック ・ボックスと考えることができます。パッケージの
仕様部を変更しなくても、本体をデバッグ、拡張または置換できます。
パッケージ仕様部を作成するには、SQL の CREATE PACKAGE 文を使用します。CREATE
PACKAGE BODY 文でパッケージ本体を定義します。SQL の CREATE PACKAGE 文の詳細は、
『Oracle Database SQL リファレンス』を参照してください。SQL の CREATE PACKAGE BODY 文
の詳細は、
『Oracle Database SQL リファレンス』を参照してください。
仕様部には、ストアド・プロシージャやその他のパッケージ外部のコードから見えるパブリッ
クな宣言を入れます。サブプログラムは、仕様部で他のすべての項目の後で最後に宣言する必
要があります(ただし、特定のファンクションの名前を指定するプラグマは、ファンクション
仕様部の後に宣言する必要があります)
。
本体には、実装の細部と、パッケージ外部のコードからは隠されているプライベートな宣言を
入れます。パッケージ本体の宣言部の後には、オプションの初期化部があります。ここには、
パッケージ変数を初期化する文と、その他の一度のみの設定を行う文を入れます。
AUTHID 句は、すべてのパッケージ・サブプログラムがその定義者(デフォルト)と実行者の
どちらの権限で実行するか、およびスキーマ・オブジェクトへの未修飾の参照が定義者と実行
者のどちらのスキーマで解決されるかを決定します。詳細は、8-15 ページの「実行者権限と定
義者権限の使用(AUTHID 句)
」を参照してください。
コール仕様を使用すると、パッケージ・サブプログラムを Java メソッドまたは外部 C ファンク
ションにマップできます。コール仕様は、Java または C 言語の名前、パラメータ型および戻り
型を対応する SQL にマップします。Java コール仕様を作成する方法は、『Oracle Database Java
開発者ガイド』を参照してください。C コール仕様を作成する方法は、
『Oracle Database アプ
リケーション開発者ガイド - 基礎編』を参照してください。
Oracle データベースに付属している PL/SQL パッケージについては、『Oracle Database
PL/SQL パッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
PL/SQL パッケージの内容
PL/SQL パッケージには、次のものが含まれています。
■
■
■
■
■
9-2
パッケージ変数の get メソッドと set メソッド。これらは他のプロシージャからの直接読
取りや書込みを避ける場合に使用します。
SQL 問合せテキストのあるカーソル宣言。同じ問合せテキストを複数の場所で再利用する
方が、同じ問合せを少しずつ変更して毎回再入力するより効率的です。また、多くの場所
で使用されている問合せを変更する必要がある場合、メンテナンスも容易になります。
例外の宣言。これらの宣言は、通常、コールされたサブプログラム内で例外を処理するた
めに、様々なプロシージャから参照できる必要があります。
相互にコールするプロシージャとファンクションの宣言。パッケージ化されたプロシー
ジャやファンクションのコンパイルの順序にとらわれる必要はありません。このため、ス
タンドアロン・ストアド・プロシージャとファンクションが互いにコールし合う場合より
も便利です。
オーバーロードされたプロシージャとファンクションの宣言。名前は同じだが異なるパラ
メータ・セットを使用する、複数のバリエーションのプロシージャまたはファンクション
を作成できます。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL パッケージのメリット
■
■
同じセッション内のプロシージャ・コール間で使用可能な状態に保つ変数。パッケージ内
でグローバル変数のように扱うことができます。
PL/SQL コレクション型の型宣言。ストアド・プロシージャまたはファンクション間でコ
レクションをパラメータとして渡すには、コール元とコール先のサブプログラムの両方で
コレクションを参照できるように、パッケージ内で型を宣言する必要があります。
詳細は、13-84 ページの「パッケージ宣言」を参照してください。PL/SQL パッケージの例につ
いては、1-13 ページの例 1-13「パッケージおよびパッケージ本体の作成」および 9-6 ページの
例 9-3 を参照してください。アプリケーションから参照およびアクセスできるのは、パッケー
ジ仕様部の宣言のみです。パッケージ本体の実装の詳細は隠ぺいされ、アクセスできません。
そのため、コールする側のプログラムを再コンパイルしなくても、本体(実装)を変更できま
す。
PL/SQL パッケージのメリット
ソフトウェア・エンジニアリングではパッケージに長い歴史があります。大規模なシステムの
チーム開発において、パッケージは信頼性のある、メンテナンスが容易で再利用可能なコード
に重要な機能を提供しています。
モジュール性
パッケージを使用すると、論理的に関連した型、項目およびサブプログラムを、名前付きの
PL/SQL モジュールにカプセル化できます。個々のパッケージは理解しやすく、パッケージ間
のインタフェースは単純かつ明快で、明確に定義されています。これはアプリケーション開発
に役立ちます。
アプリケーションの設計の容易さ
アプリケーション設計の最初の段階では、パッケージの仕様部に含まれるインタフェース情報
のみが必要です。仕様部は本体がなくてもコーディングし、コンパイルできます。仕様部のコ
ンパイルが終了すると、そのパッケージを参照するストアド・サブプログラムもコンパイルで
きます。アプリケーション作成の最終段階になるまで、パッケージ本体を完全に定義する必要
はありません。
情報の隠ぺい
パッケージを使用すると、個々の型、項目およびサブプログラムについて、それがパブリック
(可視でアクセス可能)なのか、またはプライベート(隠されていてアクセス不可)なのかを指
定できます。たとえば、パッケージに含まれる 4 つのサブプログラムのうち、3 つをパブリッ
ク、1 つをプライベートにすることもできます。パッケージはプライベートなサブプログラム
の実装を隠ぺいするため、実装が変更された場合も(アプリケーションではなく)パッケージ
のみが影響を受けます。このため、メンテナンスや機能拡張が簡単に実施できます。また、実
装上の細部をユーザーから隠ぺいすることで、パッケージの整合性を維持できます。
機能の追加
パッケージ化されたパブリック変数およびカーソルは、セッションを通じて存続します。この
ため、同じ環境の中で実行するすべてのサブプログラムで共有できます。これによって、デー
タベースに格納することなくトランザクション間でデータをメンテナンスできます。
高いパフォーマンス
パッケージ・サブプログラムを初めてコールすると、パッケージ全体がメモリーにロードされ
ます。パッケージ内の関連するサブプログラムに対する 2 度目以降のコールでは、ディスク
I/O は必要ありません。
パッケージ化すると互いに依存することがなくなるため、不要な再コンパイルを避けることが
できます。たとえば、パッケージ・ファンクションの本体を変更した場合、Oracle はそのファ
ンクションをコールする他のサブプログラムを再コンパイルしません。これらのサブプログラ
ムは仕様部で宣言されたパラメータと戻り値にのみ依存するためです。再コンパイルする必要
があるのは、仕様部が変更されたときのみです。
PL/SQL パッケージの使用
9-3
パッケージ仕様部の理解
パッケージ仕様部の理解
パッケージ仕様部にはパブリック宣言が入っています。宣言された項目は、パッケージ内のど
の場所からでも、同じスキーマ内の別のサブプログラムからでもアクセス可能です。図 9-1 に
有効範囲を示します。
図 9-1 パッケージの有効範囲
仕様部には、アプリケーションが利用できるパッケージ・リソースのリストがあります。アプ
リケーションがリソースを使用するために必要な情報は、すべて仕様部の中にあります。たと
えば、次の宣言は、factorial という名前のファンクションが INTEGER 型の引数を 1 つ取
り、INTEGER 型の値を戻すことを示しています。
FUNCTION factorial (n INTEGER) RETURN INTEGER; -- returns n!
ファンクションのコールに必要な情報はこれのみです。ユーザーは fac の下位の実装のこと
(それが反復を利用しているのか、再帰を利用しているのかなど)を考える必要がありません。
仕様部で宣言されているのが型、定数、変数、例外およびコール仕様のみであれば、パッケー
ジ本体は不要です。下位の実装を持つのは、サブプログラムとカーソルのみです。例 9-1 では、
パッケージは型、例外および変数を宣言していますが、サブプログラムまたはカーソルを持た
ないため、パッケージ本体は不要です。このようなパッケージを使用すると、セッションを通
じて存続するグローバル変数(ストアド・プロシージャ、ファンクションおよびトリガーで使
用できる)を定義できます。
例 9-1 単純なパッケージ仕様部(本体なし)
CREATE PACKAGE trans_data AS -- bodiless package
TYPE TimeRec IS RECORD (
minutes SMALLINT,
hours SMALLINT);
TYPE TransRec IS RECORD (
category VARCHAR2(10),
account INT,
amount REAL,
time_of TimeRec);
minimum_balance
CONSTANT REAL := 10.00;
number_processed INT;
insufficient_funds EXCEPTION;
END trans_data;
/
9-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
パッケージ本体の理解
パッケージの内容の参照
パッケージの仕様部で宣言された型、項目、サブプログラムおよびコール仕様部を参照すると
きには、次のようにドット表記法を使用します。
package_name.type_name
package_name.item_name
package_name.subprogram_name
package_name.call_spec_name
パッケージ内容は、データベース・トリガー、ストアド・サブプログラム、3GL アプリケー
ション・プログラムおよび様々な Oracle のツール製品から参照できます。たとえば、1-14 ペー
ジの例 1-14「パッケージのプロシージャのコール」や 9-6 ページの例 9-3 に示されているよう
にパッケージのプロシージャをコールできます。
次の例では、Pro*C プログラムの無名ブロックから hire_employee プロシージャをコールし
ています。実パラメータ emp_id、emp_lname および emp_fname はホスト変数です。
EXEC SQL EXECUTE
BEGIN
emp_actions.hire_employee(:emp_id,:emp_lname,:emp_fname, ...);
制限
リモート・パッケージ変数は、直接的にも間接的にも参照できません。たとえば、プロシー
ジャがパッケージ変数を参照する場合、データベース・リンクを通じてプロシージャをコール
することはできません。
また、パッケージ内ではホスト変数を参照できません。
パッケージ本体の理解
パッケージ本体には、パッケージ仕様部で宣言されているすべてのカーソルとサブプログラム
の実装が含まれています。パッケージ本体で定義されたサブプログラムにパッケージの外側か
らアクセスするには、その指定がパッケージ仕様部に存在している必要があります。サブプロ
グラムの仕様部がパッケージ仕様部に含まれていない場合、サブプログラムは同じパッケージ
内の他のサブプログラムからのみコールできます。パッケージ本体は、パッケージ仕様部と同
じスキーマ内にある必要があります。
サブプログラムの仕様部と本体を一致させるために、PL/SQL は、それらのヘッダーをトーク
ンごとに比較します。このため、空白を除いて、ヘッダーは一語一語が一致している必要があ
ります。一致していない場合は、PL/SQL によって例外が呼び出されます。例 9-2 を参照して
ください。
例 9-2 パッケージの仕様部と本体の一致
CREATE PACKAGE emp_bonus AS
PROCEDURE calc_bonus (date_hired employees.hire_date%TYPE);
END emp_bonus;
/
CREATE PACKAGE BODY emp_bonus AS
-- the following parameter declaration raises an exception
-- because 'DATE' does not match employees.hire_date%TYPE
-- PROCEDURE calc_bonus (date_hired DATE) IS
-- the following is correct because there is an exact match
PROCEDURE calc_bonus (date_hired employees.hire_date%TYPE) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Employees hired on ' || date_hired || ' get bonus.');
END;
END emp_bonus;
/
PL/SQL パッケージの使用
9-5
パッケージ機能の例
パッケージ本体には、パッケージの内部動作に必要な型や項目を定義するプライベート宣言を
入れることもできます。これらの宣言の有効範囲は、パッケージ本体に対してローカルです。
このため、宣言された型と項目はパッケージ本体の中からでなければアクセスできません。
パッケージ仕様部とは異なり、パッケージ本体の宣言部にはサブプログラムの本体を置くこと
ができます。
パッケージ本体の宣言部の後には、オプションの初期化部があります。ここには、一般にパッ
ケージの中で宣言済の変数を初期化する文がいくつか置かれています。
サブプログラムとは異なり、パッケージをコールすることもパッケージにパラメータを渡すこ
ともできないため、パッケージの初期化部にはあまり意味がありません。このため、パッケー
ジの初期化部は、パッケージが初めて参照されたときに一度のみ実行されます。
すでに説明したように、仕様部で宣言されているのが型、定数、変数、例外およびコール仕様
部のみであればパッケージ本体は不要です。ただしその場合でも、パッケージ本体を使用して、
パッケージ仕様部で宣言した項目を初期化できます。
パッケージ機能の例
次に示す emp_admin という名前のパッケージの例を考えます。パッケージ仕様部では、次の
ような型、項目およびサブプログラムを宣言します。
■
EmpRecTyp 型
■
カーソル desc_salary
■
例外 invalid_salary
■
ファンクション hire_employee および nth_highest_salary
■
プロシージャ fire_employee および raise_salary
パッケージを作成すると、そのパッケージの型の参照、サブプログラムのコール、カーソルの
使用、例外のコールなどを行うアプリケーションを開発できます。パッケージを作成すると、
そのパッケージは Oracle データベースに格納され、そのパッケージの実行権限を持つアプリ
ケーションから使用されます。
例 9-3 emp_admin パッケージの作成
-- create the audit table to track changes
CREATE TABLE emp_audit(date_of_action DATE, user_id VARCHAR2(20),
package_name VARCHAR2(30));
CREATE OR REPLACE PACKAGE emp_admin AS
-- Declare externally visible types, cursor, exception
TYPE EmpRecTyp IS RECORD (emp_id NUMBER, sal NUMBER);
CURSOR desc_salary RETURN EmpRecTyp;
invalid_salary EXCEPTION;
-- Declare externally callable subprograms
FUNCTION hire_employee (last_name VARCHAR2, first_name VARCHAR2,
email VARCHAR2, phone_number VARCHAR2, job_id VARCHAR2, salary NUMBER,
commission_pct NUMBER, manager_id NUMBER, department_id NUMBER)
RETURN NUMBER;
PROCEDURE fire_employee (emp_id NUMBER); -- overloaded subprogram
PROCEDURE fire_employee (emp_email VARCHAR2); -- overloaded subprogram
PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER);
FUNCTION nth_highest_salary (n NUMBER) RETURN EmpRecTyp;
END emp_admin;
/
CREATE OR REPLACE PACKAGE BODY emp_admin AS
number_hired NUMBER; -- visible only in this package
-- Fully define cursor specified in package
CURSOR desc_salary RETURN EmpRecTyp IS
SELECT employee_id, salary FROM employees ORDER BY salary DESC;
-- Fully define subprograms specified in package
9-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
パッケージ機能の例
FUNCTION hire_employee (last_name VARCHAR2, first_name VARCHAR2,
email VARCHAR2, phone_number VARCHAR2, job_id VARCHAR2, salary NUMBER,
commission_pct NUMBER, manager_id NUMBER, department_id NUMBER)
RETURN NUMBER IS
new_emp_id NUMBER;
BEGIN
SELECT employees_seq.NEXTVAL INTO new_emp_id FROM dual;
INSERT INTO employees VALUES (new_emp_id, last_name, first_name, email,
phone_number, SYSDATE, job_id, salary, commission_pct, manager_id,
department_id);
number_hired := number_hired + 1;
DBMS_OUTPUT.PUT_LINE('The number of employees hired is '
|| TO_CHAR(number_hired) );
RETURN new_emp_id;
END hire_employee;
PROCEDURE fire_employee (emp_id NUMBER) IS
BEGIN
DELETE FROM employees WHERE employee_id = emp_id;
END fire_employee;
PROCEDURE fire_employee (emp_email VARCHAR2) IS
BEGIN
DELETE FROM employees WHERE email = emp_email;
END fire_employee;
-- Define local function, available only inside package
FUNCTION sal_ok (jobid VARCHAR2, sal NUMBER) RETURN BOOLEAN IS
min_sal NUMBER;
max_sal NUMBER;
BEGIN
SELECT MIN(salary), MAX(salary) INTO min_sal, max_sal FROM employees
WHERE job_id = jobid;
RETURN (sal >= min_sal) AND (sal <= max_sal);
END sal_ok;
PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) IS
sal NUMBER(8,2);
jobid VARCHAR2(10);
BEGIN
SELECT job_id, salary INTO jobid, sal FROM employees
WHERE employee_id = emp_id;
IF sal_ok(jobid, sal + amount) THEN
UPDATE employees SET salary = salary + amount WHERE employee_id = emp_id;
ELSE
RAISE invalid_salary;
END IF;
EXCEPTION -- exception-handling part starts here
WHEN invalid_salary THEN
DBMS_OUTPUT.PUT_LINE('The salary is out of the specified range.');
END raise_salary;
FUNCTION nth_highest_salary (n NUMBER) RETURN EmpRecTyp IS
emp_rec EmpRecTyp;
BEGIN
OPEN desc_salary;
FOR i IN 1..n LOOP
FETCH desc_salary INTO emp_rec;
END LOOP;
CLOSE desc_salary;
RETURN emp_rec;
END nth_highest_salary;
BEGIN -- initialization part starts here
INSERT INTO emp_audit VALUES (SYSDATE, USER, 'EMP_ADMIN');
number_hired := 0;
END emp_admin;
/
-- calling the package procedures
PL/SQL パッケージの使用
9-7
パッケージ STANDARD による PL/SQL 環境の定義
DECLARE
new_emp_id NUMBER(6);
BEGIN
new_emp_id := emp_admin.hire_employee('Belden', 'Enrique', 'EBELDEN',
'555.111.2222', 'ST_CLERK', 2500, .1, 101, 110);
DBMS_OUTPUT.PUT_LINE('The new employee id is ' || TO_CHAR(new_emp_id) );
EMP_ADMIN.raise_salary(new_emp_id, 100);
DBMS_OUTPUT.PUT_LINE('The 10th highest salary is '||
TO_CHAR(emp_admin.nth_highest_salary(10).sal) || ', belonging to employee: '
|| TO_CHAR(emp_admin.nth_highest_salary(10).emp_id) );
emp_admin.fire_employee(new_emp_id);
-- you could also delete the newly added employee as follows:
-- emp_admin.fire_employee('EBELDEN');
END;
/
パッケージの初期化部は、パッケージが初めて参照されたときに一度のみ実行されることに注
意してください。このため、上の例の INSERT 文では、データベース表 emp_audit に挿入さ
れる行は 1 行のみです。また、変数 number_hired は一度しか初期化されません。
プロシージャ hire_employee がコールされるたびに、変数 number_hired が更新されます。
ただし、number_hired が保持しているカウントは各セッションによって異なります。つま
り、カウントは全ユーザーが処理した数ではなく、1 人のユーザーが処理した新しい従業員の
数を反映します。
PL/SQL では、パッケージ化された複数のサブプログラムに同じ名前を付けることができます。
サブプログラムで、データ型が異なるパラメータからなる類似したパラメータのセットを受け
取れるようにする場合は、この方法が便利です。たとえば、例 9-3 の emp_admin パッケージ
では fire_employee という名前の 2 つのプロシージャを定義しています。1 番目のプロシー
ジャは数値を受け取り、2 番目のプロシージャは文字列を受け取ります。ただし、どちらのプ
ロシージャもデータを適切に処理します。オーバーロードされたサブプログラムに適用される
規則については、8-10 ページの「サブプログラム名のオーバーロード」を参照してください。
パッケージのプライベート項目とパブリック項目
パッケージ emp_admin のパッケージ本体では、0(ゼロ)に初期化される変数
number_hired が宣言されています。本体で宣言される項目は、パッケージ内でしか使用でき
ません。このため、パッケージの外側の PL/SQL コードからは変数 number_hired を参照で
きません。このような項目はプライベートと呼ばれます。
例外 invalid_salary など、emp_admin の仕様部で宣言された項目は、パッケージの外から
も見えます。このため、例外 invalid_salary はどの PL/SQL コードからも参照できます。
このような項目はパブリックと呼ばれます。
セッションを通じて、または複数のトランザクションの間で維持する必要がある項目は、パッ
ケージ本体の宣言部に置くようにしてください。たとえば、number_hired の値は
hire_employee への複数のコールの間も保持されています。セッションが終了すると、値が
失われます。
パブリックにする必要がある項目は、パッケージ仕様部の中に置いてください。たとえば、
パッケージ仕様部で宣言された emp_rec は、パブリックで使用可能です。
パッケージ STANDARD による PL/SQL 環境の定義
STANDARD という名前のパッケージでは PL/SQL 環境を定義しています。このパッケージの仕
様部では、型、例外およびサブプログラムをグローバルに宣言します。それらは、自動的に
PL/SQL プログラムで使用可能になります。たとえば、パッケージ STANDARD では、引数の絶
対値を戻すファンクション ABS を次のように宣言します。
FUNCTION ABS (n NUMBER) RETURN NUMBER;
9-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
製品固有のパッケージの概要
パッケージ STANDARD の内容は、アプリケーションから直接見ることができます。その内容を
参照する場合もパッケージ名に接頭辞を付けて修飾名にする必要はありません。たとえば、
ABS はデータベース・トリガー、ストアド・サブプログラム、Oracle のツール製品または 3GL
アプリケーションから次のようにコールできます。
abs_diff := ABS(x - y);
ユーザー独自の ABS を宣言すると、ローカル宣言がグローバル宣言をオーバーライドします。
ただし、次に示すように、完全な名前を指定して、組込みファンクションをコールできます。
abs_diff := STANDARD.ABS(x - y);
ほとんどの組込みファンクションはオーバーロードされています。たとえば、パッケージ
STANDARD には次のような宣言があります。
FUNCTION
FUNCTION
FUNCTION
FUNCTION
TO_CHAR
TO_CHAR
TO_CHAR
TO_CHAR
(right DATE) RETURN VARCHAR2;
(left NUMBER) RETURN VARCHAR2;
(left DATE, right VARCHAR2) RETURN VARCHAR2;
(left NUMBER, right VARCHAR2) RETURN VARCHAR2;
PL/SQL は、仮パラメータと実パラメータの数とデータ型を比較して、どの TO_CHAR のコー
ルかを判定します。
製品固有のパッケージの概要
Oracle および Oracle の様々なツール製品には、PL/SQL、SQL、Java またはその他のプログラ
ミング環境からコールできる Application Program Interface(API)を定義した製品固有のパッ
ケージが用意されています。広く使用されているパッケージのうち、いくつかを次に示します。
詳細は、
『Oracle Database PL/SQL パッケージ・プロシージャおよびタイプ・リファレンス』
を参照してください。
DBMS_ALERT パッケージ
DBMS_ALERT パッケージでは、データベース内の特定の値が変更されたときに、データベー
ス・トリガーを使用してアプリケーションに警告できます。その警告は、トランザクション・
ベースで、非同期です(つまり、警告はタイミング・メカニズムとは無関係に作動します)
。た
とえば、会社ではこのパッケージを使用して、株や債券の取り引き価格が更新されたときに、
投資ポートフォリオの値を更新できます。
DBMS_OUTPUT パッケージ
DBMS_OUTPUT パッケージを使用すると、PL/SQL ブロック、サブプログラム、パッケージお
よびトリガーからの出力を表示できます。このパッケージは、PL/SQL デバッグ情報を表示す
る場合に特に役立ちます。PUT_LINE プロシージャは、別のトリガー、プロシージャまたは
パッケージで読み取ることができるバッファに情報を出力します。この情報は、プロシージャ
GET_LINE をコールするか、SQL*Plus に SERVEROUTPUT ON を設定することによって表示しま
す。例 9-4 に、PL/SQL ブロックからの出力の表示方法を示します。
例 9-4 DBMS_OUTPUT パッケージでの PUT_LINE の使用
REM set server output to ON to display output from DBMS_OUTPUT
SET SERVEROUTPUT ON
BEGIN
DBMS_OUTPUT.PUT_LINE('These are the tables that ' || USER || ' owns:');
FOR item IN (SELECT table_name FROM user_tables)
LOOP
DBMS_OUTPUT.PUT_LINE(item.table_name);
END LOOP;
END;
/
PL/SQL パッケージの使用
9-9
パッケージ作成のガイドライン
DBMS_PIPE パッケージ
パッケージ DBMS_PIPE を使用すると、名前付きパイプを介して異なるセッション間で通信で
きます。
(パイプとは、あるプロセスから他のプロセスに情報を渡すために使用するメモリーの
領域のことです。
)PACK_MESSAGE プロシージャと SEND_MESSAGE プロシージャを使用してパ
イプの中にメッセージをパックし、同じインスタンス内の別のセッションまたは待機中のアプ
リケーション(UNIX プログラムなど)に送信できます。
パイプのもう一端では、RECEIVE_MESSAGE プロシージャと UNPACK_MESSAGE プロシージャ
を使用して、メッセージを受信し、アンパック(読取り)できます。名前付きパイプは、あら
ゆる点で便利です。たとえば、データを収集する C プログラムを作成し、次にそれをパイプを
介して Oracle データベース内のストアド・プロシージャに送信できます。
HTF パッケージおよび HTP パッケージ
HTF パッケージおよび HTP パッケージを使用すると、PL/SQL プログラムで HTML タグを生
成できます。
UTL_FILE パッケージ
パッケージ UTL_FILE を使用すると、PL/SQL プログラムでオペレーティング・システム
(OS)のテキスト・ファイルを読み書きできます。このパッケージは、OS の標準ストリーム・
ファイル I/O の制限されたバージョン(OPEN、PUT、GET、CLOSE の操作を含む)を提供し
ます。
テキスト・ファイルの読み書きを実行する場合は、ファンクション FOPEN をコールします。こ
のファンクションは、それ以降のプロシージャ・コールで使用するためのファイル・ハンドル
を戻します。たとえば、プロシージャ PUT_LINE は、テキスト文字列と行終了文字をオープ
ン・ファイルに書き込みます。また、プロシージャ GET_LINE は、オープン・ファイルから出
力バッファにテキストの行を読み込みます。
UTL_HTTP パッケージ
UTL_HTTP パッケージを使用すると、PL/SQL プログラムで HTTP(Hypertext Transfer
Protocol)のコールアウトを実行できます。これによって、データをインターネットから取り
出すことも、Oracle Web Server カートリッジをコールすることもできます。このパッケージに
は 2 つのエントリ・ポイントがあり、各ポイントで URL(Uniform Resource Locator)を受け
取り、指定されたサイトに接続し、要求されたデータを戻します。通常このデータは HTML
(Hypertext Markup Language)形式のものです。
UTL_SMTP パッケージ
UTL_SMTP パッケージを使用すると、PL/SQL プログラムで Simple Mail Transfer Protocol
(SMTP)を介して電子メールを送信できます。パッケージには、電子メール・クライアントの
SMTP コマンドへのインタフェースがあり、電子メールを SMTP サーバーにディスパッチしま
す。
パッケージ作成のガイドライン
パッケージを作成する場合は、別のアプリケーションで再利用できるように、汎用性を持たせ
るようにしてください。オラクル社が提供するパッケージをよく理解して、すでに Oracle が提
供している機能と重複する機能を持つパッケージを作成しないように注意してください。
パッケージ本体の前にパッケージ仕様部を設計および定義してください。仕様部に入れるのは、
コール元プログラムから見える必要のあるもののみにします。こうすることで、他の開発者が
実装の細部に不適切に依存しないようにできます。
9-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
パッケージでのカーソル仕様部と本体の分離
コードの変更時に必要な再コンパイルを削減するために、パッケージ仕様部に置く項目はでき
るかぎり少なくしておきます。そうすれば、パッケージ本体を変更しても、コール元のプロ
シージャを再コンパイルする必要はありません。ただし、パッケージ仕様部を変更すると、
Oracle はそのパッケージを参照するすべてのストアド・サブプログラムを再コンパイルする必
要があります。
パッケージでのカーソル仕様部と本体の分離
パッケージの中で、カーソルの仕様部を本体と切り離して別の位置に配置できます。これに
よって、カーソルの仕様部を変更せずに、本体のみを変更できます。カーソルの構文は、13-32
ページの「カーソル宣言」を参照してください。
例 9-5 では、%ROWTYPE 属性を使用して、データベース表 employees の中の行を表すレコー
ド型を指定しています。
例 9-5 パッケージでのカーソル仕様部の分離
CREATE PACKAGE emp_stuff AS
CURSOR c1 RETURN employees%ROWTYPE; -- declare cursor spec
END emp_stuff;
/
CREATE PACKAGE BODY emp_stuff AS
CURSOR c1 RETURN employees%ROWTYPE IS
SELECT * FROM employees WHERE salary > 2500; -- define cursor body
END emp_stuff;
/
戻り値のデータ型を RETURN 句で指定しているため、カーソル仕様部には SELECT 文がありま
せん。ただしカーソル本体には、SELECT 文と、カーソル仕様部と同じ RETURN 句が必要です。
また、SELECT リスト中の項目の数とデータ型は、RETURN 句と一致する必要があります。
パッケージ・カーソルを使用すると柔軟性が向上します。たとえば、上の例では、カーソル仕
様部を変更することなく、カーソル本体を変更できます。
次の例に示すように、PL/SQL ブロックまたはサブプログラムからパッケージ・カーソルを参
照するドット表記法を使用します。
DECLARE
emp_rec employees%ROWTYPE;
BEGIN
OPEN emp_stuff.c1;
LOOP
FETCH emp_stuff.c1 INTO emp_rec;
-- do processing here ...
EXIT WHEN emp_stuff.c1%NOTFOUND;
END LOOP;
CLOSE emp_stuff.c1;
END;
/
パッケージ・カーソルの有効範囲は PL/SQL ブロックに制限されません。したがって、パッ
ケージ・カーソルをオープンすると、クローズするか、セッションから切断するまでオープン
したままになります。
PL/SQL パッケージの使用
9-11
パッケージでのカーソル仕様部と本体の分離
9-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
10
PL/SQL エラーの処理
ランタイム・エラーは、設計の失敗、コーディングの間違い、ハードウェアの障害など、多く
の原因で発生します。発生する可能性があるエラーをすべては予想できませんが、ユーザーの
PL/SQL プログラムにとって重大なエラーに対しては、処理を準備しておくことはできます。
プログラミング言語では、通常、エラー・チェックを無効にしていないかぎり、スタック・
オーバーフローや 0(ゼロ)による除算のようなランタイム・エラーが発生すると、正常な処
理が停止され、オペレーティング・システムに制御が戻ります。PL/SQL には「例外処理」と
いうメカニズムがあり、エラーが発生しても処理を続けられるように、プログラムを保護して
います。
この章の項目は、次のとおりです。
■
PL/SQL のランタイム・エラー処理の概要
■
PL/SQL 例外のメリット
■
事前定義の PL/SQL 例外のまとめ
■
独自の PL/SQL 例外の定義
■
PL/SQL 例外の呼出し
■
PL/SQL 例外の伝播
■
PL/SQL 例外の再呼出し
■
呼び出された PL/SQL 例外の処理
■
PL/SQL のコンパイル時の警告の概要
PL/SQL エラーの処理 10-1
PL/SQL のランタイム・エラー処理の概要
PL/SQL のランタイム・エラー処理の概要
PL/SQL では、エラー条件を例外と呼びます。例外には、
(実行時システムによって)内部的に
定義された例外と、ユーザーが定義した例外があります。一般的な内部例外の中には、
「0(ゼ
ロ)による除算」や「メモリー不足」などがあります。内部的に定義された例外には、
ZERO_DIVIDE や STORAGE_ERROR といった事前定義の名前を持つものもあります。それ以外
の内部例外にも名前を付けることができます。
PL/SQL ブロック、サブプログラムまたはパッケージの宣言部で、ユーザー独自の例外を定義
できます。たとえば、残高がマイナスになっている銀行口座にフラグを付けるために、
insufficient_funds という名前の例外を定義できます。内部例外とは異なり、ユーザー定
義の例外には名前を付ける必要があります。
エラーが発生すると例外が呼び出されます。つまり、通常の実行は中止され、PL/SQL ブロッ
クまたはサブプログラムの例外処理部に制御が移ります。内部例外は実行時システムによって
暗黙的(自動的)に呼び出されます。ユーザー定義の例外は RAISE 文によって明示的に呼び出
す必要があります(RAISE 文も事前定義の例外を呼び出します)。
呼び出された例外を処理するには、例外ハンドラと呼ばれる独立したルーチンを作成します。
例外ハンドラが実行されると、現在のブロックの実行を中止し、外側のブロックの次の文から
再開します。外側にブロックがない場合は、制御はホスト環境に戻ります。BULK COLLECT を
使用する場合のエラーの管理の詳細は、11-13 ページの「%BULK_EXCEPTIONS 属性を持つ
FORALL 例外の処理」を参照してください。
例 10-1 では、企業の株価収益率を計算しています。企業の収益が 0(ゼロ)の場合に除算演算
を実行すると、事前定義の例外 ZERO_DIVIDE が呼び出され、ブロックの実行が中断し、制御
が例外ハンドラに移ります。ブロックで特に名前を指定していないすべての例外は、オプショ
ンの OTHERS ハンドラで処理します。
例 10-1 ランタイム・エラー処理
DECLARE
stock_price NUMBER := 9.73;
net_earnings NUMBER := 0;
pe_ratio NUMBER;
BEGIN
-- Calculation might cause division-by-zero error.
pe_ratio := stock_price / net_earnings;
DBMS_OUTPUT.PUT_LINE('Price/earnings ratio = ' || pe_ratio);
EXCEPTION -- exception handlers begin
-- Only one of the WHEN blocks is executed.
WHEN ZERO_DIVIDE THEN -- handles 'division by zero' error
DBMS_OUTPUT.PUT_LINE('Company must have had zero earnings.');
pe_ratio := NULL;
WHEN OTHERS THEN -- handles all other errors
DBMS_OUTPUT.PUT_LINE('Some other kind of error occurred.');
pe_ratio := NULL;
END; -- exception handlers and block end here
/
上の例は例外処理を示しています。次の例に示すように、詳細なエラー・チェックを行って分
母が 0(ゼロ)の場合は答えを NULL に置き換えるようにすると、例外を完全に回避できます。
DECLARE
stock_price NUMBER := 9.73;
net_earnings NUMBER := 0;
pe_ratio NUMBER;
BEGIN
pe_ratio :=
CASE net_earnings
WHEN 0 THEN NULL
ELSE stock_price / net_earnings
end;
END;
/
10-2
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL 例外のメリット
PL/SQL エラーと例外の回避および処理のガイドライン
データベース・プログラムには信頼性が重要であるため、エラー・チェックと例外処理の両方
を使用して、プログラムがすべての可能性を処理できるようにします。
■
■
■
■
■
■
■
エラー発生の可能性がある場合は常に、例外ハンドラを追加します。算術演算、文字列操
作、データベース操作の間は、エラーが発生する可能性が特に高くなります。エラーはそ
の他の場合にも発生する可能性があります。たとえば、ディスク記憶域やメモリーのハー
ドウェア障害がコードに関係ない問題を引き起こした場合でも、コードには対処措置が必
要です。
コードが不正な入力データを受け取ることでエラー発生が予想される場合は常に、エ
ラー・チェック・コードを追加します。コードに間違ったパラメータや NULL パラメータ
が渡される場合や、問合せが行を戻さない場合、または予想以上の行を戻す場合が考えら
れます。
データベースが想定外の状態になった場合にもプログラムが安全に動作するようにします。
たとえば、問い合せた表で列の追加や削除が行われていたり、列の型が変更されている場
合があります。こうした問題を回避するには、各変数を %TYPE 修飾子で宣言し、問合せ結
果を保持するレコードを %ROWTYPE 修飾子で宣言します。
例外ハンドラで WHEN OTHERS を使用するかわりに、可能なかぎり名前付き例外を処理
します。事前定義の例外の名前と原因を調べておいてください。データベース操作によっ
て特定の ORA- エラーが発生する場合は、そのエラーに名前を付けて、それを処理するハ
ンドラを作成できるようにします。
(方法についてはこの章の後半で説明します。)
不正なデータの様々な組合せでコードをテストし、どのような潜在的なエラーが発生する
かを調べます。
デバッグ情報を例外ハンドラに記述します。個別の表にこのような情報を格納する場合も
あります。その場合は、AUTONOMOUS_TRANSACTION プラグマで宣言したプロシージャを
コールしてください。これによって、メイン・プロシージャが行っていた処理をロール
バックする場合でもデバッグ情報をコミットできます。
各例外ハンドラがトランザクションをコミットするか、ロールバックするか、継続するの
かを慎重に考慮します。エラーがどれほど重大であっても、データベースを一貫性のある
状態に保ち、不正なデータの格納を避けるようにしてください。
PL/SQL 例外のメリット
エラー処理に例外を使用すると、次のようなメリットがあります。例外を使用すると、1 つの
例外ハンドラで多くの文の潜在的なエラーを確実に処理できます。
例 10-2 1 つの例外ハンドラを使用した複数エラーの処理
DECLARE
emp_column
VARCHAR2(30) := 'last_name';
table_name
VARCHAR2(30) := 'emp';
temp_var
VARCHAR2(30);
BEGIN
temp_var := emp_column;
SELECT COLUMN_NAME INTO temp_var FROM USER_TAB_COLS
WHERE TABLE_NAME = 'EMPLOYEES' AND COLUMN_NAME = UPPER(emp_column);
-- processing here
temp_var := table_name;
SELECT OBJECT_NAME INTO temp_var FROM USER_OBJECTS
WHERE OBJECT_NAME = UPPER(table_name) AND OBJECT_TYPE = 'TABLE';
-- processing here
EXCEPTION
WHEN NO_DATA_FOUND THEN -- catches all 'no data found' errors
DBMS_OUTPUT.PUT_LINE ('No Data found for SELECT on ' || temp_var);
END;
/
PL/SQL エラーの処理 10-3
事前定義の PL/SQL 例外のまとめ
エラーが発生する可能性のある場所で逐一エラーをチェックするのではなく、単に例外ハンド
ラを PL/SQL ブロックに追加します。そうすると、そのブロック(またはサブブロック)で例
外が呼び出されたときにその例外を確実に処理できます。
エラーの発生がすぐにはわからなかったり、不正なデータで計算を実行した場合に実行後まで
エラーを検出できないこともあります。この場合も、1 つの例外ハンドラで、すべての 0(ゼ
ロ)による除算エラー、不正な配列の添字などをトラップできます。
特定の場所でエラーをチェックする必要がある場合は、独立した例外ハンドラを持つ独立した
BEGIN-END ブロックで単一の文または文のグループを囲みます。一般的なチェックを行うこと
も、厳密にチェックを行うこともできます。
エラー処理ルーチンを分離することで、プログラムの残りの部分がわかりやすく、理解しやす
くなります。
事前定義の PL/SQL 例外のまとめ
PL/SQL プログラムが Oracle の規則に違反するか、そのシステムの制限を超えると、自動的に
内部例外が呼び出されます。PL/SQL では、いくつかの一般的な Oracle エラーが例外として事
前定義されています。たとえば、SELECT INTO 文が行を戻さなかった場合は、事前定義の例外
NO_DATA_FOUND が PL/SQL によって呼び出されます。
EXCEPTION_INIT プラグマを使用して、例外名を予想される他の Oracle エラー・コードに関
連付けることができます。想定外の Oracle エラーを処理するには、OTHERS ハンドラを使用し
ます。このハンドラ内では、SQLCODE ファンクションと SQLERRM ファンクションをコールし
て、Oracle エラー・コードとメッセージ・テキストを戻すことができます。エラー・コードが
わかれば、EXCEPTION_INIT プラグマでエラー・コードを使用して、そのエラー専用のハンド
ラを作成できます。
PL/SQL では、STANDARD パッケージの中で、事前定義の例外がグローバルに宣言されていま
す。ユーザーが宣言する必要はありません。次の表に示す名前を使用すれば、事前定義の例外
を処理するハンドラを作成できます。
例外
ORA
エラー
SQLCODE
呼び出される場合
ACCESS_INTO_NULL
06530
-6530
プログラムが未初期化オブジェクトの属性に値を代入しよ
うとしたとき。
CASE_NOT_FOUND
06592
-6592
CASE 文の WHEN 句で何も選択されておらず、ELSE 句も
ない場合。
COLLECTION_IS_NULL
06531
-6531
プログラムが EXISTS 以外のコレクション・メソッドを未
初期化のネストした表または VARRAY に適用しようとし
たか、または未初期化のネストした表または VARRAY の
要素に値を代入しようとしたとき。
CURSOR_ALREADY_OPEN
06511
-6511
すでにオープンされているカーソルをオープンしようとし
たとき。カーソルをオープンするには、一度クローズする
必要があります。カーソル FOR ループは、参照するカー
ソルを自動的にオープンします。このため、ループの内側
ではカーソルをオープンできません。
DUP_VAL_ON_INDEX
00001
-1
UNIQUE 索引によって制約されている列に、重複した値
を格納しようとしたとき。
INVALID_CURSOR
01001
-1001
オープンされていないカーソルをクローズするなど、不正
なカーソル操作を実行しようとしたとき。
INVALID_NUMBER
01722
-1722
SQL 文の中で、文字列が正しい数値を表していなかった
ために、文字列から数値への変換が失敗したとき。(プロ
シージャ文では、VALUE_ERROR が呼び出されます。)こ
の例外は、バルク FETCH 文の LIMIT 句の式が正数に評価
されない場合にも呼び出されます。
10-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
事前定義の PL/SQL 例外のまとめ
例外
ORA
エラー
SQLCODE
呼び出される場合
LOGIN_DENIED
01017
-1017
不正なユーザー名またはパスワードで Oracle にログオン
しようとしたとき。
NO_DATA_FOUND
01403
+100
SELECT INTO 文が行を戻さなかったとき、ネストした表
で削除された要素を参照したとき、または索引付き表で未
初期化の要素を参照したとき。
この例外は、いくつかの SQL ファンクションで終了した
ことを通知するために内部的に使用されているため、問合
せの一部としてコールされるファンクション内部で呼び出
された場合は、この例外が伝播されても信頼しないでくだ
さい。
NOT_LOGGED_ON
01012
-1012
Oracle に接続していないプログラムが、データベース・
コールを発行した場合。
PROGRAM_ERROR
06501
-6501
PL/SQL に内部的な問題が発生した場合。
ROWTYPE_MISMATCH
06504
-6504
1 つの代入の中に含まれるホスト・カーソル変数と
PL/SQL カーソル変数の戻り型に互換性がない場合。オー
プン・ホスト・カーソル変数をストアド・サブプログラム
に渡すとき、実パラメータの戻り型と仮パラメータの戻り
型には互換性が必要です。
SELF_IS_NULL
30625
-30625
プログラムが MEMBER メソッドをコールしようとしたが、
オブジェクト型のインスタンスが初期化されていなかった
場合。つまり、組込みパラメータ SELF がオブジェクトを
指している場合です。このパラメータは、常に MEMBER メ
ソッドに最初に渡されるパラメータです。
STORAGE_ERROR
06500
-6500
PL/SQL のメモリーが足りない場合、またはメモリーが破
壊されている場合。
SUBSCRIPT_BEYOND_COUNT
06533
-6533
コレクション中の要素数より大きい索引番号を使用してネ
ストした表または VARRAY の要素を参照した場合。
SUBSCRIPT_OUTSIDE_LIMIT
06532
-6532
有効範囲外(たとえば -1)の索引番号を使用してネストし
た表または VARRAY の要素を参照した場合。
SYS_INVALID_ROWID
01410
-1410
文字列が正しい ROWID を表していなかったために、文字
列からユニバーサル ROWID への変換が失敗した場合。
TIMEOUT_ON_RESOURCE
00051
-51
Oracle がリソースを求めて待機しているときにタイムア
ウトが発生した場合。
TOO_MANY_ROWS
01422
-1422
SELECT INTO 文が複数の行を戻した場合。
VALUE_ERROR
06502
-6502
算術エラー、変換エラー、切捨てエラー、またはサイズ制
約エラーが発生した場合。たとえば、列値を選択し文字変
数に代入するときに、その値が変数の宣言された長さより
も長い場合、PL/SQL はその割当てを異常終了させて
VALUE_ERROR を呼び出します。プロシージャ文では、文
字列から数値への変換が失敗した場合に VALUE_ERROR が
呼び出されます。
(SQL 文では、INVALID_NUMBER が呼
び出されます。
)
ZERO_DIVIDE
01476
-1476
数値を 0(ゼロ)で割ろうとしたとき。
PL/SQL エラーの処理 10-5
独自の PL/SQL 例外の定義
独自の PL/SQL 例外の定義
PL/SQL ではユーザー独自の例外を定義できます。事前定義の例外とは異なり、ユーザー定義
の例外は宣言する必要があり、RAISE 文を使用して明示的に呼び出す必要があります。
PL/SQL 例外の宣言
例外は PL/SQL ブロック、サブプログラムまたはパッケージの宣言部でしか宣言できません。
例外は、例外の名前にキーワード EXCEPTION を付けて宣言します。次の例では、past_due
という名前の例外を宣言しています。
DECLARE
past_due EXCEPTION;
例外の宣言と変数の宣言は似ています。ただし、例外はデータ項目ではなく、エラー条件であ
ることを覚えておいてください。変数とは異なり、例外は代入文や SQL 文では使用できませ
ん。ただし、変数と例外の有効範囲規則は同じです。
PL/SQL 例外の有効範囲規則
同じブロックでは 1 つの例外を 2 回宣言できません。ただし、2 つの異なるブロックであれば、
同じ例外を宣言できます。
ブロックの中で宣言された例外は、そのブロックに対してローカルで、そのブロックのすべて
のサブブロックに対してグローバルであるとみなされます。ブロックはローカルまたはグロー
バルな例外しか参照できないため、サブブロックで宣言された例外を外側のブロックから参照
できません。
サブブロックでグローバルな例外を再宣言すると、ローカルの宣言が優先されます。このため、
サブブロックからはグローバルな例外を参照できません。ただし、グローバルな例外がラベル
付きのブロックで宣言されている場合は、例外の名前をブロック・ラベルで修飾すると、グ
ローバルな例外を参照できます。
block_label.exception_name
例 10-3 に、有効範囲規則を示します。
例 10-3 PL/SQL 例外の有効範囲
DECLARE
past_due EXCEPTION;
acct_num NUMBER;
BEGIN
DECLARE ---------- sub-block begins
past_due EXCEPTION; -- this declaration prevails
acct_num NUMBER;
due_date DATE := SYSDATE - 1;
todays_date DATE := SYSDATE;
BEGIN
IF due_date < todays_date THEN
RAISE past_due; -- this is not handled
END IF;
END; ------------- sub-block ends
EXCEPTION
WHEN past_due THEN -- does not handle raised exception
DBMS_OUTPUT.PUT_LINE('Handling PAST_DUE exception.');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Could not recognize PAST_DUE_EXCEPTION in this scope.');
END;
/
10-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
独自の PL/SQL 例外の定義
サブブロックの past_due の宣言が優先されるため、外側のブロックは呼び出された例外を処
理しません。この 2 つの例外は同じ past_due という名前を持っていますが、同じ名前の 2 つ
の acct_num 変数が別の変数であるのと同様に、別々の例外です。したがって、RAISE 文と
WHEN 句は別々の例外を参照しています。呼び出された例外を外側のブロックで処理するには、
サブブロックから宣言を削除するか、OTHERS ハンドラを定義する必要があります。
PL/SQL 例外と番号の関連付け : EXCEPTION_INIT プラグマ
事前定義の名前がないエラー状態(通常は ORA- メッセージ)を処理するには、OTHERS ハン
ドラまたは EXCEPTION_INIT プラグマを使用する必要があります。プラグマは、実行時では
なくコンパイル時に処理されるコンパイラ・ディレクティブです。
PL/SQL では、EXCEPTION_INIT プラグマでコンパイラに指示して、例外名と Oracle エラー
番号を関連付けます。この関連付けによって、内部例外を名前で参照し、専用のハンドラを作
成できます。エラー・スタックまたは一連のエラー・メッセージを確認する場合、一番上のエ
ラーがトラップおよび処理できるエラーです。
EXCEPTION_INIT プラグマは、PL/SQL ブロック、サブプログラムまたはパッケージの宣言部
で、次の構文を使用して指定します。
PRAGMA EXCEPTION_INIT(exception_name, -Oracle_error_number);
exception_name は事前に宣言されている例外の名前で、番号は ORA- エラー番号に対応する
負の値です。例 10-4 に示すとおり、プラグマは、同じ宣言部内の例外宣言より後に表示されま
す。
例 10-4 PRAGMA EXCEPTION_INIT の使用
DECLARE
deadlock_detected EXCEPTION;
PRAGMA EXCEPTION_INIT(deadlock_detected, -60);
BEGIN
NULL; -- Some operation that causes an ORA-00060 error
EXCEPTION
WHEN deadlock_detected THEN
NULL; -- handle the error
END;
/
独自のエラー・メッセージの定義 : RAISE_APPLICATION_ERROR プロシージャ
RAISE_APPLICATION_ERROR プロシージャを使用すると、ストアド・サブプログラムから
ユーザー定義の ORA- エラー・メッセージを発行できます。これを利用すると、アプリケー
ションに対してエラーを報告し、処理されない例外が戻されるのを回避できます。
RAISE_APPLICATION_ERROR をコールするには、次の構文を使用します。
raise_application_error(
error_number, message[, {TRUE | FALSE}]);
error_number は -20000 ~ -20999 の範囲内の負の整数で、message は長さが 2048 バイト以
内の文字列です。オプションの 3 番目のパラメータが TRUE の場合、エラーは、以前のエラー
のスタックに配置されます。そのパラメータが FALSE(デフォルト)の場合、エラーは以前の
エラーをすべて置換します。RAISE_APPLICATION_ERROR はパッケージ DBMS_STANDARD の
一部で、パッケージ STANDARD と同様に、参照する際に名前を修飾する必要はありません。
アプリケーションは、実行中のストアド・サブプログラム(またはメソッド)からのみ
raise_application_error をコールできます。raise_application_error が呼び出さ
れると、サブプログラムは終了し、ユーザー定義のエラー番号とメッセージがアプリケーショ
ンに戻されます。エラー番号とメッセージは、Oracle エラーのようにトラップさせることがで
きます。
PL/SQL エラーの処理 10-7
独自の PL/SQL 例外の定義
例 10-5 では、選択したエラー条件が発生した場合に(この例では、現行スキーマの所有する表
の数が 1000 より少ない場合に)raise_application_error を呼び出しています。
例 10-5 raise_application_error を使用したアプリケーション・エラーの呼出し
DECLARE
num_tables NUMBER;
BEGIN
SELECT COUNT(*) INTO num_tables FROM USER_TABLES;
IF num_tables < 1000 THEN
/* Issue your own error code (ORA-20101) with your own error message.
Note that you do not need to qualify raise_application_error with
DBMS_STANDARD */
raise_application_error(-20101, 'Expecting at least 1000 tables');
ELSE
NULL; -- Do the rest of the processing (for the non-error case).
END IF;
END;
/
呼出し側のアプリケーションは、PL/SQL 例外を受け取り、エラー・レポート・ファンクショ
ン SQLCODE および SQLERRM を使用して OTHERS ハンドラで処理できます。また、
EXCEPTION_INIT プラグマを使用すると、次の Pro*C 例が示すように
raise_application_error が戻す特定のエラー番号をアプリケーション独自の例外にマッ
プできます。
EXEC SQL EXECUTE
/* Execute embedded PL/SQL block using host
variables v_emp_id and v_amount, which were
assigned values in the host environment. */
DECLARE
null_salary EXCEPTION;
/* Map error number returned by raise_application_error
to user-defined exception. */
PRAGMA EXCEPTION_INIT(null_salary, -20101);
BEGIN
raise_salary(:v_emp_id, :v_amount);
EXCEPTION
WHEN null_salary THEN
INSERT INTO emp_audit VALUES (:v_emp_id, ...);
END;
END-EXEC;
この手法を使用すると、呼出し側のアプリケーションは、エラーが発生している状態を特定の
例外ハンドラで処理できます。
事前定義の例外の再宣言
PL/SQL は、事前定義の例外をパッケージ STANDARD でグローバルに宣言しているため、ユー
ザーが宣言する必要はありません。事前定義の例外を再宣言すると、ローカルな宣言がグロー
バルな宣言をオーバーライドするため、エラーが発生しやすくなります。たとえば、
invalid_number という名前の例外を宣言し、PL/SQL によって事前定義の例外
INVALID_NUMBER が内部的に呼び出された場合、INVALID_NUMBER 用に作成されたハンドラ
は内部例外を捕捉できません。この場合は、ドット表記法を使用して、次のように事前定義の
例外を指定する必要があります。
EXCEPTION
WHEN invalid_number OR STANDARD.INVALID_NUMBER THEN
-- handle the error
END;
10-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL 例外の伝播
PL/SQL 例外の呼出し
内部例外は実行時システムによって暗黙的に呼び出されます。これは、EXCEPTION_INIT を使
用して Oracle エラー番号に関連付けたユーザー定義の例外の場合も同じです。ただし、それ以
外のユーザー定義の例外は、RAISE 文で明示的に呼び出す必要があります。
RAISE 文を使用した例外の呼出し
PL/SQL ブロックおよびサブプログラムから例外を呼び出すのは、エラーが原因で処理の完了
が望ましくない場合または不可能な場合のみにする必要があります。指定した例外に対する
RAISE 文は、その例外の有効範囲の中ならば任意の場所に置くことができます。例 10-6 では、
PL/SQL ブロックで out_of_stock という名前のユーザー定義の例外を指定しています。
例 10-6 ユーザー定義の例外を強制するための RAISE の使用
DECLARE
out_of_stock
EXCEPTION;
number_on_hand NUMBER := 0;
BEGIN
IF number_on_hand < 1 THEN
RAISE out_of_stock; -- raise an exception that we defined
END IF;
EXCEPTION
WHEN out_of_stock THEN
-- handle the error
DBMS_OUTPUT.PUT_LINE('Encountered out-of-stock error.');
END;
/
事前定義の例外を明示的に呼び出すこともできます。これを利用すると、事前定義の例外のた
めに書かれた例外ハンドラで、それ以外のエラーを処理させることができます。例 10-7 に例を
示します。
例 10-7 事前定義の例外を強制するための RAISE の使用
DECLARE
acct_type INTEGER := 7;
BEGIN
IF acct_type NOT IN (1, 2, 3) THEN
RAISE INVALID_NUMBER; -- raise predefined exception
END IF;
EXCEPTION
WHEN INVALID_NUMBER THEN
DBMS_OUTPUT.PUT_LINE('HANDLING INVALID INPUT BY ROLLING BACK.');
ROLLBACK;
END;
/
PL/SQL 例外の伝播
例外が呼び出されたときに、PL/SQL がその例外のハンドラをカレント・ブロックまたはサブ
プログラムで発見できない場合、例外は伝播します。つまり、例外は外側のブロックで再生さ
れ、ハンドラが見つかるまで、または検索するブロックがなくなるまで、1 つずつ外側のブ
ロックに進んでいきます。ハンドラが見つからなかった場合、PL/SQL はホスト環境に「未処
理例外」エラーを戻します。
例外はデータベース・リンクを通じて行われるリモート・プロシージャ・コールには伝播しま
せん。そのため、PL/SQL ブロックは、リモート・サブプログラムによって呼び出された例外
を処理できません。回避策の詳細は、10-7 ページの「独自のエラー・メッセージの定義 :
RAISE_APPLICATION_ERROR プロシージャ」を参照してください。
PL/SQL エラーの処理 10-9
PL/SQL 例外の伝播
図 10-1、図 10-2 および図 10-3 に、基本的な伝播規則を示します。
図 10-1 伝播規則 : 例 1
図 10-2 伝播規則 : 例 2
10-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL 例外の再呼出し
図 10-3 伝播規則 : 例 3
例 10-8 に示すように、例外は有効範囲を超えて、つまり宣言されたブロックを超えたところま
で伝播することがあります。
例 10-8 例外の有効範囲
BEGIN
DECLARE ---------- sub-block begins
past_due EXCEPTION;
due_date DATE := trunc(SYSDATE) - 1;
todays_date DATE := trunc(SYSDATE);
BEGIN
IF due_date < todays_date THEN
RAISE past_due;
END IF;
END; ------------- sub-block ends
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;
/
例外 past_due が宣言されたブロックに例外ハンドラが存在しないため、例外は外側のブロッ
クに伝播します。ただし、宣言された有効範囲がすでに存在しないため、外側のブロックは名
前 PAST_DUE を参照できません。一度例外名が失われると、この例外を捕捉できるのは
OTHERS ハンドラにかぎられます。ユーザー定義の例外のハンドラがない場合は、呼出し側の
アプリケーションは次のエラーを受け取ります。
ORA-06510: PL/SQL: unhandled user-defined exception
PL/SQL 例外の再呼出し
例外の再呼出しとは、ローカルに処理した例外を、外側のブロックに渡すことです。たとえば、
現在のブロックでトランザクションをロールバックし、エラーを外側のブロックの中でログす
る場合があります。
例外を再度呼び出すには、RAISE 文で例外名を省略します。例外名の省略は、例外ハンドラの
中でのみ許されます。
PL/SQL エラーの処理
10-11
呼び出された PL/SQL 例外の処理
例 10-9 PL/SQL 例外の再呼出し
DECLARE
salary_too_high EXCEPTION;
current_salary NUMBER := 20000;
max_salary NUMBER := 10000;
erroneous_salary NUMBER;
BEGIN
BEGIN ---------- sub-block begins
IF current_salary > max_salary THEN
RAISE salary_too_high; -- raise the exception
END IF;
EXCEPTION
WHEN salary_too_high THEN
-- first step in handling the error
DBMS_OUTPUT.PUT_LINE('Salary ' || erroneous_salary || ' is out of range.');
DBMS_OUTPUT.PUT_LINE('Maximum salary is ' || max_salary || '.');
RAISE; -- reraise the current exception
END; ------------ sub-block ends
EXCEPTION
WHEN salary_too_high THEN
-- handle the error more thoroughly
erroneous_salary := current_salary;
current_salary := max_salary;
DBMS_OUTPUT.PUT_LINE('Revising salary from ' || erroneous_salary ||
' to ' || current_salary || '.');
END;
/
呼び出された PL/SQL 例外の処理
例外が呼び出されると、PL/SQL ブロックまたはサブプログラムの通常の実行は中止され、制
御が例外処理部に移ります。例外処理部の書式を次に示します。
EXCEPTION
WHEN exception1 THEN -- handler for exception1
sequence_of_statements1
WHEN exception2 THEN -- another handler for exception2
sequence_of_statements2
...
WHEN OTHERS THEN -- optional handler for all other errors
sequence_of_statements3
END;
呼び出された例外を処理するには、例外ハンドラを作成します。個々のハンドラは、例外を指
定する WHEN 句に、その例外が呼び出されたときに実行される一連の文を続けたものです。こ
れらの文を最後に、ブロックまたはサブプログラムの実行は終わります。制御は例外が呼び出
された箇所に戻りません。つまり、処理を中止した位置からは再開できません。
オプションの OTHERS 例外ハンドラは、必ずブロックまたはサブプログラムの最後のハンドラ
にする必要があります。OTHERS 例外ハンドラは、名前を付けなかったすべての例外のハンド
ラとして使用されます。このため、ブロックまたはサブプログラムが持てる OTHERS ハンドラ
は 1 つのみです。OTHERS ハンドラを使用すると、すべての例外が処理されます。
2 つ以上の例外で、同じ一連の文を実行する場合は、WHEN 句の中でキーワード OR で区切って
例外名を並べてください。次に例を示します。
EXCEPTION
WHEN over_limit OR under_limit OR VALUE_ERROR THEN
-- handle the error
10-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
呼び出された PL/SQL 例外の処理
リスト中の例外のいずれかが呼び出されると、それに関連する一連の文が実行されます。キー
ワード OTHERS は例外名のリストの中では使用できず、単独で使用する必要があります。例外
ハンドラの数に制限はなく、また、個々のハンドラは例外のリストを一連の文に関連付けるこ
とができます。ただし、例外名は PL/SQL ブロックまたはサブプログラムの例外処理部で一度
しか使用できません。
PL/SQL 変数の通常の有効範囲規則が適用されるため、例外ハンドラの中ではローカル変数と
グローバル変数が参照できます。ただし、カーソル FOR ループの内側で例外が呼び出される
と、ハンドラに制御が移る前にカーソルは暗黙的にクローズされます。したがって、ハンドラ
では明示カーソルの属性の値を参照できません。
宣言の中で呼び出された例外
宣言の中でも、初期化の式が間違っていると例外が呼び出される場合があります。たとえば、
次の宣言では定数 credit_limit が 999 よりも大きい数値を格納できないため、例外が呼び
出されます。
例 10-10 宣言の中での例外の呼出し
DECLARE
credit_limit CONSTANT NUMBER(3) := 5000; -- raises an error
BEGIN
NULL;
EXCEPTION
WHEN OTHERS THEN
-- Cannot catch the exception. This handler is never called.
DBMS_OUTPUT.PUT_LINE('Can''t handle an exception in a declaration.');
END;
/
宣言の中で呼び出された例外は、ただちに外側のブロックに伝播するため、現在のブロックの
中のハンドラは呼び出された例外を捕捉できません。
ハンドラの中で呼び出された例外の処理
例外ハンドラの中で例外が発生した場合、そのハンドラで例外を捕捉することはできません。
このため、ハンドラの内側で呼び出された例外はただちに外側のブロックに伝播し、そこで再
び呼び出されて、その新しい例外のハンドラが検索されます。それ以降の例外の伝播は通常ど
おりに行われます。次に例を示します。
EXCEPTION
WHEN INVALID_NUMBER THEN
INSERT INTO ...-- might raise DUP_VAL_ON_INDEX
WHEN DUP_VAL_ON_INDEX THEN ...-- cannot catch the exception
END;
例外ハンドラへの分岐と例外ハンドラからの分岐
GOTO 文では、例外ハンドラから外側のブロックに分岐できます。
ただし、GOTO 文では例外ハンドラへは分岐できません。また、例外ハンドラからカレント・ブ
ロックに分岐することもできません。
エラー・コードとエラー・メッセージの取得 : SQLCODE および SQLERRM
例外ハンドラでは、組込みファンクション SQLCODE および SQLERRM を使用して、発生したエ
ラーを確認し、関連するエラー・メッセージを取得できます。内部例外の場合、SQLCODE は
Oracle エラーの番号を戻します。SQLCODE が戻す番号は負の値ですが、Oracle エラー「デー
タが見つかりません。
」の場合は例外で、+100 が戻されます。SQLERRM は対応するエラー・
メッセージを戻します。メッセージの先頭には Oracle エラー・コードが示されています。
PL/SQL エラーの処理
10-13
呼び出された PL/SQL 例外の処理
ユーザー定義の例外の場合、SQLCODE は +1 を戻し、SQLERRM はメッセージ「ユーザー定義の
例外」を戻します。ただし、EXCEPTION_INIT プラグマを使用して例外名を Oracle エラー番
号に関連付けている場合は例外です。この場合、SQLCODE はそのエラー番号を戻し、SQLERRM
は対応するエラー・メッセージを戻します。Oracle エラー・メッセージの長さは、エラー・
コードおよびネストされたメッセージ、表や列の名前といったメッセージの挿入部分を含めて
512 文字以内です。
例外が呼び出されなければ、SQLCODE は 0(ゼロ)を戻し、SQLERRM はメッセージ
「ORA-0000: 正常に完了しました。
」を戻します。
SQLERRM にエラー番号を渡すことができます。このとき、SQLERRM はそのエラー番号に関連
付けられたメッセージを戻します。SQLERRM に渡すエラー番号は負の値にしてください。
SQLERRM に正数を渡すと、必ず「ユーザー定義の例外」というメッセージが戻されます。
+100 を渡した場合は例外で、この場合 SQLERRM は「データが見つかりません。」というメッ
セージを戻します。SQLERRM に 0(ゼロ)を渡すと、常にメッセージ「正常に完了しました。」
を戻します。
SQLCODE または SQLERRM は、SQL 文では直接使用できません。例 10-11 に示すように、値を
ローカル変数に代入してから、その変数を SQL 文の中で使用する必要があります。
例 10-11 SQLCODE および SQLERRM の表示
CREATE TABLE errors (code NUMBER, message VARCHAR2(64), happened TIMESTAMP);
DECLARE
name employees.last_name%TYPE;
v_code NUMBER;
v_errm VARCHAR2(64);
BEGIN
SELECT last_name INTO name FROM employees WHERE employee_id = -1;
EXCEPTION
WHEN OTHERS THEN
v_code := SQLCODE;
v_errm := SUBSTR(SQLERRM, 1 , 64);
DBMS_OUTPUT.PUT_LINE('Error code ' || v_code || ': ' || v_errm);
-- Normally we would call another procedure, declared with PRAGMA
-- AUTONOMOUS_TRANSACTION, to insert information about errors.
INSERT INTO errors VALUES (v_code, v_errm, SYSTIMESTAMP);
END;
/
文字列ファンクション SUBSTR を使用しているため、SQLERRM の値を err_msg に代入して
も、
(切捨ての結果として発生する)VALUE_ERROR 例外は呼び出されません。どの内部例外が
呼び出されるかを通知するファンクション SQLCODE および SQLERRM は、特に OTHERS 例外ハ
ンドラで使用すると便利です。
RESTRICT_REFERENCES プラグマを使用してストアド・ファンクションの純正度を示すときに
ファンクションが SQLCODE または SQLERRM をコールする場合は、WNPS および RNPS 制約は
指定できません。
未処理例外の捕捉
発生した例外に対応するハンドラが発見できない場合、PL/SQL はホスト環境に「例外は処理
されませんでした。
」というエラーを戻します。その結果はホスト環境によって異なります。た
とえば、Oracle プリコンパイラ環境では、失敗した SQL 文または PL/SQL ブロックがデータ
ベースに加えた変更は、すべてロールバックされます。
未処理例外はサブプログラムにも影響を与えます。サブプログラムの実行が正常終了すると、
PL/SQL は OUT パラメータに値を代入します。ただし、未処理例外が発生して実行が終了する
と、PL/SQL は OUT パラメータに値を代入しません(NOCOPY パラメータではない場合)
。ま
た、ストアド・サブプログラムで未処理例外が発生して実行が失敗した場合、PL/SQL はその
サブプログラムが実行したデータベース処理をロールバックしません。
すべての PL/SQL プログラムの最も上のレベルに OTHERS ハンドラを置くと、未処理例外の発
生を避けることができます。
10-14
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
呼び出された PL/SQL 例外の処理
PL/SQL エラーの処理のヒント
ここでは、柔軟性が高い方法について説明します。
例外が呼び出された後に実行を続ける方法
例外ハンドラを使用すると、ブロックを終了する前に致命的なエラーからリカバリできます。
ただしハンドラの実行が終了すると、ブロックの実行も終了します。例外ハンドラから現在の
ブロックに戻ることはできません。次の例で、SELECT INTO 文が ZERO_DIVIDE を呼び出した
場合、INSERT 文の実行は再開できません。
CREATE TABLE employees_temp AS
SELECT employee_id, salary, commission_pct FROM employees;
DECLARE
sal_calc NUMBER(8,2);
BEGIN
INSERT INTO employees_temp VALUES (301, 2500, 0);
SELECT salary / commission_pct INTO sal_calc FROM employees_temp
WHERE employee_id = 301;
INSERT INTO employees_temp VALUES (302, sal_calc/100, .1);
EXCEPTION
WHEN ZERO_DIVIDE THEN
NULL;
END;
/
ある文の例外を処理してから、次の文に進むことができます。この場合、独立した例外ハンド
ラを持つ独立したサブブロックに文を入れます。サブブロックでエラーが発生すると、ローカ
ルなハンドラが例外を処理します。例 10-12 に示すように、サブブロックが終了すると、外側
のブロックは、そのサブブロックの終了位置から実行を継続します。
例 10-12 例外の後に実行を続ける方法
DECLARE
sal_calc NUMBER(8,2);
BEGIN
INSERT INTO employees_temp VALUES (303, 2500, 0);
BEGIN -- sub-block begins
SELECT salary / commission_pct INTO sal_calc FROM employees_temp
WHERE employee_id = 301;
EXCEPTION
WHEN ZERO_DIVIDE THEN
sal_calc := 2500;
END; -- sub-block ends
INSERT INTO employees_temp VALUES (304, sal_calc/100, .1);
EXCEPTION
WHEN ZERO_DIVIDE THEN
NULL;
END;
/
この例では、SELECT INTO 文が ZERO_DIVIDE 例外を呼び出すと、ローカル・ハンドラが例外
を捕捉して sal_calc を 2500 に設定します。ハンドラの実行が終わり、サブブロックが終了
すると、実行は INSERT 文から続けられます。5-26 ページの例 5-38「コレクションに関する例
外」を参照してください。
また、一部で失敗した可能性がある一連の DML 操作を実行し、操作全体が完了した後で例外
を処理する方法もあります。11-13 ページの「%BULK_EXCEPTIONS 属性を持つ FORALL 例外
の処理」を参照してください。
PL/SQL エラーの処理
10-15
呼び出された PL/SQL 例外の処理
トランザクションの再試行
例外が呼び出された場合、トランザクションを中止せずに、再試行する場合があります。その
方法は、次のとおりです。
1.
トランザクションをサブブロックに入れます。
2.
そのサブブロックをループの中に入れ、トランザクションが繰り返して実行されるように
します。
3.
トランザクションを開始する前にセーブポイントをマークします。トランザクションの実
行に成功すると、コミットしてループを終了します。トランザクションの実行に失敗する
と制御は例外ハンドラに移り、例外ハンドラはセーブポイントまでロールバックして変更
をすべて取り消し、問題点を修正します。
例 10-13 では、INSERT 文で一意の列に重複する値を挿入しようとしたため、例外が呼び出さ
れます。この例では、一意である必要のある値を変更し、次のループ反復に進んでいます。
INSERT 文での挿入が正常に完了すると、ただちにループを終了します。この方法で、FOR
ループまたは WHILE ループを使用して、試行の回数を制限することをお薦めします。
例 10-13 例外の後のトランザクションの再試行
CREATE
CREATE
INSERT
INSERT
TABLE results ( res_name VARCHAR(20), res_answer VARCHAR2(3) );
UNIQUE INDEX res_name_ix ON results (res_name);
INTO results VALUES ('SMYTHE', 'YES');
INTO results VALUES ('JONES', 'NO');
DECLARE
name
VARCHAR2(20) := 'SMYTHE';
answer VARCHAR2(3) := 'NO';
suffix NUMBER := 1;
BEGIN
FOR i IN 1..5 LOOP -- try 5 times
BEGIN -- sub-block begins
SAVEPOINT start_transaction; -- mark a savepoint
/* Remove rows from a table of survey results. */
DELETE FROM results WHERE res_answer = 'NO';
/* Add a survey respondent's name and answers. */
INSERT INTO results VALUES (name, answer);
-- raises DUP_VAL_ON_INDEX if two respondents have the same name
COMMIT;
EXIT;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
ROLLBACK TO start_transaction; -- undo changes
suffix := suffix + 1;
-- try to fix problem
name := name || TO_CHAR(suffix);
END; -- sub-block ends
END LOOP;
END;
/
ロケータ変数を使用した例外の位置の識別
INSERT 文、DELETE 文または UPDATE 文のような一連の文に対して 1 つの例外ハンドラを使
用すると、エラーの原因となった文がわからなくなる場合があります。どの文が失敗したかを
知る必要がある場合は、ロケータ変数を使用します。
例 10-14 ロケータ変数を使用した例外の位置の識別
CREATE OR REPLACE PROCEDURE loc_var AS
stmt_no NUMBER;
name
VARCHAR2(100);
BEGIN
10-16
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL のコンパイル時の警告の概要
stmt_no := 1; -- designates 1st SELECT statement
SELECT table_name INTO name FROM user_tables WHERE table_name LIKE 'ABC%';
stmt_no := 2; -- designates 2nd SELECT statement
SELECT table_name INTO name FROM user_tables WHERE table_name LIKE 'XYZ%';
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Table name not found in query ' || stmt_no);
END;
/
CALL loc_var();
PL/SQL のコンパイル時の警告の概要
プログラムの安全性を高め、実行時の問題を避けるには、特定の警告条件のチェックを有効に
します。これらの条件は、エラーが発生したり、サブプログラムがコンパイルできなくなるほ
ど重大ではありません。未定義の結果を生成したり、パフォーマンス問題を発生させる可能性
のあるサブプログラム内の問題を指摘する場合もあります。
PL/SQL 警告メッセージを操作するには、PLSQL_WARNINGS 初期化パラメータ、
DBMS_WARNING パッケージおよび USER/DBA/ALL_PLSQL_OBJECT_SETTINGS ビューを使用
します。
PL/SQL の警告カテゴリ
PL/SQL 警告メッセージはカテゴリに分類されているため、よく似た警告のグループをコンパ
イル時に抑制したり、表示することができます。カテゴリは次のとおりです。
■
■
■
SEVERE: パラメータのエイリアシング問題など、予期しない動作や誤った結果が発生する
可能性がある条件のメッセージ。
PERFORMANCE: INSERT 文で NUMBER 列に VARCHAR2 値が渡される場合など、パフォーマ
ンス問題が発生する可能性がある条件のメッセージ。
INFORMATIONAL: 実行できない到達不能コードなど、パフォーマンスや正確性に影響はな
いが、コードのメンテナンス性の向上のために変更する可能性がある条件のメッセージ。
All キーワードはすべての警告メッセージを参照する簡単な方法です。
特定のメッセージを警告ではなく、エラーとして扱うこともできます。たとえば、警告メッ
セージ PLW-05003 がコードの重大な問題を表している場合、PLSQL_WARNINGS 設定に
'ERROR:05003' を含めると、条件トリガーは警告メッセージではなくエラー・メッセージ
(PLS_05003)になります。エラー・メッセージが発行されると、コンパイルは失敗します。
PL/SQL 警告メッセージの制御
PL/SQL コンパイル時にデータベースで警告メッセージを発行させるには、初期化パラメータ
PLSQL_WARNINGS を設定します。警告の全カテゴリ(ALL、SEVERE、INFORMATIONAL、
PERFORMANCE)および特定のメッセージ番号を有効または無効にできます。また、条件の修正
が必要な特定の警告をデータベースでコンパイル・エラーとして扱うこともできます。
このパラメータはシステム・レベルまたはセッション・レベルで設定できます。ALTER
PROCEDURE ...COMPILE 文に含めることによって、1 回のコンパイル用にも設定できます。開発
中にすべての警告を有効にしたり、本番のための配布時にすべての警告を無効にできます。ま
た、不要なコードやパフォーマンスなどの問題が予想される特定のサブプログラムの開発中に、
一部の警告を有効にすることもできます。
例 10-15 PL/SQL 警告の表示の制御
-- To focus on one aspect
ALTER SESSION SET PLSQL_WARNINGS='ENABLE:PERFORMANCE';
-- Recompile with extra checking
ALTER PROCEDURE loc_var COMPILE PLSQL_WARNINGS='ENABLE:PERFORMANCE'
PL/SQL エラーの処理
10-17
PL/SQL のコンパイル時の警告の概要
REUSE SETTINGS;
-- To turn off all warnings
ALTER SESSION SET PLSQL_WARNINGS='DISABLE:ALL';
-- Display 'severe' warnings, don't want 'performance' warnings, and
-- want PLW-06002 warnings to produce errors that halt compilation
ALTER SESSION SET PLSQL_WARNINGS='ENABLE:SEVERE', 'DISABLE:PERFORMANCE',
'ERROR:06002';
-- For debugging during development
ALTER SESSION SET PLSQL_WARNINGS='ENABLE:ALL';
PL/SQL サブプログラムのコンパイル中に警告メッセージが発行される場合がありますが、無
名ブロックは警告を発行しません。
PLSQL_WARNINGS パラメータの設定は、コンパイルされた各サブプログラムとともに格納され
ます。CREATE OR REPLACE 文でサブプログラムを再コンパイルする場合、そのセッションの
現在の設定が使用されます。ALTER ...COMPILE 文でサブプログラムを再コンパイルする場合
は、REUSE SETTINGS 句を文に含めるかどうかによって、現在のセッション設定か、サブプロ
ラムとともに格納した元の設定のいずれかが使用されます。詳細は、
『Oracle Database SQL リ
ファレンス』の ALTER FUNCTION、ALTER PACKAGE および ALTER PROCEDURE に関する説明
を参照してください。
コンパイル中に生成される警告を確認するには、SQL*Plus の SHOW ERRORS コマンドを使用す
るか、USER_ERRORS データ・ディクショナリ・ビューを問い合せます。すべての PL/SQL 警
告メッセージには、接頭辞 PLW が付きます。
DBMS_WARNING パッケージの使用
PL/SQL サブプログラムをコンパイルする開発環境を作成している場合、DBMS_WARNING パッ
ケージ内のサブプログラムをコールすることで、PL/SQL 警告メッセージを制御できます。複
数のネストした SQL*Plus スクリプトからなる複雑なアプリケーションでは、コンパイル時に
このパッケージを使用することで、サブプログラムごとに異なる警告設定を適用できます。こ
のパッケージを一度コールして PLSQL_WARNINGS パラメータの現在の状態を保存し、パラ
メータを変更して特定のサブプログラム・セットをコンパイルしてから、元のパラメータ値を
リストアできます。
たとえば、例 10-16 のプロシージャには、削除できる不要なコードがあります。間違いの可能
性や、デバッグ・フラグで意図的に隠された可能性もあります。したがって警告メッセージが
必要な場合も必要ない場合もあります。
例 10-16 DBMS_WARNING パッケージを使用した警告の表示
-- When warnings disabled, the following procedure compiles with no warnings
CREATE OR REPLACE PROCEDURE unreachable_code AS
x CONSTANT BOOLEAN := TRUE;
BEGIN
IF x THEN
DBMS_OUTPUT.PUT_LINE('TRUE');
ELSE
DBMS_OUTPUT.PUT_LINE('FALSE');
END IF;
END unreachable_code;
/
-- enable all warning messages for this session
CALL DBMS_WARNING.set_warning_setting_string('ENABLE:ALL' ,'SESSION');
-- Check the current warning setting
SELECT DBMS_WARNING.get_warning_setting_string() FROM DUAL;
-- Recompile the procedure and a warning about unreachable code displays
ALTER PROCEDURE unreachable_code COMPILE;
SHOW ERRORS;
10-18
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL のコンパイル時の警告の概要
例 10-16 では、DBMS_WARNINGS.set_warning_setting_string のコールなしで次の
ALTER PROCEDURE を使用できます。
ALTER PROCEDURE unreachable_code COMPILE
PLSQL_WARNINGS = 'ENABLE:ALL' REUSE SETTINGS;
詳細は、
『Oracle Database SQL リファレンス』の ALTER PROCEDURE、
『Oracle Database
PL/SQL パッケージ・プロシージャおよびタイプ・リファレンス』の DBMS_WARNING パッ
ケージおよび『Oracle Database エラー・メッセージ』の PLW- メッセージに関する説明を参照
してください。
PL/SQL エラーの処理
10-19
PL/SQL のコンパイル時の警告の概要
10-20
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
11
PL/SQL アプリケーションのパフォーマンスの
チューニング
この章では、効率的な PL/SQL コードを記述する方法および既存のコードを高速化する方法に
ついて説明します。
この章の項目は、次のとおりです。
■
PL/SQL コンパイル用の初期化パラメータ
■
PL/SQL でプログラムを最適化する方法
■
PL/SQL のパフォーマンス問題を回避するためのガイドライン
■
PL/SQL プログラムのプロファイルおよびトレース
■
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
■
PL/SQL での計算集中型プログラムの記述
■
EXECUTE IMMEDIATE およびカーソル変数を使用した動的 SQL のチューニング
■
NOCOPY コンパイラ・ヒントを使用した PL/SQL プロシージャ・コールのチューニング
■
システム固有の実行のための PL/SQL コードのコンパイル
■
パイプライン・ファンクションによる変換の設定
参照 :
■
PL/SQL パフォーマンス・チューニングの詳細は、次の URL を参照し
てください。
http://www.oracle.com/technology/tech/pl_sql/htdocs/new
_in_10gr1.htm
■
PL/SQL アプリケーションのチューニングの詳細は、Oracle
Technology Network(OTN)を参照してください。
http://www.oracle.com/technology/tech/pl_sql/
■
「Best Practice PL/SQL」などの、OTN の特定の項目の情報にアクセ
スするには、次の URL で OTN メイン・ページの検索フィールドに適
切な語句を入力してください。
http://www.oracle.com/technology/
■
Oracle 10g の PL/SQL コンパイラの変更については、次を参照してく
ださい。
xxiv ページの「パフォーマンスの向上」
PL/SQL アプリケーションのパフォーマンスのチューニング
11-1
PL/SQL コンパイル用の初期化パラメータ
PL/SQL コンパイル用の初期化パラメータ
PL/SQL ユニットのコンパイル時には、いくつかの Oracle 初期化パラメータが使用されます。
このような PL/SQL コンパイラ・パラメータには、PLSQL_CCFLAGS、PLSQL_CODE_TYPE、
PLSQL_DEBUG、PLSQL_NATIVE_LIBRARY_DIR、
PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT、PLSQL_OPTIMIZE_LEVEL、PLSQL_WARNINGS、
NLS_LENGTH_SEMANTICS があります。初期化パラメータの詳細は、『Oracle Database リファ
レンス』を参照してください。
PLSQL_CCFLAGS、PLSQL_CODE_TYPE、PLSQL_DEBUG、PLSQL_OPTIMIZE_LEVEL、
PLSQL_WARNINGS、NLS_LENGTH_SEMANTICS の各初期化パラメータのコンパイル時の値は、
ユニットのメタデータとともに格納されます。これらのパラメータの設定に関する情報は、
ALL_PLSQL_OBJECT_SETTINGS ビューで参照できます。詳細は、『Oracle Database リファレ
ンス』を参照してください。
SQL の ALTER 文で REUSE SETTINGS を指定すると、ユニットのメタデータに格納されている
値を保持できます。ALTER 文での PL/SQL コンパイラ・パラメータの使用の詳細は、『Oracle
Database SQL リファレンス』で ALTER FUNCTION 文、ALTER PACKAGE 文、ALTER
PROCEDURE 文および ALTER SESSION 文を参照してください。
PL/SQL でプログラムを最適化する方法
10g より前の Oracle リリースでは、PL/SQL コンパイラは、パフォーマンスを最適化するため
の変更を行うことなく、作成されたコードを機械コードに変換していました。今回のリリース
の PL/SQL では、コードのパフォーマンスが向上するように再調整する機能を持つ最適化コン
パイラが使用されます。
この新しいオプティマイザを利用するための特別な操作は必要ありません。このオプティマイ
ザは、デフォルトで使用可能です。まれに、オプティマイザのオーバーヘッドによって、非常
に大規模なアプリケーションをコンパイルするときに時間が長くかかる場合があります。この
場合、初期化パラメータ PLSQL_OPTIMIZE_LEVEL=1 を設定して(デフォルト値は 2)、最適
化レベルを低くすることもできます。また、非常にまれですが、例外動作が変更されて、例外
が発生しなくなったり、予測よりも早く例外が発生するようになる場合もあります。
PLSQL_OPTIMIZE_LEVEL=0 に設定すると、コードは再調整されません。
PLSQL_OPTIMIZE_LEVEL 初期化パラメータの詳細は、『Oracle Database リファレンス』を参
照してください。
ご使用の環境の最適化レベルおよびその他の PL/SQL コンパイラ設定については、
ALL_PLSQL_OBJECT_SETTINGS ビューで参照できます。詳細は、『Oracle Database リファレ
ンス』を参照してください。
PL/SQL コードをチューニングする場合
この章では、特に次の条件に該当する場合に有効な情報について説明します。
■
■
■
11-2
数学の計算を大量に実行するプログラム。PLS_INTEGER、BINARY_FLOAT および
BINARY_DOUBLE データ型について検討します。
PL/SQL 問合せからコールされ、数百万回実行される可能性があるファンクション。ファ
ンクションをできるだけ効率的にするために、すべてのパフォーマンス機能を検討します。
また、各行の結果を事前に計算して問合せ時間を短縮するファンクション索引について検
討することをお薦めします。
INSERT 文、UPDATE 文または DELETE 文の処理、あるいは問合せのループに長時間を費や
すプログラム。DML を発行する場合は FORALL 文、問合せの場合は BULK COLLECT
INTO 句および RETURNING BULK COLLECT INTO 句について検討します。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL のパフォーマンス問題を回避するためのガイドライン
■
■
最新の PL/SQL 言語機能を利用していない古いコード。Oracle Database 10g では多くの点
でパフォーマンスが改善されたため、以前のリリースのコードはすべてチューニングの対
象になります。
SQL に直接渡されるだけの DDL 文(CREATE TABLE など)を発行するのではなく、
PL/SQL 処理に長時間を費やすプログラム。ネイティブ・コンパイルについて検討します。
PL/SQL は多くの組込みデータベース機能で使用されるため、このチューニング機能を
データベース全体に適用して、自分のコードのみでなく、多くの面でパフォーマンスを改
善できます。
チューニングに取りかかる前に、現在のシステムで、個々のサブプログラムの実行時間を計測
します。Oracle Database 10g の PL/SQL には、多くの自動最適化機能があるため、チューニン
グしなくても、パフォーマンスが改善する場合があります。
PL/SQL のパフォーマンス問題を回避するためのガイドライン
PL/SQL ベースのアプリケーションのパフォーマンスが十分でない場合、その原因は通常、不
適切な SQL 文の記述、プログラミング慣習の不徹底、PL/SQL の基本に対する不注意、共有メ
モリーの間違った使用などが考えられます。
PL/SQL コードでの CPU オーバーヘッドの回避
この項では、PL/SQL コードが原因で CPU に過度にオーバーヘッドがかかるのを回避するため
の方法について説明します。
SQL 文の最大限の効率化
PL/SQL プログラムは比較的単純に見えますが、これは、ほとんどの処理が SQL 文で実行され
るためです。処理が低速な SQL 文は、実行が低速になる主な原因となります。
SQL 文によってプログラムが低速になる場合は、次の手順を試します。
■
■
■
■
適切な索引を使用していることを確認します。状況に応じて、使用する索引の種類は異な
ります。索引の使用方法は、問合せでの様々な表のサイズ、各問合せでのデータの配布、
および WHERE 句で使用される列によって異なる場合があります。
DBMS_STATS パッケージのサブプログラムを使用して、すべての表について最新の統計が
存在することを確認します。
次のものを使用して、実行計画および SQL 文のパフォーマンスを分析します。
■
EXPLAIN PLAN 文
■
TKPROF ユーティリティを持つ SQL トレース機能
必要に応じて、SQL 文を記述しなおします。たとえば、問合せヒントを使用すると、不要
な全表スキャンなどの問題を回避できます。
これらの方法の詳細は、
『Oracle Database パフォーマンス・チューニング・ガイド』を参照し
てください。
次に示すように、PL/SQL 機能を利用して SQL 文のパフォーマンスを改善できる場合もありま
す。
■
■
PL/SQL ループ内で SQL 文を実行している場合、INSERT 文、UPDATE 文および DELETE 文
のループのかわりに、FORALL 文を使用することを検討します。
問合せの結果セットをループしている場合、単一の操作で結果セット全体をメモリーに格
納する方法として、SELECT INTO 文の BULK COLLECT 句を使用することを検討します。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-3
PL/SQL のパフォーマンス問題を回避するためのガイドライン
ファンクション・コールの最大限の効率化
不適切に記述されたサブプログラム(低速のソートや検索機能など)によって、パフォーマン
スが低下する場合があります。次に示すように、サブプログラムに対する不要なコールを回避
して、コードを最適化します。
■
■
SQL 問合せ内でファンクションがコールされる場合、問合せ時に表にファンクション索引
を作成することで、行ごとにファンクション値をキャッシュできます。CREATE INDEX 文
には少し時間がかかる場合もありますが、問合せは非常に高速になる可能性があります。
SQL 問合せ内で列がファンクションに渡される場合、問合せではその列上で通常の索引を
使用できません。また、ファンクションが(非常に大きい可能性がある)表の行ごとに
コールされる可能性があります。例 11-1 に示すように、問合せをネストして、内側の問合
せで問合せ結果が少ない行数になるようにフィルタリングし、外側の問合せでファンク
ションが数回のみコールされるようにすることを検討します。
例 11-1 問合せのネストによるパフォーマンス改善
BEGIN
-- Inefficient, calls function for every row
FOR item IN (SELECT DISTINCT(SQRT(department_id)) col_alias FROM employees)
LOOP
DBMS_OUTPUT.PUT_LINE(item.col_alias);
END LOOP;
-- Efficient, only calls function once for each distinct value.
FOR item IN
( SELECT SQRT(department_id) col_alias FROM
( SELECT DISTINCT department_id FROM employees)
)
LOOP
DBMS_OUTPUT.PUT_LINE(item.col_alias);
END LOOP;
END;
/
OUT パラメータまたは IN OUT パラメータを使用する場合、PL/SQL は、例外が発生した場合
に正しく動作するように、パフォーマンスのオーバーヘッドを追加します(OUT パラメータの
元の値が保たれるように、OUT パラメータに値を割り当てた後で、未処理例外のためにサブプ
ログラムを終了します)
。
作成するプログラムにおいて、このような状況で OUT パラメータの値を保持する必要がない場
合、NOCOPY キーワードをパラメータ宣言に追加して、パラメータを OUT NOCOPY または IN
OUT NOCOPY と宣言できます。
この手法を使用すると、コレクション、大きい VARCHAR2 値、LOB などの大量のデータを OUT
パラメータに渡す場合の処理を、大幅に高速化することができます。
また、この手法は、オブジェクト型のメンバー・メソッドにも適用できます。このメソッドが
オブジェクト型の属性を変更する場合、すべての属性は、サブプログラムが終了するときにコ
ピーされます。このオーバーヘッドを回避するには、PL/SQL の暗黙的な宣言である SELF IN
OUT を使用するのではなく、メンバー・メソッドの最初のパラメータを SELF IN OUT NOCOPY
として明示的に宣言します。オブジェクト・メソッドの設計上の考慮事項の詳細は、
『Oracle
Database アプリケーション開発者ガイド - オブジェクト・リレーショナル機能』を参照してく
ださい。
ループの最大限の効率化
PL/SQL アプリケーションはループの周囲に構築されることが多いため、次に示すように、
ループ自体およびループ内のコードを最適化することは重要です。
■
■
11-4
一連の DML 文を発行するために、ループ構造を FORALL 文で置換します。
結果セットをループして値を格納するかわりに、問合せで BULK COLLECT 句を使用して、
単一の操作で問合せ結果をメモリーに格納します。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL のパフォーマンス問題を回避するためのガイドライン
■
■
結果セットを 2 回以上ループしたり、結果セットのループ時に他の問合せを発行する必要
がある場合、元の問合せを改善して、目的の結果を正確に取得することが可能な場合があ
ります。UNION、INTERSECT、MINUS および CONNECT BY 問合せ演算子の使用を検討し
ます。
問合せを他の問合せ内にネストして(副問合せという)
、複数の段階でフィルタリングおよ
びソートを行うこともできます。たとえば、内側の WHERE 句で PL/SQL ファンクション
をコールすると、表の各行でファンクションが毎回コールされる可能性があります。かわ
りに、内側の問合せで結果セットが少ない行数になるようにフィルタリングして、外側の
問合せでファンクションをコールすることができます。
組込み文字列ファンクションの使用
PL/SQL には、REPLACE、TRANSLATE、SUBSTR、INSTR、RPAD、LTRIM などの高度に最適
化された文字列ファンクションが多数用意されています。これらの組込みファンクションは、
通常の PL/SQL よりも効率的な低レベルのコードを使用します。
正規表現の検索に PL/SQL の文字列ファンクションを使用する場合、REGEXP_SUBSTR などの
組込み正規表現ファンクションを使用することを検討します。
■
■
正規表現による検索には、SQL 演算子 REGEXP_LIKE を使用します。6-9 ページの例 6-10 を
参照してください。
文字列のテストまたは操作には、組込みファンクション REGEXP_INSTR、
REGEXP_REPLACE および REGEXP_SUBSTR を使用します。
Oracle の正規表現機能では、UNIX や Perl プログラミングでも使用される「.」
、「*」
、「^」、
「$」
などの文字を使用します。多言語用のプログラミングの場合、その他の拡張機能も使用できま
す。たとえば、小文字の検索で、アクセント記号付きの小文字には一致しない [a-z] のかわり
に、[:lower:] を使用できます。
参照 : Oracle Technology Network(OTN)の「Oracle By Example Using Regular Expressions」
http://www.oracle.com/technology/obe/obe10gdb/develop/r
egexp/regexp.htm
条件テストにおける最低コストの条件の先頭への配置
PL/SQL は、結果が判別できた時点でただちに論理式の評価を停止します。この機能は、短絡
評価と呼ばれるものです。2-21 ページの「短絡評価」を参照してください。
AND または OR で指定された複数の条件を評価する場合、最低コストの条件を最初に配置しま
す。たとえば、ファンクションの戻り値をテストする前に、PL/SQL 変数の値を確認します。
これは、PL/SQL がファンクションのコールをスキップできる場合があるためです。
データ型変換の回数の最少化
PL/SQL は実行時に、異なるデータ型を自動的に変換します。たとえば、PLS_INTEGER 変数
を NUMBER 変数に代入すると、両者の内部表現は異なるため、変換が実行されます。
データ型は、暗黙的な変換が最小限に抑えられるように慎重に選択してください。文字式では
文字リテラル、数式では小数など、適切な型のリテラルを使用します。
変換の回数を可能なかぎり減らすには、変数の型を変更したり、異なるデータ型で表を設計し
なおすことが必要となる場合があります。また、データを一度変換(INTEGER 列から
PLS_INTEGER 変数への変換など)した後は、一貫してその PL/SQL 型を使用することもでき
ます。INTEGER から PLS_INTEGER データ型に変換すると、より効率の良いハードウェア算術
計算が使用されるため、実際のパフォーマンスを向上できる場合があります。11-6 ページの
「整数の算術計算での PLS_INTEGER の使用」を参照してください。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-5
PL/SQL のパフォーマンス問題を回避するためのガイドライン
整数の算術計算での PLS_INTEGER の使用
ローカル整変数を宣言する必要がある場合は、PLS_INTEGER データ型を使用します。
PLS_INTEGER は、最も効率的な整数型です。PLS_INTEGER 変数は、INTEGER 値または
NUMBER 値より格納サイズが小さく、PLS_INTEGER 演算ではマシン算術計算が使用されます。
BINARY_INTEGER データ型は、PLS_INTEGER と同じです。
NUMBER 型とそのサブタイプは特殊な内部形式で表され、パフォーマンスよりも移植性および
任意の位取りと精度に重点を置いて設計されています。INTEGER サブタイプの場合も、小数点
以下がない浮動小数点数として扱われます。NUMBER 変数または INTEGER 変数の演算では、ラ
イブラリ・ルーチンへのコールが必要です。
パフォーマンスを重視するコードでは、INTEGER、NATURAL、NATURALN、POSITIVE、
POSITIVEN、SIGNTYPE などの、制約付きのサブタイプを使用しないようにします。この型の
変数を計算で使用すると、実行時に余分なチェックが必要となります。
浮動小数点の算術計算での BINARY_FLOAT および BINARY_DOUBLE の使用
NUMBER 型とそのサブタイプは特殊な内部形式で表され、パフォーマンスよりも移植性および
任意の位取りと精度に重点を置いて設計されています。NUMBER 変数または INTEGER 変数の演
算では、ライブラリ・ルーチンへのコールが必要です。
BINARY_FLOAT 型および BINARY_DOUBLE 型では、システム固有のマシン算術計算命令を使
用することができ、科学的な処理など、大量の演算を行うアプリケーションではより適してい
ます。また、これらの型の方が、データベースで必要な領域が少なくて済みます。
これらの型は、常に正確に小数値を表すわけではなく、NUMBER 型とは異なる四捨五入処理が
行われます。これらの型は、正確さが非常に重要な財務処理コードにはあまり適していません。
PL/SQL コードでのメモリー・オーバーヘッドの回避
この項では、PL/SQL コードが原因でメモリーに過度にオーバーヘッドがかかるのを回避する
ための方法について説明します。
VARCHAR2 変数宣言時の大きいサイズの指定
式の結果がどの程度のサイズになるかが不明な場合、VARCHAR2 変数に大きいサイズを割り当
てる必要がある場合があります。VARCHAR2 変数を宣言する際に、256 や 1000 などのやや大き
いサイズを予測して指定するよりも、32000 などの大きいサイズを指定する方が、実際にはメ
モリーを節約できます。PL/SQL の最適化機能によって、簡単にオーバーフローの問題を回避
し、同時にメモリーも節約できます。VARCHAR2 型変数には、4000 文字以上のサイズを指定し
ます。PL/SQL は、変数が割り当てられるまで待機し、必要な量の記憶域のみを割り当てます。
関連するサブプログラムのパッケージへのグループ化
パッケージ・サブプログラムを初めてコールすると、パッケージ全体が共有メモリー・プール
にロードされます。パッケージ内の関連するサブプログラムに対する 2 度目以降のコールでは、
ディスク I/O が必要ないため実行速度が向上します。パッケージがメモリーからエージ・アウ
トされた場合は、再参照する前に再ロードする必要があります。
共有メモリー・プールのサイズを適切に設定すると、パフォーマンスを改善できます。頻繁に
使用するパッケージを十分に保持でき、しかもメモリーが浪費されないサイズになるように設
定してください。
共有メモリー・プールでのパッケージの確保
オラクル社が提供するパッケージ DBMS_SHARED_POOL を使用すると、頻繁にアクセスする
パッケージを共有メモリー・プールに確保できます。パッケージを確保すると、Oracle で通常
使用される LRU(Least Recently Used)アルゴリズムでもエージ・アウトされることはありま
せん。パッケージは、プールの占有状態やパッケージへのアクセス頻度に関係なく、メモリー
に残ります。
DBMS_SHARED_POOL パッケージの詳細は、
『Oracle Database PL/SQL パッケージ・プロシー
ジャおよびタイプ・リファレンス』を参照してください。
11-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL プログラムのプロファイルおよびトレース
コンパイラの警告を回避するためのコードの改善
PL/SQL のコンパイラは、プログラムは動作しても、パフォーマンスが低くなる可能性がある
場合に、警告を発行します。このような警告を受け取った場合、パフォーマンスが重要なコー
ドでは、警告のアドバイスに従ってコードを変更し、コードをより効率的にします。
PL/SQL プログラムのプロファイルおよびトレース
開発する PL/SQL アプリケーションが大きくなるほど、パフォーマンスの問題を切り出すのは
困難になります。PL/SQL には、実行時の動作をプロファイルし、パフォーマンスのボトル
ネックを識別できるように、プロファイラ API が用意されています。また、サーバー上でプロ
グラムの実行をトレースするためのトレース API もあります。Oracle Trace を使用すると、サ
ブプログラム別または例外ごとに実行をトレースできます。
プロファイラ API の使用 : DBMS_PROFILER パッケージ
プロファイラ API は、PL/SQL パッケージ DBMS_PROFILER として実装され、ランタイム統計
を収集して保存するサービスを提供します。情報はデータベース表に格納され、後で問合せで
きます。たとえば、PL/SQL の各行とサブプログラムの実行にかかる所要時間を知ることがで
きます。
プロファイラを使用するには、プロファイル・セッションを開始し、十分な範囲のコードを取
得できるまでアプリケーションを実行し、収集されたデータをデータベースにフラッシュし、
プロファイル・セッションを停止します。
プロファイラによって、プログラムの実行がトレースされ、各行および各サブプログラムの所
要時間が計算されます。収集されたデータを使用してパフォーマンスを改善できます。たとえ
ば、低速のサブプログラムに改善の重点を置くことができます。DBMS_PROFILER サブプログ
ラムの詳細は、
『Oracle Database PL/SQL パッケージ・プロシージャおよびタイプ・リファレ
ンス』を参照してください。
プロファイラでデータを収集したら、次の操作を実行できます。
■
収集したパフォーマンス・データの分析
特定のコード・セグメントの実行や特定のデータ構造へのアクセスに、他よりも時間がか
かっている原因を判断します。パフォーマンス・データを問い合せて問題を探します。ほ
とんどの実行時間を占めているサブプログラムやパッケージに重点を置いて、SQL 文、
ループ、再帰ファンクションなど、考えられるパフォーマンスのボトルネックを調べてく
ださい。
■
トレース・データを使用したパフォーマンス改善
分析結果に基づいて低速のアルゴリズムを書き直します。たとえば、データが急増したた
めに、線形検索をバイナリ検索に置き換える必要が出てくることがあります。また、不適
切なデータ構造によって生じた非効率な部分を探し、必要に応じてそのデータ構造を置き
換えてください。
トレース API の使用 : DBMS_TRACE パッケージ
大規模で複雑なアプリケーションの場合は、サブプログラム間のコールを追跡するのは困難で
す。トレース API でコードをトレースすると、サブプログラムの実行順序を確認できます。ト
レース API は PL/SQL パッケージ DBMS_TRACE として実装され、サブプログラムまたは例外
ごとに実行をトレースするサービスを提供します。
トレースを使用するには、トレース・セッションを開始し、アプリケーションを実行してから、
トレース・セッションを停止します。プログラムを実行すると、トレース・データが収集され、
データベース表に格納されます。
DBMS_TRACE サブプログラムの詳細は、
『Oracle Database PL/SQL パッケージ・プロシージャ
およびタイプ・リファレンス』を参照してください。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-7
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
トレースの制御
大規模なアプリケーションをトレースすると、大量のデータが生成されて管理が困難になるこ
とがあります。必要であれば、トレースを起動する前に、トレース・データ収集用の特定のサ
ブプログラムを選択し、収集されるデータ量を制限できます。
また、トレース・レベルも選択できます。たとえば、すべてのサブプログラムと例外をトレー
スするか、選択したサブプログラムと例外をトレースするように指定できます。
バルク SQL による、DML
文および問合せのループ・オーバー
による、
ヘッドの削減
PL/SQL は、DML や問合せなどの SQL 文を SQL エンジンへ送信して実行します。SQL は、結
果データを PL/SQL に戻します。バルク SQL と総称される PL/SQL 言語機能を使用すること
によって、この PL/SQL と SQL 間の通信において、パフォーマンスのオーバーヘッドを最小化
できます。FORALL 文を使用すると、INSERT 文、UPDATE 文または DELETE 文が、1 文ずつで
はなく、バッチで送信されます。BULK COLLECT 句を使用すると、結果が SQL からバッチで戻
されます。DML 文が 4 つ以上のデータベース行に影響する場合は、バルク SQL を使用すると
パフォーマンスが向上します。
値を PL/SQL 変数に SQL 文で代入することを、バインドと呼びます。PL/SQL バインド操作
は、3 つのカテゴリに分類されます。
■
■
■
インバインド : PL/SQL 変数またはホスト変数が、INSERT 文または UPDATE 文によって
データベースに格納される場合。
アウトバインド : データベースの値が、INSERT 文、UPDATE 文または DELETE 文の
RETURNING 句によって PL/SQL 変数またはホスト変数に代入される場合。
定義 : データベースの値が、SELECT 文または FETCH 文によって PL/SQL 変数またはホスト
変数に代入される場合。
バルク SQL は、VARRAY やネストした表などの PL/SQL コレクションを使用して、大量の
データを単一の操作でやり取りします。この処理をバルク・バインドと呼びます。コレクショ
ンに 20 個の要素がある場合、バルク・バインドは単一の操作で、20 回分の SELECT 文、
INSERT 文、UPDATE 文または DELETE 文に相当する処理を実行できます。問合せでは、任意
の数の結果を戻すことができ、行ごとに FETCH 文を指定する必要はありません。
INSERT 文、UPDATE 文および DELETE 文をスピードアップするには、ループ構造ではなく
PL/SQL の FORALL 文内に SQL 文を記述します。
SELECT 文をスピードアップするには、SELECT 文で、INTO を使用するかわりに BULK
COLLECT INTO 句を指定します。
これらの文に関する構文と制限の詳細は、13-55 ページの「FORALL 文」および 13-105 ページ
の「SELECT INTO 文」を参照してください。
FORALL 文の使用
キーワード FORALL を使用すると、複数の DML 文を非常に効率的に実行できます。汎用目的
の FOR ループとは異なり、1 つの DML 文のみを繰り返すことができます。完全な構文と制約
については、13-55 ページの「FORALL 文」を参照してください。
この SQL 文では複数のコレクションを参照できますが、索引値が添字として使用される場合の
み、FORALL によってパフォーマンスが改善されます。
通常、境界には連続した索引番号の範囲を指定します。コレクション要素を削除した後などに
索引番号が連続していない場合、INDICES OF 句または VALUES OF 句を使用して、実際に存
在する索引値のみを反復できます。
INDICES OF 句は、指定したコレクションの索引値全体、または下限から上限の境界内の索引
値のみを反復します。
11-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
VALUES OF 句は、BINARY_INTEGER 型または PLS_INTEGER 型によって索引付けされ、要素
が BINARY_INTEGER 型または PLS_INTEGER 型であるコレクションを参照します。FORALL
文は、このコレクションの要素によって指定される索引値を反復します。
例 11-2 の FORALL 文では、3 つの DELETE 文を一度にまとめて SQL エンジンに送信していま
す。
例 11-2 ループでの DELETE 文の発行
CREATE TABLE employees_temp AS SELECT * FROM employees;
DECLARE
TYPE NumList IS VARRAY(20) OF NUMBER;
depts NumList := NumList(10, 30, 70); -- department numbers
BEGIN
FORALL i IN depts.FIRST..depts.LAST
DELETE FROM employees_temp WHERE department_id = depts(i);
COMMIT;
END;
/
例 11-3 では、一部のデータを PL/SQL コレクションにロードします。次に、コレクション要素
をデータベース表に 2 回挿入しています。1 回目は FOR ループを使用し、2 回目は FORALL 文
を使用します。FORALL を使用する方が高速です。
例 11-3 ループでの INSERT 文の発行
CREATE TABLE parts1 (pnum INTEGER, pname VARCHAR2(15));
CREATE TABLE parts2 (pnum INTEGER, pname VARCHAR2(15));
DECLARE
TYPE NumTab IS TABLE OF parts1.pnum%TYPE INDEX BY PLS_INTEGER;
TYPE NameTab IS TABLE OF parts1.pname%TYPE INDEX BY PLS_INTEGER;
pnums NumTab;
pnames NameTab;
iterations CONSTANT PLS_INTEGER := 500;
t1 INTEGER;
t2 INTEGER;
t3 INTEGER;
BEGIN
FOR j IN 1..iterations LOOP -- load index-by tables
pnums(j) := j;
pnames(j) := 'Part No. ' || TO_CHAR(j);
END LOOP;
t1 := DBMS_UTILITY.get_time;
FOR i IN 1..iterations LOOP -- use FOR loop
INSERT INTO parts1 VALUES (pnums(i), pnames(i));
END LOOP;
t2 := DBMS_UTILITY.get_time;
FORALL i IN 1..iterations -- use FORALL statement
INSERT INTO parts2 VALUES (pnums(i), pnames(i));
t3 := DBMS_UTILITY.get_time;
DBMS_OUTPUT.PUT_LINE('Execution Time (secs)');
DBMS_OUTPUT.PUT_LINE('---------------------');
DBMS_OUTPUT.PUT_LINE('FOR loop: ' || TO_CHAR((t2 - t1)/100));
DBMS_OUTPUT.PUT_LINE('FORALL: ' || TO_CHAR((t3 - t2)/100));
COMMIT;
END;
/
このブロックを実行すると、FORALL を使用するループの方が高速であることがわかります。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-9
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
例 11-4 に示すように、FORALL ループの境界は、必ずしもすべての要素に適用する必要はなく、
コレクションの一部に適用できます。
例 11-4 コレクションの一部での FORALL の使用
CREATE TABLE employees_temp AS SELECT * FROM employees;
DECLARE
TYPE NumList IS VARRAY(10) OF NUMBER;
depts NumList := NumList(5,10,20,30,50,55,57,60,70,75);
BEGIN
FORALL j IN 4..7 -- use only part of varray
DELETE FROM employees_temp WHERE department_id = depts(j);
COMMIT;
END;
/
FORALL 文でコレクションを使用する前に、コレクションから一部の要素を削除する必要があ
る場合があります。INDICES OF 句は、残りの要素のみを反復して、疎コレクションを処理し
ます。
元のコレクションを変更せずに、一部の要素のみを処理したり、要素を異なる順序で処理した
り、または一部の要素を複数回処理する場合もあります。VALUES OF 句を使用すると、要素全
体を新しいコレクションにコピーする(その結果、場合によっては大量のメモリーが消費され
る)かわりに、元のコレクションの要素へのポインタとして機能する要素を持つ単純なコレク
ションを設定できます。
例 11-5 では、任意のデータ(表名のセット)を保持するコレクションを作成します。要素の一
部を削除すると、デフォルトの FORALL 文では動作しない疎コレクションになります。プログ
ラムは、INDICES OF 句を指定した FORALL 文を使用して、データを表に挿入します。次に、
元のコレクションの特定の要素を指す 2 つのコレクションを新しく設定します。VALUES OF 句
を指定した FORALL 文を使用して、名前の各セットを別のデータベース表に格納します。
例 11-5 連続していない索引値での FORALL の使用
-- Create empty tables to hold order details
CREATE TABLE valid_orders (cust_name VARCHAR2(32), amount NUMBER(10,2));
CREATE TABLE big_orders AS SELECT * FROM valid_orders WHERE 1 = 0;
CREATE TABLE rejected_orders AS SELECT * FROM valid_orders WHERE 1 = 0;
DECLARE
-- Make collections to hold a set of customer names and order amounts.
SUBTYPE cust_name IS valid_orders.cust_name%TYPE;
TYPE cust_typ IS TABLe OF cust_name;
cust_tab cust_typ;
SUBTYPE order_amount IS valid_orders.amount%TYPE;
TYPE amount_typ IS TABLE OF NUMBER;
amount_tab amount_typ;
-- Make other collections to point into the CUST_TAB collection.
TYPE index_pointer_t IS TABLE OF PLS_INTEGER;
big_order_tab index_pointer_t := index_pointer_t();
rejected_order_tab index_pointer_t := index_pointer_t();
PROCEDURE setup_data IS BEGIN
-- Set up sample order data, including some invalid orders and some 'big' orders.
cust_tab := cust_typ('Company1','Company2','Company3','Company4','Company5');
amount_tab := amount_typ(5000.01, 0, 150.25, 4000.00, NULL);
END;
BEGIN
setup_data();
DBMS_OUTPUT.PUT_LINE('--- Original order data ---');
FOR i IN 1..cust_tab.LAST LOOP
DBMS_OUTPUT.PUT_LINE('Customer #' || i || ', ' || cust_tab(i) || ': $' ||
amount_tab(i));
END LOOP;
-- Delete invalid orders (where amount is null or 0).
FOR i IN 1..cust_tab.LAST LOOP
11-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
IF amount_tab(i) is null or amount_tab(i) = 0 THEN
cust_tab.delete(i);
amount_tab.delete(i);
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE('--- Data with invalid orders deleted ---');
FOR i IN 1..cust_tab.LAST LOOP
IF cust_tab.EXISTS(i) THEN
DBMS_OUTPUT.PUT_LINE('Customer #' || i || ', ' || cust_tab(i) || ': $' ||
amount_tab(i));
END IF;
END LOOP;
-- Because the subscripts of the collections are not consecutive, use
-- FORALL...INDICES OF to iterate through the actual subscripts,
-- rather than 1..COUNT
FORALL i IN INDICES OF cust_tab
INSERT INTO valid_orders(cust_name, amount)
VALUES(cust_tab(i), amount_tab(i));
-- Now process the order data differently
-- Extract 2 subsets and store each subset in a different table
setup_data(); -- Initialize the CUST_TAB and AMOUNT_TAB collections again.
FOR i IN cust_tab.FIRST .. cust_tab.LAST LOOP
IF amount_tab(i) IS NULL OR amount_tab(i) = 0 THEN
rejected_order_tab.EXTEND; -- Add a new element to this collection
-- Record the subscript from the original collection
rejected_order_tab(rejected_order_tab.LAST) := i;
END IF;
IF amount_tab(i) > 2000 THEN
big_order_tab.EXTEND; -- Add a new element to this collection
-- Record the subscript from the original collection
big_order_tab(big_order_tab.LAST) := i;
END IF;
END LOOP;
-- Now it's easy to run one DML statement on one subset of elements,
-- and another DML statement on a different subset.
FORALL i IN VALUES OF rejected_order_tab
INSERT INTO rejected_orders VALUES (cust_tab(i), amount_tab(i));
FORALL i IN VALUES OF big_order_tab
INSERT INTO big_orders VALUES (cust_tab(i), amount_tab(i));
COMMIT;
END;
/
-- Verify that the correct order details were stored
SELECT cust_name "Customer", amount "Valid order amount" FROM valid_orders;
SELECT cust_name "Customer", amount "Big order amount" FROM big_orders;
SELECT cust_name "Customer", amount "Rejected order amount" FROM rejected_orders;
FORALL がロールバックに与える影響
FORALL 文では、SQL 文の実行によって未処理例外が発生した場合、前回の実行中に行われた
すべてのデータベース変更はロールバックされます。ただし、呼び出された例外が捕捉され処
理されると、変更は、各 SQL 文の実行の前にマークされた暗黙的なセーブポイントまでロール
バックされます。前の実行の間に行われた変更は、ロールバックされません。たとえば、例
11-6 に示すように、部門番号と肩書きを格納するデータベース表を作成するとします。次に、
肩書きを、より長い肩書きに変更します。この新しい値が長すぎてその列では使用できないた
め、2 番目の UPDATE は失敗します。この例外に対する処理は行われるため、最初の UPDATE
はロールバックされず、変更はコミットされます。
例 11-6 FORALL でのロールバックの使用
CREATE TABLE emp_temp (deptno NUMBER(2), job VARCHAR2(18));
DECLARE
TYPE NumList IS TABLE OF NUMBER;
PL/SQL アプリケーションのパフォーマンスのチューニング
11-11
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
depts NumList := NumList(10, 20, 30);
BEGIN
INSERT INTO emp_temp VALUES(10, 'Clerk');
-- Lengthening this job title causes an exception
INSERT INTO emp_temp VALUES(20, 'Bookkeeper');
INSERT INTO emp_temp VALUES(30, 'Analyst');
COMMIT;
FORALL j IN depts.FIRST..depts.LAST -- Run 3 UPDATE statements.
UPDATE emp_temp SET job = job || ' (Senior)' WHERE deptno = depts(j);
-- raises a "value too large" exception
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Problem in the FORALL statement.');
COMMIT; -- Commit results of successful updates.
END;
/
%BULK_ROWCOUNT 属性を持つ FORALL による影響を受ける行カウント
カーソル属性の SQL%FOUND、SQL%ISOPEN、SQL%NOTFOUND および SQL%ROWCOUNT は、直
前に実行された DML 文についての役に立つ情報を戻します。カーソル属性の詳細は、6-6 ペー
ジの「暗黙カーソル」を参照してください。
SQL カーソルは、FORALL で使用するための複合属性 %BULK_ROWCOUNT を持ちます。この属
性は、結合配列のように機能します。SQL%BULK_ROWCOUNT(i) には、INSERT 文、UPDATE
文または DELETE 文の i 番目の実行によって処理された行数が格納されます。次に例を示しま
す。
例 11-7 FORALL 文での %BULK_ROWCOUNT の使用
CREATE TABLE emp_temp AS SELECT * FROM employees;
DECLARE
TYPE NumList IS TABLE OF NUMBER;
depts NumList := NumList(30, 50, 60);
BEGIN
FORALL j IN depts.FIRST..depts.LAST
DELETE FROM emp_temp WHERE department_id = depts(j);
-- How many rows were affected by each DELETE statement?
FOR i IN depts.FIRST..depts.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Iteration #' || i || ' deleted ' ||
SQL%BULK_ROWCOUNT(i) || ' rows.');
END LOOP;
END;
/
FORALL 文と %BULK_ROWCOUNT 属性は同じ添字を使用します。たとえば、FORALL が 5 ~ 10
の範囲を使用した場合は、%BULK_ROWCOUNT でも同じ範囲が使用されます。FORALL 文で
INDICES OF 句を使用して疎コレクションを処理する場合、%BULK_ROWCOUNT は、対応する
疎の添字を持ちます。FORALL 文で VALUES OF 句を使用して要素のサブセットを処理する場
合、%BULK_ROWCOUNT は、索引コレクションの要素の値に対応する添字を持ちます。索引コレ
クションの要素が重複しているために一部の DML 文が同じ添字を使用して複数回発行される
場合、%BULK_ROWCOUNT の対応する要素は、その添字を使用する DML 文によって影響を受け
たすべての行の合計です。INDICES OF 句および VALUES OF 句を使用する場合の
%BULK_ROWCOUNT の解釈例については、
http://www.oracle.com/technology/sample_code/tech/pl_sql の PL/SQL サンプ
ル・プログラムを参照してください。
11-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
典型的な挿入操作は 1 行にのみ影響するため、通常、挿入の場合の %BULK_ROWCOUNT は 1 で
す。INSERT ...SELECT 構造の場合は、%BULK_ROWCOUNT が 1 よりも大きくなることがあり
ます。たとえば、例 11-8 の FORALL 文は、反復のたびに任意の数の行を挿入します。それぞれ
の反復後に、%BULK_ROWCOUNT は挿入された行数を戻します。
例 11-8 FORALL で %BULK_ROWCOUNT を指定した場合の行カウント
CREATE TABLE emp_by_dept AS SELECT employee_id, department_id
FROM employees WHERE 1 = 0;
DECLARE
TYPE dept_tab IS TABLE OF departments.department_id%TYPE;
deptnums dept_tab;
BEGIN
SELECT department_id BULK COLLECT INTO deptnums FROM departments;
FORALL i IN 1..deptnums.COUNT
INSERT INTO emp_by_dept
SELECT employee_id, department_id FROM employees
WHERE department_id = deptnums(i);
FOR i IN 1..deptnums.COUNT LOOP
-- Count how many rows were inserted for each department; that is,
-- how many employees are in each department.
DBMS_OUTPUT.PUT_LINE('Dept '||deptnums(i)||': inserted '||
SQL%BULK_ROWCOUNT(i)||' records');
END LOOP;
DBMS_OUTPUT.PUT_LINE('Total records inserted: ' || SQL%ROWCOUNT);
END;
/
FORALL 文を実行した後で、スカラー属性の %FOUND、%NOTFOUND および %ROWCOUNT も使用
できます。たとえば、%ROWCOUNT は、SQL 文のすべての実行によって処理された行の総数を
戻します。
%FOUND と %NOTFOUND は、SQL 文の最後の実行のみを参照します。%BULK_ROWCOUNT を使用
すると、個々の実行に対する値を推論できます。たとえば、%BULK_ROWCOUNT(i) がゼロの場
合、%FOUND と %NOTFOUND はそれぞれ、FALSE および TRUE になります。
%BULK_EXCEPTIONS 属性を持つ FORALL 例外の処理
PL/SQL には、FORALL 文の実行中に呼び出される例外を処理するメカニズムが用意されてい
ます。このメカニズムによって、バルク・バインド操作では、例外に関する情報を保存して処
理を継続できます。
エラーが発生した場合もバルク・バインドを完了させるには、FORALL 文にキーワード SAVE
EXCEPTIONS を(境界の後、DML 文の前に)追加します。バルク操作中に発生した例外を追
跡する場合は、例外ハンドラも用意してください。
例 11-9 では、DML 操作でエラーが発生しても停止せずに、多数の DML 操作を実行する方法
の例を示します。この例では、EXCEPTION_INIT を使用して、dml_errors 例外を
ORA-24381 エラーに関連付けています。ORA-24381 エラーは、バルク操作後に例外が捕捉さ
れ、保存された場合に発生します。
実行中に呼び出されたすべての例外は、レコードのコレクションを格納するカーソル属性
%BULK_EXCEPTIONS に保存されます。各レコードには次の 2 つのフィールドがあります。
■
■
%BULK_EXCEPTIONS(i).ERROR_INDEX には、例外が呼び出されたときに実行中だった
FORALL 文の反復が保持されます。
%BULK_EXCEPTIONS(i).ERROR_CODE には、対応する Oracle エラー・コードが保持され
ます。
%BULK_EXCEPTIONS によって格納された値は常に、直前に実行された FORALL 文を参照しま
す。例外の数は、%BULK_EXCEPTIONS.COUNT に保存されます。添字の範囲は 1 ~ COUNT で
す。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-13
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
個々のエラー・メッセージは、置換される引数も含めて保存されませんが、例 11-9 に示すよう
に、ERROR_CODE を SQLERRM とともに使用すると、エラー・メッセージの本文を検索できま
す。
例外が発生した反復で使用されたコレクション要素を特定するために、処理を逆にたどる必要
がある場合があります。たとえば、INDICES OF 句を使用して疎コレクションを処理する場
合、要素を 1 つずつ確認して、%BULK_EXCEPTIONS(i).ERROR_INDEX に対応する要素を検
出する必要があります。VALUES OF 句を使用して要素のサブセットを処理する場合、索引コレ
クション内で添字が %BULK_EXCEPTIONS(i).ERROR_INDEX に一致する要素を検出し、次に
その要素の値を添字として使用して、元のコレクション内の誤った要素を検出する必要があり
ます。INDICES OF 句および VALUES OF 句を使用する場合に誤った要素を検出する方法の例
については、http://www.oracle.com/technology/tech/pl_sql/ の PL/SQL サンプ
ル・プログラムを参照してください。
キーワード SAVE EXCEPTIONS を省略すると、例外が呼び出された時点で FORALL 文の実行が
停止します。その場合、SQL%BULK_EXCEPTIONS.COUNT は 1 を戻し、
SQL%BULK_EXCEPTIONS にはレコードが 1 つのみ含まれます。実行中に例外が呼び出されなけ
れば、SQL%BULK_EXCEPTIONS.COUNT は 0(ゼロ)を戻します。
例 11-9 例外が発生しても継続するバルク操作
-- create a temporary table for this example
CREATE TABLE emp_temp AS SELECT * FROM employees;
DECLARE
TYPE empid_tab IS TABLE OF employees.employee_id%TYPE;
emp_sr empid_tab;
-- create an exception handler for ORA-24381
errors NUMBER;
dml_errors EXCEPTION;
PRAGMA EXCEPTION_INIT(dml_errors, -24381);
BEGIN
SELECT employee_id BULK COLLECT INTO emp_sr FROM emp_temp
WHERE hire_date < '30-DEC-94';
-- add '_SR' to the job_id of the most senior employees
FORALL i IN emp_sr.FIRST..emp_sr.LAST SAVE EXCEPTIONS
UPDATE emp_temp SET job_id = job_id || '_SR'
WHERE emp_sr(i) = emp_temp.employee_id;
-- If any errors occurred during the FORALL SAVE EXCEPTIONS,
-- a single exception is raised when the statement completes.
EXCEPTION
WHEN dml_errors THEN -- Now we figure out what failed and why.
errors := SQL%BULK_EXCEPTIONS.COUNT;
DBMS_OUTPUT.PUT_LINE('Number of statements that failed: ' || errors);
FOR i IN 1..errors LOOP
DBMS_OUTPUT.PUT_LINE('Error #' || i || ' occurred during '||
'iteration #' || SQL%BULK_EXCEPTIONS(i).ERROR_INDEX);
DBMS_OUTPUT.PUT_LINE('Error message is ' ||
SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
END;
/
DROP TABLE emp_temp;
この例の出力は次のようになります。
Number of statements that failed: 2
Error #1 occurred during iteration #7
Error message is ORA-12899: value too large for column
Error #2 occurred during iteration #13
Error message is ORA-12899: value too large for column
11-14
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
例 11-9 の PL/SQL では、更新後の値が大きすぎて job_id 列に挿入できないため、事前定義済
例外が発生します。FORALL 文の後、SQL%BULK_EXCEPTIONS.COUNT が 2 を返し、
SQL%BULK_EXCEPTIONS の内容が (7,12899) および (13,12899) になりました。
Oracle エラー・メッセージを(コードを含めて)取得するために、
SQL%BULK_EXCEPTIONS(i).ERROR_CODE の値を無効にして、エラー・レポート・ファンク
ション SQLERRM に渡しています。このファンクションでは負の数値が予測されています。
BULK COLLECT 句を使用した、問合せ結果のコレクションへの取出し
問合せでキーワード BULK COLLECT を使用すると、結果セットを非常に効率的に取り出すこと
ができます。各行をループするかわりに、単一の操作で、結果を 1 つ以上のコレクションに格
納できます。このキーワードは、SELECT INTO 文、FETCH INTO 文および RETURNING INTO
句で使用できます。
BULK COLLECT 句では、INTO リスト内のすべての変数はコレクションである必要があります。
表の列には、スカラー値または複合値(オブジェクト型を含む)を格納できます。例 11-10 で
は、ネストした表に、データベースの 2 つの列全体をロードします。
例 11-10 BULK COLLECT による問合せ結果の取得
DECLARE
TYPE NumTab IS TABLE OF employees.employee_id%TYPE;
TYPE NameTab IS TABLE OF employees.last_name%TYPE;
enums NumTab; -- No need to initialize the collections.
names NameTab; -- Values will be filled in by the SELECT INTO.
PROCEDURE print_results IS
BEGIN
IF enums.COUNT = 0 THEN
DBMS_OUTPUT.PUT_LINE('No results!');
ELSE
DBMS_OUTPUT.PUT_LINE('Results:');
FOR i IN enums.FIRST .. enums.LAST
LOOP
DBMS_OUTPUT.PUT_LINE(' Employee #' || enums(i) || ': ' || names(i));
END LOOP;
END IF;
END;
BEGIN
-- Retrieve data for employees with Ids greater than 1000
SELECT employee_id, last_name
BULK COLLECT INTO enums, names FROM employees WHERE employee_id > 1000;
-- The data has all been brought into memory by BULK COLLECT
-- No need to FETCH each row from the result set
print_results();
-- Retrieve approximately 20% of all rows
SELECT employee_id, last_name
BULK COLLECT INTO enums, names FROM employees SAMPLE (20);
print_results();
END;
/
コレクションは自動的に初期化されます。ネストした表および結合配列は、必要な数の要素を
保持できるように拡張されます。VARRAY を使用する場合、すべての戻り値は、宣言した
VARRAY のサイズに格納できる必要があります。要素は、索引 1 から、既存の要素を上書きし
ながら挿入されます。
BULK COLLECT INTO 句の処理は FETCH ループに類似しており、問合せに一致する行がない
場合に NO_DATA_FOUND 例外は発生しません。例 11-10 に示すように、処理後のネストした表
または VARRAY が NULL かどうか、または処理後の結合配列に要素が含まれているかどうか
を確認する必要があります。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-15
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
結果のコレクションが無制限に拡大するのを防ぐため、LIMIT 句または疑似列 ROWNUM を使用
して、処理される行の数を制限できます。また、SAMPLE 句を使用して、行のランダムなサン
プルを取り出すこともできます。
例 11-11 疑似列 ROWNUM による問合せ結果の制限
DECLARE
TYPE SalList IS TABLE OF employees.salary%TYPE;
sals SalList;
BEGIN
-- Limit the number of rows to 50
SELECT salary BULK COLLECT INTO sals FROM employees
WHERE ROWNUM <= 50;
-- Retrieve 10% (approximately) of the rows in the table
SELECT salary BULK COLLECT INTO sals FROM employees SAMPLE (10);
END;
/
次の項に示すように、指定した数の行をカーソルから一度にフェッチすることで、非常にサイ
ズが大きい結果セットを処理できます。
カーソルからのバルク・フェッチの例
例 11-12 に示すように、1 つのカーソルから 1 つ以上のコレクションにフェッチできます。
例 11-12 カーソルから 1 つ以上のコレクションへのバルク・フェッチ
DECLARE
TYPE NameList IS TABLE OF employees.last_name%TYPE;
TYPE SalList IS TABLE OF employees.salary%TYPE;
CURSOR c1 IS SELECT last_name, salary FROM employees WHERE salary > 10000;
names NameList;
sals SalList;
TYPE RecList IS TABLE OF c1%ROWTYPE;
recs RecList;
v_limit PLS_INTEGER := 10;
PROCEDURE print_results IS
BEGIN
IF names IS NULL OR names.COUNT = 0 THEN -- check if collections are empty
DBMS_OUTPUT.PUT_LINE('No results!');
ELSE
DBMS_OUTPUT.PUT_LINE('Results: ');
FOR i IN names.FIRST .. names.LAST
LOOP
DBMS_OUTPUT.PUT_LINE(' Employee ' || names(i) || ': $' || sals(i));
END LOOP;
END IF;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE('--- Processing all results at once ---');
OPEN c1;
FETCH c1 BULK COLLECT INTO names, sals;
CLOSE c1;
print_results();
DBMS_OUTPUT.PUT_LINE('--- Processing ' || v_limit || ' rows at a time ---');
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO names, sals LIMIT v_limit;
EXIT WHEN names.COUNT = 0;
print_results();
END LOOP;
CLOSE c1;
DBMS_OUTPUT.PUT_LINE('--- Fetching records rather than columns ---');
11-16
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
OPEN c1;
FETCH c1 BULK COLLECT INTO recs;
FOR i IN recs.FIRST .. recs.LAST
LOOP
-- Now all the columns from the result set come from a single record
DBMS_OUTPUT.PUT_LINE(' Employee ' || recs(i).last_name || ': $'
|| recs(i).salary);
END LOOP;
END;
/
例 11-13 では、1 つのカーソルから複数レコードのコレクションにフェッチする方法を示しま
す。
例 11-13 カーソルからレコードのコレクションへのバルク・フェッチ
DECLARE
TYPE DeptRecTab IS TABLE OF departments%ROWTYPE;
dept_recs DeptRecTab;
CURSOR c1 IS
SELECT department_id, department_name, manager_id, location_id
FROM departments WHERE department_id > 70;
BEGIN
OPEN c1;
FETCH c1 BULK COLLECT INTO dept_recs;
END;
/
LIMIT 句を使用したバルク・フェッチ操作の対象行の制限
バルク FETCH 文でのみ使用可能なオプションの LIMIT 句を使用すると、データベースから
フェッチされる行の数を制限できます。例 11-14 では、ループが繰り返されるたびに、FETCH
文によって 10 行(またはそれ以下)が索引付き表 empids にフェッチされます。前の値は上書
きされます。ループから抜けるタイミングを判断するために、empids.COUNT を使用していま
す。
例 11-14 LIMIT による BULK COLLECT の行数の制御
DECLARE
TYPE numtab IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
CURSOR c1 IS SELECT employee_id FROM employees WHERE department_id = 80;
empids
numtab;
rows
PLS_INTEGER := 10;
BEGIN
OPEN c1;
LOOP -- the following statement fetches 10 rows or less in each iteration
FETCH c1 BULK COLLECT INTO empids LIMIT rows;
EXIT WHEN empids.COUNT = 0;
-- EXIT WHEN c1%NOTFOUND; -- incorrect, can omit some data
DBMS_OUTPUT.PUT_LINE('------- Results from Each Bulk Fetch --------');
FOR i IN 1..empids.COUNT LOOP
DBMS_OUTPUT.PUT_LINE( 'Employee Id: ' || empids(i));
END LOOP;
END LOOP;
CLOSE c1;
END;
/
PL/SQL アプリケーションのパフォーマンスのチューニング
11-17
バルク SQL による、DML 文および問合せのループ・オーバーヘッドの削減
RETURNING INTO 句を使用したコレクションへの DML 結果の取出し
次に示すように、INSERT 文、UPDATE 文または DELETE 文の RETURNING INTO 句に BULK
COLLECT 句を使用できます。
例 11-15 RETURNING INTO 句での BULK COLLECT の使用
CREATE TABLE emp_temp AS SELECT * FROM employees;
DECLARE
TYPE NumList IS TABLE OF employees.employee_id%TYPE;
enums NumList;
TYPE NameList IS TABLE OF employees.last_name%TYPE;
names NameList;
BEGIN
DELETE FROM emp_temp WHERE department_id = 30
RETURNING employee_id, last_name BULK COLLECT INTO enums, names;
DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows:');
FOR i IN enums.FIRST .. enums.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Employee #' || enums(i) || ': ' || names(i));
END LOOP;
END;
/
FORALL と BULK COLLECT の併用
FORALL 文と BULK COLLECT 句を組み合せることができます。出力コレクションは、FORALL
文が反復されるとともに構築されます。
例 11-16 では、削除対象の各行の employee_id 値をコレクション e_ids に格納しています。
コレクション depts には 3 つの要素が存在するため、FORALL 文は 3 回反復します。FORALL
文によって発行される各 DELETE で 5 行ずつ削除される場合、削除された行の値を格納するコ
レクション e_ids には、文が完了すると 15 の要素が保持されます。
例 11-16 BULK COLLECT での FORALL の使用
CREATE TABLE emp_temp AS SELECT * FROM employees;
DECLARE
TYPE NumList IS TABLE OF NUMBER;
depts NumList := NumList(10,20,30);
TYPE enum_t IS TABLE OF employees.employee_id%TYPE;
TYPE dept_t IS TABLE OF employees.department_id%TYPE;
e_ids enum_t;
d_ids dept_t;
BEGIN
FORALL j IN depts.FIRST..depts.LAST
DELETE FROM emp_temp WHERE department_id = depts(j)
RETURNING employee_id, department_id BULK COLLECT INTO e_ids, d_ids;
DBMS_OUTPUT.PUT_LINE('Deleted ' || SQL%ROWCOUNT || ' rows:');
FOR i IN e_ids.FIRST .. e_ids.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Employee #' || e_ids(i) || ' from dept #' || d_ids(i));
END LOOP;
END;
/
各実行によって戻された列の値は、前に戻された値に追加されます。FORALL 文のかわりに
FOR ループを使用する場合、戻り値のセットは、各 DELETE 文によって上書きされます。
FORALL 文では、SELECT ...BULK COLLECT 文は使用できません。
11-18
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL での計算集中型プログラムの記述
バルク・バインドとホスト配列の併用
クライアント側のプログラムは、無名 PL/SQL ブロックを使用してホスト配列をバルク・バイ
ンド入出力できます。これは、コレクションをデータベース・サーバーとの間でやり取りする
のに最も効率的な方法です。
ホスト配列は OCI や Pro*C プログラムなどのホスト環境で宣言され、PL/SQL コレクションと
区別するためのコロンを接頭辞として付ける必要があります。次の例では、DELETE 文に入力
ホスト配列が使用されています。実行時に、無名 PL/SQL ブロックがデータベース・サーバー
に送信されて、実行されます。
DECLARE
...
BEGIN
-- assume that values were assigned to the host array
-- and host variables in the host environment
FORALL i IN :lower..:upper
DELETE FROM employees WHERE department_id = :depts(i);
COMMIT;
END;
/
PL/SQL での計算集中型プログラムの記述
BINARY_FLOAT および BINARY_DOUBLE データ型を使用すると、浮動小数点計算を伴う科学
アプリケーションなど、大量の演算を行う実用的な PL/SQL プログラムを記述できます。これ
らのデータ型は、多くのハードウェア・システム上でシステム固有の浮動小数点型とほぼ同様
に動作し、IEEE-754 浮動小数点標準で示されるセマンティックを持ちます。
これらのデータ型で小数データを表す方法は、財務処理アプリケーションにはあまり適してい
ません。財務処理アプリケーションの場合、小数部分が正確に表されることの方が、単にパ
フォーマンスが向上することよりも重要です。
PLS_INTEGER および BINARY_INTEGER データ型は PL/SQL 専用のデータ型で、整数の算術
計算の場合、SQL データ型の NUMBER または INTEGER より効率的です。PLS_INTEGER また
は BINARY_INTEGER を使用して、整数の算術計算用に純粋な PL/SQL コードを記述したり、
PL/SQL で操作できるように NUMBER または INTEGER 値を PLS_INTEGER または
BINARY_INTEGER に変換できます。BINARY_INTEGER データ型は、PLS_INTEGER と同じで
す。その他の考慮事項については、xxv ページの「BINARY_INTEGER データ型への変更」を
参照してください。
パッケージ内で、異なる数値パラメータを受け入れるための、オーバーロードされるプロシー
ジャおよびファンクションを記述できます。数学ルーチンは、パラメータ(BINARY_FLOAT、
BINARY_DOUBLE、NUMBER および PLS_INTEGER)の種類に合わせて最適化して、不要な変換
を回避できます。
SQRT、SIN、COS などの組込み数学ファンクションには、BINARY_FLOAT パラメータおよび
BINARY_DOUBLE パラメータを受け入れる、オーバーロードされる高速なファンクションがす
でに用意されています。BINARY_FLOAT および BINARY_DOUBLE 型の変数をこのような
ファンクションに渡したり、このようなファンクションに式を渡すときに TO_BINARY_FLOAT
または TO_BINARY_DOUBLE ファンクションをコールすることによって、計算集中型コードを
スピードアップできます。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-19
EXECUTE IMMEDIATE およびカーソル変数を使用した動的 SQL のチューニング
EXECUTE IMMEDIATE およびカーソル変数を使用した動的 SQL の
チューニング
たとえば汎用目的のレポート・ライターなど、プログラムによっては、文の正確なテキストが
実行時まで判明しない場合、様々な SQL 文を構築および処理する必要があります。多くの場
合、このような文は実行ごとに変わります。このような文は動的 SQL 文と呼ばれます。
以前は、動的 SQL 文を実行するには、提供されているパッケージ DBMS_SQL を使用する必要
がありました。現在、PL/SQL 内では、どの種類の動的 SQL 文でも、システム固有の動的 SQL
と呼ばれるインタフェースを使用して実行できます。これに関連する主な PL/SQL 機能は、
EXECUTE IMMEDIATE 文およびカーソル変数(REF CURSOR ともいう)です。
システム固有の動的 SQL コードは、DBMS_SQL パッケージをコールする場合よりもサイズが小
さくなり、処理速度も高速になります。次の例では、カーソル変数を宣言し、そのカーソル変
数を動的 SELECT 文に関連付けます。
DECLARE
TYPE EmpCurTyp IS REF CURSOR;
emp_cv EmpCurTyp;
v_ename VARCHAR2(15);
v_sal NUMBER := 1000;
table_name VARCHAR2(30) := 'employees';
BEGIN
OPEN emp_cv FOR 'SELECT last_name, salary FROM ' || table_name ||
' WHERE salary > :s' USING v_sal;
CLOSE emp_cv;
END;
/
詳細は、第 7 章「システム固有の動的 SQL を使用した SQL 操作の実行」を参照してください。
NOCOPY コンパイラ・ヒントを使用した PL/SQL プロシージャ・
コールのチューニング
デフォルトでは、OUT パラメータと IN OUT パラメータは値によって渡されます。すべての IN
OUT パラメータの値は、サブプログラムの実行前にコピーされます。サブプログラムの実行中
は、一時変数に出力パラメータ値が保持されます。サブプログラムが正常に終了した場合、こ
の値は実パラメータにコピーされます。サブプログラムが未処理例外で終了した場合、元のパ
ラメータは変更されません。
パラメータが、コレクション、レコード、オブジェクト型のインスタンスなどの大規模なデー
タ構造を表す場合、このコピー作業によって実行速度が遅くなり、メモリーが消費されます。
特に、このオーバーヘッドは、オブジェクト・メソッドに対する各コールで発生します。メ
ソッドが正常に終了した場合のみメソッドによる変更が適用されるように、一時コピーがすべ
ての属性に対して作成されます。
このオーバーヘッドを回避するには、NOCOPY ヒントを指定します。これによって、PL/SQL
コンパイラは OUT および IN OUT パラメータを参照によって渡すことができます。サブプログ
ラムが正常に終了した場合、動作は通常の場合と同じです。サブプログラムが例外によって終
了した場合も、OUT および IN OUT パラメータ(またはオブジェクト属性)の値が変更される
ことがあります。この手法を使用する場合、サブプログラムですべての例外が処理されるよう
にします。
次の例では、IN OUT パラメータ v_staff を参照によって渡すように、コンパイラに指示しま
す。これによって、エントリの VARRAY をサブプログラムにコピーしてサブプログラムが終了
することを回避できます。
DECLARE
TYPE Staff IS VARRAY(200) OF Employee;
PROCEDURE reorganize (v_staff IN OUT NOCOPY Staff) IS ...
11-20
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
NOCOPY コンパイラ・ヒントを使用した PL/SQL プロシージャ・コールのチューニング
例 11-17 では、ローカルのネストした表に 25,000 レコードがロードされます。この表は、何も
実行しない 2 つのローカル・プロシージャに渡されます。プロシージャへのコールで NOCOPY
を使用する方が、時間がかかりません。
例 11-17 パラメータでの NOCOPY の使用
DECLARE
TYPE EmpTabTyp IS TABLE OF employees%ROWTYPE;
emp_tab EmpTabTyp := EmpTabTyp(NULL); -- initialize
t1 NUMBER;
t2 NUMBER;
t3 NUMBER;
PROCEDURE get_time (t OUT NUMBER) IS
BEGIN t := DBMS_UTILITY.get_time; END;
PROCEDURE do_nothing1 (tab IN OUT EmpTabTyp) IS
BEGIN NULL; END;
PROCEDURE do_nothing2 (tab IN OUT NOCOPY EmpTabTyp) IS
BEGIN NULL; END;
BEGIN
SELECT * INTO emp_tab(1) FROM employees WHERE employee_id = 100;
emp_tab.EXTEND(49999, 1); -- copy element 1 into 2..50000
get_time(t1);
do_nothing1(emp_tab); -- pass IN OUT parameter
get_time(t2);
do_nothing2(emp_tab); -- pass IN OUT NOCOPY parameter
get_time(t3);
DBMS_OUTPUT.PUT_LINE('Call Duration (secs)');
DBMS_OUTPUT.PUT_LINE('--------------------');
DBMS_OUTPUT.PUT_LINE('Just IN OUT: ' || TO_CHAR((t2 - t1)/100.0));
DBMS_OUTPUT.PUT_LINE('With NOCOPY: ' || TO_CHAR((t3 - t2))/100.0);
END;
/
NOCOPY の制限
NOCOPY を使用することによって、パラメータのエイリアシングの可能性が高くなります。詳
細は、8-23 ページの「サブプログラムのパラメータのエイリアシングの理解」を参照してくだ
さい。
NOCOPY は、ディレクティブではなく、ヒントです。次の場合には、PL/SQL コンパイラは
NOCOPY ヒントを無視して、値によってパラメータを渡します。エラーは生成されません。
■
■
■
■
■
■
実パラメータが結合配列の要素である場合。この制限は、パラメータが結合配列全体の場
合は適用されません。
実パラメータに、位取りや NOT NULL などの制約がある場合。この制限は、サイズ制約付
きの文字列には適用されません。この制限は、制約付きの要素またはコンポジット型の属
性には拡張されません。
実パラメータと仮パラメータがレコードであり、いずれかまたは両方のレコードが
%ROWTYPE または %TYPE を使用して宣言されており、レコード内の対応するフィールドの
制約が異なる場合。
実パラメータと仮パラメータがレコードであり、実パラメータはカーソル FOR ループの索
引として(暗黙的に)宣言されており、レコード内の対応するフィールドの制約が異なる
場合。
実パラメータを渡すために、暗黙的なデータ型の変換が必要となる場合。
サブプログラムが、データベース・リンクによって、または外部プロシージャとしてコー
ルされる場合。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-21
システム固有の実行のための PL/SQL コードのコンパイル
システム固有の実行のための PL/SQL コードのコンパイル
PL/SQL プロシージャをコンパイルして、共有ライブラリに常駐するシステム固有のコードに
すると、プロシージャをスピードアップできます。プロシージャは C 言語のコードに変換され
てから、通常の C コンパイラでコンパイルされ、Oracle プロセスにリンクされます。
ネイティブ・コンパイルは、提供されている Oracle パッケージと独自に記述したプロシージャ
の両方に使用できます。この方法でコンパイルしたプロシージャは、共有サーバー構成(以前
のマルチスレッド・サーバー)や Oracle Real Application Clusters などのすべてのサーバー環
境で動作します。
参照 :
■
PL/SQL ネイティブ・コンパイルの設定に関する Best Practices および
その他の情報は、Oracle Technology Network(OTN)を参照してく
ださい。
http://www.oracle.com/technology/tech/pl_sql/
■
Note 269012.1 など、ネイティブ・コンパイルの詳細は、Oracle
Metalink を参照してください。
http://metalink.oracle.com
はじめに
PL/SQL のネイティブ・コンパイルを初めて実行する場合は、本番環境の前に、まずテスト・
データベースで試します。
データベースを PL/SQL のネイティブ・コンパイル用に構成する前に、常にデータベースを
バックアップします。パフォーマンス上のメリットに比べて、余分なコンパイル時間のデメ
リットの方が大きい場合、バックアップからリストアする方が、解釈済モードで全体を再コン
パイルするよりも、必要な時間が短い場合があります。
設定手順の一部では、DBA の認可レベルが必要です。一部の初期化パラメータの値を変更し
て、データベース・サーバーで(可能であればインスタンスのデータ・ファイルの近くに)新
しいディレクトリを作成する必要があります。また、データベース・サーバーには C コンパイ
ラも必要です。クラスタの場合、コンパイラはノードごとに必要です。この手順を開発用マシ
ン上でテストできる場合でも、通常、ネイティブ・コンパイルを本番サーバーで実行するには、
DBA に協力を依頼する必要があります。
注意 : PL/SQL コードをネイティブ・コンパイルして使用するための前
提要件については、プラットフォームごとに Oracle データベースのイン
ストレーション・ガイドで説明しています。ソフトウェア要件の項で、ご
使用のプラットフォームのネイティブ・コンパイルに使用するための動作
保証されたコンパイラを確認し、保証されたコンパイラを使用してくださ
い。
PL/SQL のネイティブ・コンパイルを使用するかどうかの判断
PL/SQL のネイティブ・コンパイルによって、計算集中型のプロシージャ操作のパフォーマン
スは大幅に改善されます。このような操作の例には、データ・ウェアハウス・アプリケーショ
ンや、サーバー側でデータを大幅に変換して表示するアプリケーションなどがあります。この
ような場合、実行速度が最高 30% 向上する場合があります。
この手法では、PL/SQL からコールされる SQL 文は高速にならないため、SQL の実行に費やす
時間の少ない計算集中型の PL/SQL プロシージャで最も高い効果が得られます。PL/SQL のネ
イティブ・コンパイルを有効にしてパフォーマンスが改善される度合いは、テストによって確
認できます。
ネイティブ・コンパイルを使用してプログラム・ユニットをコンパイルすると、デフォルトの
解釈済モードを使用するよりも時間がかかります。コードを頻繁に再コンパイルする、開発サ
イクルの繁忙期には、ネイティブ・コンパイルを無効にしてもかまいません。
11-22
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
システム固有の実行のための PL/SQL コードのコンパイル
PL/SQL のネイティブ・コンパイルを使用するとデータベース操作で大幅にパフォーマンスが
改善すると判断した場合、NATIVE 設定を使用してデータベース全体をコンパイルすることを
お薦めします。データベース内のすべての PL/SQL コードをコンパイルすると、作成したコー
ドおよびすべての組込み PL/SQL パッケージへのコールがスピードアップします。
ご使用の環境で解釈コンパイルが必要な場合は、すべての PL/SQL ユニットを INTERPRETED
でコンパイルできます。たとえば、NATIVE PL/SQL ユニットが含まれているデータベース全
体を、C コンパイラが使用できない環境にインポートする場合などです。
データベース全体を NATIVE または INTERPRETED コンパイルに変換する場合は、11-28 ペー
ジの「PL/SQL ネイティブ・コンパイルまたは解釈コンパイルで使用するデータベース全体の
変更」を参照してください。
PL/SQL のネイティブ・コンパイルの動作
ネイティブ・コンパイルを使用しない場合、各 PL/SQL プログラム・ユニットは、中間形式の
機械可読コード(m コード)にコンパイルされます。m コードはデータベース・ディクショナ
リに格納され、実行時に解釈されます。PL/SQL のネイティブ・コンパイルを使用する場合、
PL/SQL 文は実行時に解釈が不要な C コードへ変換され、実行時のパフォーマンスが改善され
ます。
PLSQL_ 初期化パラメータでは、PL/SQL ネイティブ・コンパイルの環境を設定します。詳細
は、11-25 ページの「PL/SQL ネイティブ・コンパイルの初期化パラメータの設定」を参照して
ください。
PL/SQL は、コマンド・ファイル $ORACLE_HOME/plsql/spnc_commands、およびオペレー
ティング・システムでサポートされている C コンパイラとリンカーを使用し、変換された C
コードをコンパイルして共有ライブラリにリンクします。11-24 ページの「spnc_commands
ファイル」を参照してください。
共有ライブラリは、データ・ディクショナリ内に格納されるため、自動的にパックアップする
ことができ、削除されないように保護されます。共有ライブラリ・ファイルは、ファイル・シ
ステムにコピーされ、PL/SQL のサブプログラムの起動時にロードされて実行されます。この
ファイルがデータベースの停止中にファイル・システムから削除された場合、またはライブラ
リを格納するディレクトリを変更した場合、ファイルは自動的に再度抽出されます。
SQL 文をコールするだけの PL/SQL プログラム・ユニットの場合、あまり(またはまったく)
高速化しないこともありますが、ネイティブ・コンパイルされた PL/SQL が、対応する解釈済
コードより低速になることはありません。コンパイルされたコードは解釈済コードと同じライ
ブラリをコールするため、動作は同じです。
依存性、無効化および再評価
プロシージャをコンパイルして共有ライブラリに入れると、Oracle プロセスに自動的にリンク
されます。データベースを再起動したり、共有ライブラリを別の場所に移動する必要はありま
せん。ストアド・プロシージャがすべて解釈されたか、すべてシステム固有の実行用にコンパ
イルされたか、または両者を組み合せてコンパイルされたかにかかわらず、ストアド・プロ
シージャを任意にコールできます。
無効化した PL/SQL モジュールでは、再コンパイルが自動的に行われます。たとえば、ネイ
ティブ・コンパイルされた PL/SQL サブプログラムが依存するオブジェクトが変更されると、
サブプログラムは無効になります。同じサブプログラムが次にコールされたとき、データベー
スはサブプログラムを自動的に再コンパイルします。PLSQL_CODE_TYPE 設定はサブプログラ
ムごとにライブラリ・ユニットに格納されるため、自動再コンパイルではこの格納された設定
をコード型として使用します。
格納された設定は、再評価の一部として再コンパイルが行われるときにのみ使用されます。
SQL コマンドの CREATE OR REPLACE または ALTER...COMPILE を使用して PL/SQL サブプ
ログラムを明示的にコンパイルする場合、現在のセッション設定が使用されます。11-2 ページ
の「PL/SQL コンパイル用の初期化パラメータ」を参照してください。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-23
システム固有の実行のための PL/SQL コードのコンパイル
生成された共有ライブラリは、SYSTEM 表領域のデータベースに格納されます。ネイティブ・
コンパイルされたプロシージャを初めて実行すると、対応する共有ライブラリが、データベー
スから PLSQL_NATIVE_LIBRARY_DIR 初期化パラメータで指定されたディレクトリにコピー
されます。
Real Application Clusters および PL/SQL のネイティブ・コンパイル
クラスタではすべてのノードで PL/SQL のサブプログラムをコンパイルすることが必要な場合
があるため、クラスタの各ノードで C コンパイラが必要です。また、各ノードの
$ORACLE_HOME/plsql/spnc_commands ファイルで、設定およびパスを適切に指定する必要
があります。
Real Application Clusters(RAC)環境で PL/SQL のネイティブ・コンパイルを使用する場合、
共有ライブラリ・ファイルの元のコピーはデータベースに格納され、自動的にクラスタのすべ
てのノードに伝播されます。この機能を使用するためにライブラリをコピーする必要はありま
せん。
RAC クラスタのすべてのノードで、PL/SQL ネイティブ・コンパイルを制御する初期化パラ
メータの設定が同じであることを確認してください。また、共有ライブラリを配置する、
PLSQL_NATIVE_LIBRARY_DIR に指定したパスが、クラスタを構成するすべてのノードに等し
く作成されていることを確認してください。
ネイティブ・コンパイルの制限
ネイティブ・コンパイルには次のような制限があります。
■
■
PL/SQL 用のデバッグ・ツールでは、システム固有の実行用にコンパイルされたプロシー
ジャは処理されません。
多数のプロシージャとパッケージ(通常は 15000 以上)をシステム固有の実行用にコンパ
イルすると、単一のディレクトリに多数の共有オブジェクトができるため、システムのパ
フォーマンスに影響することがあります。回避策の詳細は、11-26 ページの「PL/SQL のシ
ステム固有のライブラリ用のサブディレクトリの設定」を参照してください。
spnc_commands ファイル
$ORACLE_HOME/plsql ディレクトリの spnc_commands ファイルには、各プログラムをコン
パイルおよびリンクするコマンドのテンプレートが含まれています。%(src) などの一部の特
殊な名前は事前定義されており、対応するファイル名で置換されます。$(ORACLE_HOME) 変数
は、Oracle ホーム・ディレクトリの位置で置換されます。コメント行は、# 文字で始まります。
このファイルには、すべての特殊な表記法について説明するコメントが記載されています。
spnc_commands ファイルには、デフォルトの C コンパイラの事前定義されたパスが記述され
ています。パスはオペレーティング・システムによって異なります。オペレーティング・シス
テムごとに特定のコンパイラがサポートされます。PL/SQL モジュールのコンパイルに使用で
きるコンパイラは 1 つのみです。データベース内の PL/SQL モジュールを異なるコンパイラで
コンパイルしないでください。
spnc_commands ファイルを参照して、コマンド・テンプレートが正しいことを確認できます。
このファイルは、システム管理者がコンパイラを別の場所にインストールした場合、またはサ
ポートされている別の C コンパイラを使用する場合を除き、変更する必要はありません。詳細
は、ご使用のプラットフォームの Oracle データベースのインストレーション・ガイドを参照し
てください。また、Oracle Metalink(http://metalink.oracle.com)で
spnc_commands を検索して情報を参照することもできます。
11-24
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
システム固有の実行のための PL/SQL コードのコンパイル
PL/SQL ネイティブ・コンパイルの初期化パラメータの設定
この項では、PL/SQL ネイティブ・コンパイルの設定に使用される初期化パラメータについて
説明します。
■
PLSQL_NATIVE_LIBRARY_DIR
■
PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT
■
PLSQL_CODE_TYPE
これらのパラメータの設定を確認するには、SQL*Plus で次のように入力します。
SHOW PARAMETERS PLSQL
11-2 ページの「PL/SQL コンパイル用の初期化パラメータ」を参照してください。
PLSQL_NATIVE_LIBRARY_DIR 初期化パラメータ
システム・レベル専用の必須パラメータで、ネイティブ・コンパイル済の PL/SQL コードを格
納する共有ライブラリの格納場所のフルパスおよびディレクトリ名を指定します。この値は、
既存のアクセス可能なディレクトリを明示的に示す必要があります。このパスには、
ORACLE_HOME などの変数を含めることはできません。パラメータ値を設定するには、
ALTER SYSTEM コマンドを使用するか、または初期化ファイルを更新します。
たとえば、PL/SQL のシステム固有のライブラリに使用するディレクトリのパスが
/oracle/oradata/db1/natlib の場合、初期化ファイルの設定は次のようになります。
PLSQL_NATIVE_LIBRARY_DIR='/oracle/oradata/db1/natlib'
Optimal Flexible Architecture(OFA)規則に従って、共有ライブラリのディレクトリを、デー
タ・ファイルの格納場所のサブディレクトリとして作成することをお薦めします。セキュリ
ティ上の理由から、このディレクトリに対する書込み権限を持つユーザーは、oracle および
root のみにする必要があります。
Real Application Clusters 環境を使用している場合は、11-24 ページの「Real Application
Clusters および PL/SQL のネイティブ・コンパイル」を参照してください。
PLSQL_NATIVE_LIBRARY_DIR 初期化パラメータの詳細は、『Oracle Database リファレンス』
を参照してください。
PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT 初期化パラメータ
システム・レベル専用のオプションのパラメータで、PLSQL_NATIVE_LIBRARY_DIR パラメー
タで指定したディレクトリ内のサブディレクトリの数を指定します。パラメータ値を設定する
には、ALTER SYSTEM コマンドを使用するか、または初期化ファイルを更新します。
たとえば、1,000 個のサブディレクトリに対してパラメータを設定する場合は、初期化パラメー
タ・ファイルに次のように設定します。
PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT=1000;
ネイティブ・コンパイルされたプログラム・ユニットの数が膨大である場合は、このパラメー
タを設定してください。11-26 ページの「PL/SQL のシステム固有のライブラリ用のサブディレ
クトリの設定」を参照してください。
PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT 初期化パラメータの詳細は、
『Oracle Database リ
ファレンス』を参照してください。
PLSQL_CODE_TYPE 初期化パラメータ
PLSQL_CODE_TYPE 初期化パラメータによって、PL/SQL コードをネイティブ・コンパイルす
るか解釈済にするかが決まります。デフォルト設定は INTERPRETED です。PL/SQL のネイ
ティブ・コンパイルを有効にするには、PLSQL_CODE_TYPE の値を NATIVE に設定します。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-25
システム固有の実行のための PL/SQL コードのコンパイル
このパラメータは、システム・レベル、セッション・レベルまたは特定の PL/SQL モジュール
用に設定できます。パラメータ値を設定するには、ALTER SYSTEM コマンドまたは
ALTER SESSION コマンドを使用するか、初期化ファイルを更新してください。データベース
全体を NATIVE でコンパイルする場合は、システム・レベルで PLSQL_CODE_TYPE を設定する
ことをお薦めします。
次の SQL*Plus 構文では、セッション・レベルでパラメータを設定しています。
ALTER SESSION SET PLSQL_CODE_TYPE='NATIVE';
ALTER SESSION SET PLSQL_CODE_TYPE='INTERPRETED';
PLSQL_CODE_TYPE = NATIVE 句を ALTER ..COMPILE 文とともに特定の PL/SQL モジュールに
対して使用することもできます。詳細は、11-27 ページの例 11-18 を参照してください。この影
響を受けるのは、指定したモジュールのみです。セッション全体の初期化パラメータは変更さ
れません。パッケージ仕様部とその本体は、同じネイティブ・コンパイル設定でコンパイルす
る必要はありません。
PLSQL_CODE_TYPE 初期化パラメータの詳細は、
『Oracle Database リファレンス』を参照して
ください。
PL/SQL のシステム固有のライブラリ用のサブディレクトリの設定
デフォルトでは、PL/SQL プログラム・ユニットは 1 つのディレクトリに保持されます。ただ
し、プログラム・ユニットの数が膨大である場合は、多数のファイルを 1 つのディレクトリで
処理するのが難しいこともあります。この問題を回避するため、
PLSQL_NATIVE_LIBRARY_DIR 初期化パラメータで指定したディレクトリ下の複数のサブディ
レクトリに PL/SQL プログラム・ユニットを分散させることをお薦めします。
既存のデータベースを新しいデータベースへ移植する場合、またはテスト・データベースを設
定した場合、次の SQL 問合せによって、使用している PL/SQL プログラム・ユニットの数を判
断します。
SELECT COUNT (*) from DBA_PLSQL_OBJECT_SETTINGS
パッケージなど一部のユニットを除外する場合は、前述の問合せで次の構文を使用します。
WHERE TYPE NOT IN ('TYPE', 'PACKAGE')
PL/SQL のシステム固有のライブラリ用のサブディレクトリを設定する必要がある場合は、ま
ずサブディレクトリを d0、d1、d2、d3...dx と順番に作成します。ここで、x はディレクトリの
総数です。このタスクには、スクリプトを使用することをお薦めします。たとえば、次のよう
な PL/SQL ブロックを実行して、出力をファイルに保存してから、そのファイルをシェル・ス
クリプトとして実行することができます。
SPOOL make_dirs
BEGIN
FOR j IN 0..1000 -- change to the number of directories needed
LOOP
DBMS_OUTPUT.PUT_LINE ( 'mkdir d' || TO_CHAR(j) );
END LOOP;
END;
/
SPOOL OFF
次に、PLSQL_NATIVE_LIBARY_SUBDIR_COUNT 初期化パラメータに、作成したサブディレク
トリの数を設定します。たとえば、1,000 個のサブディレクトリを作成した場合は、SQL*Plus
を使用して次の SQL 文を入力できます。
ALTER SYSTEM SET PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT=1000;
11-25 ページの「PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT 初期化パラメータ」を参照して
ください。
11-26
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
システム固有の実行のための PL/SQL コードのコンパイル
PL/SQL ネイティブ・コンパイルの設定方法およびテスト方法
ネイティブ・コンパイルを使用して 1 つ以上のサブプログラムを設定しテストする手順は、次
のとおりです。
1.
必要な初期化パラメータを設定します。11-25 ページの「PL/SQL ネイティブ・コンパイル
の初期化パラメータの設定」を参照してください。
2.
次のいずれかの方法を使用して 1 つ以上のサブプログラムをコンパイルします。
■
■
■
■
■
CREATE OR REPLACE を使用してサブプログラムを作成または再コンパイルします。
例 11-18 に示すとおり、ALTER PROCEDURE、ALTER FUNCTION または ALTER
PACKAGE コマンドに COMPILE オプションを指定して、特定のサブプログラムまたは
パッケージ全体を再コンパイルします。
サブプログラムを削除して再作成します。
オラクル社が提供するパッケージ・セットを作成する SQL*Plus スクリプトの 1 つを実
行します。
PLSQL_CODE_TYPE=NATIVE を指定し、構成済の初期化ファイルを使用してデータ
ベースを作成します。データベースの作成中に、utlirp スクリプトが実行され、オ
ラクル社が提供するパッケージがすべてコンパイルされます。
例 11-18 に、ネイティブ・コンパイルを使用してプロシージャを変更しテストするまでの
プロセスを示します。プロシージャはただちにコールできるようになり、Oracle プロセス
内で共有ライブラリとして直接実行されます。コンパイル時にエラーが発生した場合、
USER_ERRORS ビューまたは SQL*Plus の SHOW ERRORS コマンドを使用して、エラーを確
認できます。
例 11-18 システム固有の実行のための PL/SQL プロシージャのコンパイル
-- PLSQL_NATIVE_LIBRARY_DIR must be set to an existing, accessible directory
SET SERVEROUTPUT ON FORMAT WRAPPED
CREATE OR REPLACE PROCEDURE hello_native AS
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello world. Today is ' || TO_CHAR(SYSDATE) || '.');
END hello_native;
/
ALTER PROCEDURE hello_native COMPILE PLSQL_CODE_TYPE=NATIVE REUSE SETTINGS;
SHOW ERRORS
-- check for a file HELLO_NATIVE... in the PLSQL_NATIVE_LIBRARY_DIR directory
CALL hello_native();
3.
処理が正常に実行されたかどうかを確認するために、データ・ディクショナリを問い合せ
て、プロシージャがシステム固有の実行用にコンパイルされたかどうかを調べることがで
きます。既存のプロシージャがシステム固有の実行用にコンパイルされたかどうかを確認
するには、ALL_PLSQL_OBJECT_SETTINGS ビューを問い合せます。PLSQL_CODE_TYPE
列の値は、プロシージャがシステム固有の実行用にコンパイルされていれば NATIVE、そ
れ以外の場合は INTERPRETED となります。詳細は、
『Oracle Database リファレンス』を
参照してください。
4.
たとえば、プロシージャ hello_native のステータスを確認するには、例 11-19 のように
問合せを使用します。
例 11-19 コンパイルされたプロシージャに対する plsql_code_type の確認
SELECT PLSQL_CODE_TYPE FROM USER_PLSQL_OBJECT_SETTINGS
WHERE NAME = 'HELLO_NATIVE';
PL/SQL アプリケーションのパフォーマンスのチューニング
11-27
システム固有の実行のための PL/SQL コードのコンパイル
PL/SQL のネイティブ・コンパイルで使用する新しいデータベースの設定
この項で示す手順を使用して、PL/SQL ネイティブ・コンパイル用に新しいデータベースを設
定します。多くのデータベース操作で使用されるすべての組込み PL/SQL パッケージで、パ
フォーマンスが改善します。Real Application Clusters 環境を使用している場合は、11-24 ペー
ジの「Real Application Clusters および PL/SQL のネイティブ・コンパイル」を参照してくだ
さい。
1.
spnc_commands ファイルのコマンド・テンプレートが正しいことを確認します。システ
ム管理者に連絡し、必要な C コンパイラがオペレーティング・システムに存在することを
確認します。11-24 ページの「spnc_commands ファイル」を参照してください。
2.
PL/SQL のシステム固有ライブラリのディレクトリを Oracle データベースごとに作成しま
す。11-25 ページの「PLSQL_NATIVE_LIBRARY_DIR 初期化パラメータ」を参照してくだ
さい。
■
■
■
■
3.
Oracle データベースごとに PL/SQL ライブラリを設定する必要があります。共有ライ
ブラリ(.so および .dll ファイル)は、各データベースへ論理的に接続されます。
データベース間で共有することはできません。PL/SQL ライブラリを設定して共有す
ると、データベースは破損します。
.so および .dll ファイルに対する不正アクセスを防ぐために、OFA 規則に従って、
保護された場所にディレクトリを作成します。
PL/SQL のネイティブ・コンパイルに使用されるコンパイラの実行可能ファイルが、
適切な権限を持つユーザーによってのみ書込み可能であることを確認します。
共有ライブラリの元のコピーが、データベース内に格納されていることを確認します。
これによって元のコピーがデータベースとともに自動的にバックアップされます。
必要な初期化パラメータを設定します。11-25 ページの「PL/SQL ネイティブ・コンパイル
の初期化パラメータの設定」を参照してください。
データベース・コンフィギュレーション・アシスタントを使用する場合は、これを使用し
て PL/SQL ネイティブ・コンパイルに必要な初期化パラメータを設定します。
PLSQL_NATIVE_LIBRARY_DIR をアクセス可能なディレクトリに設定し、
PLSQL_CODE_TYPE を NATIVE に設定していることを確認します。
PL/SQL ネイティブ・コンパイルまたは解釈コンパイルで使用するデータベー
ス全体の変更
この項に説明するプロセスで、dbmsupgnv.sql および dbmsupgin.sql のスクリプトを使用
して、既存のデータベースのすべての PL/SQL モジュールをそれぞれ NATIVE または
INTERPRETED に再コンパイルできます。この変換を実行する前に、11-22 ページの「PL/SQL
のネイティブ・コンパイルを使用するかどうかの判断」の内容に目を通してください。
ネイティブ・コンパイルへの変換で、dbmsupgnv.sql によって TYPE 仕様部を NATIVE に再
コンパイルすることはできません。これらの仕様部には実行可能なコードが含まれていないた
めです。
パッケージ仕様部に実行可能なコードが含まれることはほとんどないため、NATIVE にコンパ
イルしても実行時の利点は得られません。dbmsupgnv.sql スクリプトで TRUE コマンドライ
ン・パラメータを使用すると、NATIVE への再コンパイルからパッケージ仕様部を除外して、
変換処理にかかる時間を節約できます。
dbmsupgin.sql スクリプトで解釈コンパイルに変換するときは、パラメータは指定できず、
PL/SQL ユニットを除外することはできません。
11-28
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
システム固有の実行のための PL/SQL コードのコンパイル
注意 : 次の手順では、ネイティブ・コンパイルへの変換について説明し
ます。すべての PL/SQL モジュールを解釈コンパイルに再コンパイルする
必要がある場合は、手順を次のように変更してください。
■
■
■
1.
1 番目の手順をスキップします。
PLSQL_CODE_TYPE 初期化パラメータを NATIVE ではなく
INTERPRETED に設定します。
dbmsupgnv.sql スクリプトを dbmsupgin.sql スクリプトに置き換
えます。
ネイティブ・コンパイルをサポートするように、次の点が正しく構成されていることを確
認します。
■
■
■
■
サポートされている C コンパイラがデータベース環境にインストールされ、
spnc_commands ファイルのコマンド・テンプレートがその C コンパイラ用の正しい
ものであること。
PLSQL_NATIVE_LIBRARY_DIR が設定されていること。11-25 ページの
「PLSQL_NATIVE_LIBRARY_DIR 初期化パラメータ」を参照してください。
PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT が、変換後のネイティブ・コンパイルさ
れたユニットの数に正しく設定されていること。11-25 ページの
「PLSQL_NATIVE_LIBRARY_DIR 初期化パラメータ」および 11-26 ページの
「PL/SQL のシステム固有のライブラリ用のサブディレクトリの設定」を参照してくだ
さい。
11-27 ページの例 11-18 に示すように、PL/SQL テスト・ユニットをコンパイルできる
こと。次に例を示します。
ALTER PROCEDURE my_proc COMPILE PLSQL_CODE_TYPE=NATIVE
REUSE SETTINGS;
2.
アプリケーション・サービス、リスナーおよびデータベースを停止します。
■
■
■
3.
Forms Process、Web Server、Reports Server、Concurrent Manager Server など、すべ
てのアプリケーション・サービスを停止します。すべてのアプリケーション・サービ
スを停止したら、データベースへのすべての接続が終了していることを確認します。
データベースの TNS リスナーを停止して、新規接続が作成されないようにします。
ユーザー SYS として、通常モードまたは即時モードでデータベースを停止します。
『Oracle Database 管理者ガイド』の起動と終了に関する項を参照してください。
初期化パラメータ・ファイルで PLSQL_CODE_TYPE を NATIVE に設定します。データベー
スでサーバー・パラメータ・ファイルを使用している場合は、データベースを起動してか
らこの設定を行ってください。11-25 ページの「PLSQL_CODE_TYPE 初期化パラメータ」
を参照してください。
PLSQL_CODE_TYPE の値は、この手順の PL/SQL ユニットの変換には影響を与えません。
ただし、この手順以降にコンパイルしたユニットは影響を受けるため、ここで必要なコン
パイル・タイプを明示的に設定する必要があります。
4.
UPGRADE オプションを使用して、データベースをアップグレード・モードで起動します。
SQL*Plus の STARTUP の詳細は、
『SQL*Plus ユーザーズ・ガイドおよびリファレンス』を
参照してください。
5.
次のコードを実行して、無効な PL/SQL ユニットを一覧表示します。SQL SPOOL コマンド
を使用すると、問合せの出力を今後の参照のために保存しておくことができます。
例 11-20 無効な PL/SQL ユニットの確認
REM To save the output of the query to a file: SPOOL pre_update_invalid.log
SELECT o.OWNER, o.OBJECT_NAME, o.OBJECT_TYPE
FROM DBA_OBJECTS o, DBA_PLSQL_OBJECT_SETTINGS s
PL/SQL アプリケーションのパフォーマンスのチューニング
11-29
システム固有の実行のための PL/SQL コードのコンパイル
WHERE o.OBJECT_NAME = s.NAME AND o.STATUS='INVALID';
REM To stop spooling the output: SPOOL OFF
Oracle が提供するユニットが無効化されている場合は、有効化します。次に例を示します。
ALTER PACKAGE OLAPSYS.DBMS_AWM COMPILE BODY REUSE SETTINGS;
『Oracle Database SQL リファレンス』の ALTER FUNCTION、ALTER PACKAGE および
ALTER PROCEDURE を参照してください。ユニットを有効化できない場合は、今後の解決
のためスプール・ログを保存してから処理を続けます。
6.
次の問合せを実行して、NATIVE および INTERPRETED にコンパイルされるオブジェクト
の数を確認します。問合せの出力を保存する場合は、SQL の SPOOL コマンドを使用しま
す。
例 11-21 PL/SQL のコンパイル・タイプの確認
SELECT TYPE, PLSQL_CODE_TYPE, COUNT(*) FROM DBA_PLSQL_OBJECT_SETTINGS
WHERE PLSQL_CODE_TYPE IS NOT NULL
GROUP BY TYPE, PLSQL_CODE_TYPE
ORDER BY TYPE, PLSQL_CODE_TYPE;
NULL plsql_code_type のオブジェクトは特別な内部オブジェクトであり、無視してか
まいません。
7.
ユーザー SYS として $ORACLE_HOME/rdbms/admin/dbmsupgnv.sql スクリプトを実行
して、すべての PL/SQL ユニットのディクショナリ表で plsql_code_type 設定を
NATIVE に更新します。この処理によってもユニットが無効化されます。パッケージ仕様
部を除外するときは、スクリプトで TRUE を使用します。パッケージ仕様部を含めるとき
は、FALSE を使用します。
この更新は、データベースが UPGRADE モードの場合に実行する必要があります。スクリ
プトを使用すると、更新を正常に完了できます。また、すべての変更をロールバックする
こともできます。
8.
データベースを停止し、NORMAL モードで再起動します。
9.
問題の発生を回避するため、utlrp.sql スクリプトを実行する前に他のセッションに接続
しないことをお薦めします。このためには、次の文を実行します。
ALTER SYSTEM ENABLE RESTRICTED SESSION;
10. ユーザー SYS として $ORACLE_HOME/rdbms/admin/utlrp.sql スクリプトを実行しま
す。このスクリプトでは、デフォルトの並列度を使用してすべての PL/SQL モジュールを
再コンパイルします。並列度を明示的に設定する方法については、スクリプトのコメント
を参照してください。
スクリプトが異常終了した場合は、utlrp.sql スクリプトを再実行して残りの無効な
PL/SQL モジュールを再コンパイルします。
11. コンパイルが正常に完了したら、例 11-20 の問合せを使用して、他に無効な PL/SQL ユ
ニットがないかを確認します。問合せの出力を post_upgrade_invalid.log ファイル
にスプーリングしておくと、以前に作成した pre_upgrade_invalid.log ファイルがあ
れば、スプーリングした内容と比較できます。
12. 例 11-21 の問合せを再実行します。dbmsupgnv.sql で再コンパイルした場合は、除外し
た TYPE 仕様部およびパッケージ仕様部を除くすべての PL/SQL ユニットが NATIVE であ
ることを確認します。dbmsupgin.sql で再コンパイルした場合は、すべての PL/SQL ユ
ニットが INTERPRETED であることを確認します。
13. データベースの制限付きセッション・モードを無効にしてから、前に停止したサービスを
開始します。制限付きセッション・モードを無効にするには次の文を実行します。
ALTER SYSTEM DISABLE RESTRICTED SESSION;
11-30
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
パイプライン・ファンクションによる変換の設定
パイプライン・ファンクションによる変換の設定
この項では、パイプライン・テーブル・ファンクションと呼ばれる特殊なファンクションを連
鎖する方法について説明します。テーブル・ファンクションは、データ・ウェアハウスなどで
複数の変換をデータに適用する場合に使用します。
参照 :
■
次の URL で「テーブル・ファンクションとカーソル式」を参照してく
ださい。
http://www.oracle.com/technology/tech/pl_sql/pdf
/PLSQL_9i_New_Features_Doc.pdf
■
「テーブル・ファンクションとカーソル式」の例は、次の URL にアク
セスしてください。
http://www.oracle.com/technology/sample_code/tech
/pl_sql/index.html
■
パイプラインと並列テーブル・ファンクションの詳細は、
『Oracle
Database データ・カートリッジ開発者ガイド』を参照してください。
パイプライン・テーブル・ファンクションの概要
パイプライン・テーブル・ファンクションは、物理データベース表と同様に問合せできるよう
に、または PL/SQL コレクション変数に代入できるように、行のコレクション(ネストした表
または VARRAY)を生成するファンクションです。テーブル・ファンクションは、問合せの
FROM 句にあるデータベース表の名前のかわりに、または問合せの SELECT リストにある列名
のかわりに使用できます。
テーブル・ファンクションは、入力として行のコレクションを使用することができます。入力
コレクション・パラメータには、コレクション型(VARRAY や PL/SQL 表など)または REF
CURSOR を使用できます。
テーブル・ファンクションの実行はパラレル化でき、戻される行は中間のステージングなしで
次のプロセスに直接送ることができます。テーブル・ファンクションから戻されるコレクショ
ンの行は、パイプライン化することもできます。つまり、テーブル・ファンクションの入力の
処理がすべて完了してからバッチで戻されるのではなく、生成された時点で反復的に戻されま
す。
テーブル・ファンクションのストリーム、パイプラインおよびパラレル実行によって、次のよ
うにパフォーマンスを改善できます。
■
マルチスレッドが可能になり、テーブル・ファンクションを同時に実行します。
■
プロセス間の中間的なステージングを排除します。
■
■
問合せの応答時間が短縮されます。パイプラインでないテーブル・ファンクションの場合
は、問合せで 1 つの結果行を戻す前に、テーブル・ファンクションから戻されるコレク
ション全体を組み立てて、サーバーに戻す必要があります。パイプライン化によって、行
を、生成時に反復的に戻すことができます。また、オブジェクト・キャッシュでコレク
ション全体をマテリアライズする必要がないため、テーブル・ファンクションのメモリー
消費量も減少します。
コレクション全体が表やメモリーにステージングされるまで待ってから、コレクション全
体を戻すのではなく、各行の生成時にテーブル・ファンクションから戻されるコレクショ
ンの結果行を反復的に提供します。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-31
パイプライン・ファンクションによる変換の設定
パイプライン・テーブル・ファンクションの記述
パイプライン・テーブル・ファンクションを宣言するには、PIPELINED キーワードを指定しま
す。パイプライン・ファンクションは、CREATE FUNCTION を使用してスキーマ・レベルで定
義することも、パッケージに定義することもできます。PIPELINED キーワードは、ファンク
ションが行を反復的に戻すことを示します。パイプライン・テーブル・ファンクションの戻り
型は、ネストした表や VARRAY など、サポートされているコレクション型である必要がありま
す。このコレクション型は、スキーマ・レベルまたはパッケージ内で宣言できます。ファンク
ション内では、コレクション型の個々の要素を戻します。コレクション型の要素は、NUMBER
や VARCHAR2 など、サポートされている SQL データ型である必要があります。パイプライン・
ファンクションでは、PLS_INTEGER や BOOLEAN などの PL/SQL データ型はコレクション要
素としてサポートされません。
例 11-22 に、パイプライン・テーブル・ファンクションの結果を PL/SQL コレクション変数に
代入し、そのファンクションを SELECT 文で使用する方法を示します。
例 11-22 テーブル・ファンクションの結果の代入
CREATE PACKAGE pkg1 AS
TYPE numset_t IS TABLE OF NUMBER;
FUNCTION f1(x NUMBER) RETURN numset_t PIPELINED;
END pkg1;
/
CREATE PACKAGE BODY pkg1 AS
-- FUNCTION f1 returns a collection of elements (1,2,3,... x)
FUNCTION f1(x NUMBER) RETURN numset_t PIPELINED IS
BEGIN
FOR i IN 1..x LOOP
PIPE ROW(i);
END LOOP;
RETURN;
END;
END pkg1;
/
-- pipelined function is used in FROM clause of SELECT statement
SELECT * FROM TABLE(pkg1.f1(5));
変換へのパイプライン・テーブル・ファンクションの使用
パイプライン・テーブル・ファンクションには、通常のファンクションに使用できる引数であ
れば、すべて使用できます。引数として REF CURSOR を受け入れるテーブル・ファンクション
は、変換ファンクションとして使用できます。つまり、REF CURSOR を使用して入力行を
フェッチし、その変換を実行し、結果をパイプラインで出力できます。
例 11-23 では、f_trans ファンクションが employees 表の 1 行を 2 行に変換しています。
例 11-23 変換へのパイプライン・テーブル・ファンクションの使用
-- Define the ref cursor types and function
CREATE OR REPLACE PACKAGE refcur_pkg IS
TYPE refcur_t IS REF CURSOR RETURN employees%ROWTYPE;
TYPE outrec_typ IS RECORD (
var_num
NUMBER(6),
var_char1 VARCHAR2(30),
var_char2 VARCHAR2(30));
TYPE outrecset IS TABLE OF outrec_typ;
FUNCTION f_trans(p refcur_t)
RETURN outrecset PIPELINED;
END refcur_pkg;
/
11-32
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
パイプライン・ファンクションによる変換の設定
CREATE OR REPLACE PACKAGE BODY refcur_pkg IS
FUNCTION f_trans(p refcur_t)
RETURN outrecset PIPELINED IS
out_rec outrec_typ;
in_rec p%ROWTYPE;
BEGIN
LOOP
FETCH p INTO in_rec;
EXIT WHEN p%NOTFOUND;
-- first row
out_rec.var_num := in_rec.employee_id;
out_rec.var_char1 := in_rec.first_name;
out_rec.var_char2 := in_rec.last_name;
PIPE ROW(out_rec);
-- second row
out_rec.var_char1 := in_rec.email;
out_rec.var_char2 := in_rec.phone_number;
PIPE ROW(out_rec);
END LOOP;
CLOSE p;
RETURN;
END;
END refcur_pkg;
/
-- SELECT query using the f_transc table function
SELECT * FROM TABLE(
refcur_pkg.f_trans(CURSOR(SELECT * FROM employees WHERE department_id = 60)));
この問合せでは、パイプライン・テーブル・ファンクション f_trans は CURSOR 副問合せ
SELECT * FROM employees ... から行をフェッチし、変換を実行して、結果をパイプライ
ンでユーザーに表として戻します。このファンクションでは、入力行ごとに出力行(コレク
ション要素)が 2 行ずつ生成されます。
例 11-23 のように、CURSOR 副問合せが SQL から REF CURSOR ファンクションの引数に渡され
る場合、ファンクションの実行中には参照先のカーソルがすでにオープンされています。
パイプライン・テーブル・ファンクションからの結果の戻し
PL/SQL では、PIPE ROW 文によってパイプライン・テーブル・ファンクションで行がパイプ
され、処理が継続します。この文を使用すると、PL/SQL のテーブル・ファンクションで生成
直後に行を戻すことができます。パフォーマンス上の理由から、PL/SQL ランタイム・システ
ムでは、行はコンシューマにバッチで与えられます。
例 11-23 の PIPE ROW(out_rec) 文では、データをパイプラインで PL/SQL テーブル・ファ
ンクションから戻しています。out_rec はレコードで、その型は出力コレクションの要素の型
と一致します。
PIPE ROW 文を使用できるのはパイプライン・テーブル・ファンクションの本体内のみで、他
の場所で使用するとエラーが呼び出されます。行を戻さないパイプライン・テーブル・ファン
クションの場合は、PIPE ROW 文を省略できます。
パイプライン・テーブル・ファンクションでは、値を戻さない RETURN 文を含めることもでき
ます。この RETURN 文は、制御をコンシューマに移し、次回のフェッチで NO_DATA_FOUND 例
外が確実に呼び出されるようにします。
テーブル・ファンクションとコール元のルーチンは、行の生成に伴って制御をやり取りするた
め、テーブル・ファンクションと PRAGMA AUTONOMOUS_TRANSACTION の組合せに関する制
限があります。テーブル・ファンクションが自律型トランザクションの一部である場合、コー
ル元のサブプログラムでエラーが発生しないように、各 PIPE ROW 文の前に COMMIT または
ROLLBACK を実行する必要があります。
PL/SQL アプリケーションのパフォーマンスのチューニング
11-33
パイプライン・ファンクションによる変換の設定
Oracle には、オブジェクトやコレクション型など、他の SQL 型の型記述、データ・インスタン
スおよびデータ・インスタンス・セットを動的にカプセル化してアクセスできるように、3 つ
の特別なデータ型が用意されています。また、この 3 つの型を使用すると、匿名コレクション
型のように匿名の(つまり、名前を持たない)型を作成できます。この 3 つの型は、
SYS.ANYTYPE、SYS.ANYDATA および SYS.ANYDATASET です。SYS.ANYDATA 型は、テーブ
ル・ファンクションからの戻り値として役立つ場合があります。
参照 : ANYTYPE、ANYDATA および ANYDATASET 型へのインタフェース
と、この 3 つの型で使用する DBMS_TYPES パッケージについては、
『Oracle Database PL/SQL パッケージ・プロシージャおよびタイプ・リ
ファレンス』を参照してください。
PL/SQL テーブル・ファンクション間のデータのパイプライン
シリアル実行では、コルーチン実行に似たアプローチを使用して、結果がある PL/SQL テーブ
ル・ファンクションから別の PL/SQL テーブル・ファンクションへとパイプラインされます。
たとえば、次の文では、ファンクション g からファンクション f へと結果がパイプラインされ
ます。
SELECT * FROM TABLE(f(CURSOR(SELECT * FROM TABLE(g()))));
パラレル実行の場合も同様ですが、各ファンクションは異なるプロセス(またはプロセス・
セット)で実行されます。
パイプライン・テーブル・ファンクションに対する複数コールの最適化
パイプライン・テーブル・ファンクションを同じ問合せまたは別の問合せで複数回コールする
と、基礎となる実装が複数回実行されます。デフォルトでは、行のバッファリングや再利用は
行われません。次に例を示します。
SELECT * FROM
WHERE t1.id
SELECT * FROM
SELECT * FROM
TABLE(f(...)) t1, TABLE(f(...)) t2
= t2.id;
TABLE(f());
TABLE(f());
ファンクションが、渡される値の各組合せに対して常に同じ結果の値を生成する場合、ファン
クション DETERMINISTIC を宣言すると、Oracle によって行が自動的にバッファリングされま
す。ファンクションが実際は非決定的である場合、予測できない結果になります。
パイプライン・テーブル・ファンクションの結果からのフェッチ
PL/SQL の CURSOR と REF CURSOR は、テーブル・ファンクションに対する問合せ用に定義
できます。次に例を示します。
OPEN c FOR SELECT * FROM TABLE(f(...));
テーブル・ファンクションのカーソルと通常のカーソルでは、フェッチの意味は同じです。
テーブル・ファンクションに基づく REF CURSOR の代入に特別な意味はありません。
ただし、SQL オプティマイザでは、PL/SQL 文にまたがる最適化は行われません。次に例を示
します。
DECLARE
r SYS_REFCURSOR;
BEGIN
OPEN r FOR SELECT *
FROM TABLE(f(CURSOR(SELECT * FROM tab)));
SELECT * BULK COLLECT INTO rec_tab FROM TABLE(g(r));
END;
/
11-34
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
パイプライン・ファンクションによる変換の設定
前述の例は、次の例と同様には実行されません。
SELECT * FROM TABLE(g(CURSOR(SELECT * FROM
TABLE(f(CURSOR(SELECT * FROM tab))))));
これは、2 つの SQL 文の実行に関連するオーバーヘッドを無視して、2 つの文の間で結果をパ
イプラインできると想定した場合も同様です。
カーソル変数によるデータの引渡し
PL/SQL ファンクションに REF CURSOR パラメータで行セットを渡すことができます。たとえ
ば、このファンクションが事前定義された弱い型指定の REF CURSOR を持つ SYS_REFCURSOR
型の引数を受け入れるように宣言されているとします。
FUNCTION f(p1 IN SYS_REFCURSOR) RETURN ... ;
副問合せの結果をファンクションに直接渡すことができます。
SELECT * FROM TABLE(f(CURSOR(SELECT empid FROM tab)));
この例では、副問合せの結果を REF CURSOR パラメータとして渡す必要があることを示すため
に、CURSOR キーワードが必要です。
事前定義の弱い REF CURSOR 型の SYS_REFCURSOR もサポートされます。SYS_REFCURSOR を
使用すると、パッケージ内で REF CURSOR 型を使用前に作成する必要はありません。
強い REF CURSOR 型を使用する場合は、PL/SQL パッケージを作成し、その中で宣言する必要
があります。また、強い REF CURSOR 型をテーブル・ファンクションの引数として使用する場
合は、REF CURSOR 引数の実際の型が列の型と一致する必要があります。一致しない場合は、
エラーが生成されます。テーブル・ファンクションの弱い REF CURSOR 引数をパーティション
化するには、PARTITION BY ANY 句を使用する必要があります。弱い REF CURSOR 引数には、
レンジ・パーティション化もハッシュ・パーティション化も使用できません。
例 11-24 に示すように、PL/SQL ファンクションは複数の REF CURSOR 入力変数を受け入れる
ことができます。
例 11-24 複数の REF CURSOR 入力変数の使用
-- Define the ref cursor types
CREATE PACKAGE refcur_pkg IS
TYPE refcur_t1 IS REF CURSOR RETURN employees%ROWTYPE;
TYPE refcur_t2 IS REF CURSOR RETURN departments%ROWTYPE;
TYPE outrec_typ IS RECORD (
var_num
NUMBER(6),
var_char1 VARCHAR2(30),
var_char2 VARCHAR2(30));
TYPE outrecset IS TABLE OF outrec_typ;
FUNCTION g_trans(p1 refcur_t1, p2 refcur_t2)
RETURN outrecset PIPELINED;
END refcur_pkg;
/
CREATE PACKAGE BODY refcur_pkg IS
FUNCTION g_trans(p1 refcur_t1, p2 refcur_t2)
RETURN outrecset PIPELINED IS
out_rec outrec_typ;
in_rec1 p1%ROWTYPE;
in_rec2 p2%ROWTYPE;
BEGIN
LOOP
FETCH p2 INTO in_rec2;
EXIT WHEN p2%NOTFOUND;
END LOOP;
CLOSE p2;
LOOP
PL/SQL アプリケーションのパフォーマンスのチューニング
11-35
パイプライン・ファンクションによる変換の設定
FETCH p1 INTO in_rec1;
EXIT WHEN p1%NOTFOUND;
-- first row
out_rec.var_num := in_rec1.employee_id;
out_rec.var_char1 := in_rec1.first_name;
out_rec.var_char2 := in_rec1.last_name;
PIPE ROW(out_rec);
-- second row
out_rec.var_num := in_rec2.department_id;
out_rec.var_char1 := in_rec2.department_name;
out_rec.var_char2 := TO_CHAR(in_rec2.location_id);
PIPE ROW(out_rec);
END LOOP;
CLOSE p1;
RETURN;
END;
END refcur_pkg;
/
-- SELECT query using the g_trans table function
SELECT * FROM TABLE(refcur_pkg.g_trans(
CURSOR(SELECT * FROM employees WHERE department_id = 60),
CURSOR(SELECT * FROM departments WHERE department_id = 60)));
戻されたデータを反復する REF CURSOR を作成すると、テーブル・ファンクションの戻り値を
他のテーブル・ファンクションに渡すことができます。
SELECT * FROM TABLE(f(CURSOR(SELECT * FROM TABLE(g(...)))));
問合せに対して REF CURSOR を明示的にオープンし、それをテーブル・ファンクションにパラ
メータとして渡すことができます。
DECLARE
r SYS_REFCURSOR;
rec ...;
BEGIN
OPEN r FOR SELECT * FROM TABLE(f(...));
-- Must return a single row result set.
SELECT * INTO rec FROM TABLE(g(r));
END;
/
この場合、テーブル・ファンクションは完了時にカーソルをクローズするため、プログラムで
はカーソルを明示的にクローズしないようにする必要があります。
テーブル・ファンクションでは、入力 REF CURSOR を使用して集計結果を計算できます。例
11-25 では、一連の入力行を反復することで、加重平均を計算しています。
例 11-25 集計関数としてのパイプライン・テーブル・ファンクションの使用
CREATE TABLE gradereport (student VARCHAR2(30), subject VARCHAR2(30),
weight NUMBER, grade NUMBER);
INSERT INTO gradereport VALUES('Mark', 'Physics', 4, 4);
INSERT INTO gradereport VALUES('Mark','Chemistry', 4, 3);
INSERT INTO gradereport VALUES('Mark','Maths', 3, 3);
INSERT INTO gradereport VALUES('Mark','Economics', 3, 4);
CREATE PACKAGE pkg_gpa IS
TYPE gpa IS TABLE OF NUMBER;
FUNCTION weighted_average(input_values SYS_REFCURSOR)
RETURN gpa PIPELINED;
END pkg_gpa;
/
CREATE PACKAGE BODY pkg_gpa IS
11-36
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
パイプライン・ファンクションによる変換の設定
FUNCTION weighted_average(input_values SYS_REFCURSOR)
RETURN gpa PIPELINED IS
grade NUMBER;
total NUMBER := 0;
total_weight NUMBER := 0;
weight NUMBER := 0;
BEGIN
-- The function accepts a ref cursor and loops through all the input rows
LOOP
FETCH input_values INTO weight, grade;
EXIT WHEN input_values%NOTFOUND;
-- Accumulate the weighted average
total_weight := total_weight + weight;
total := total + grade*weight;
END LOOP;
PIPE ROW (total / total_weight);
RETURN; -- the function returns a single result
END;
END pkg_gpa;
/
-- the query result comes back as a nested table with a single row
-- COLUMN_VALUE is a keyword that returns the contents of a nested table
SELECT w.column_value "weighted result" FROM TABLE(
pkg_gpa.weighted_average(CURSOR(SELECT weight, grade FROM gradereport))) w;
パイプライン・テーブル・ファンクション内での DML 操作の実行
DML 文を実行するには、AUTONOMOUS_TRANSACTION プラグマを使用してパイプライン・
テーブル・ファンクションを宣言します。これによって、ファンクションは、他のプロセスに
共有されない新しいトランザクションで実行されます。
CREATE FUNCTION f(p SYS_REFCURSOR)
RETURN CollType PIPELINED IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN NULL; END;
/
パラレル実行中に、テーブル・ファンクションの各インスタンスが独立したトランザクション
を作成します。
パイプライン・テーブル・ファンクションへの DML 操作の実行
パイプライン・テーブル・ファンクションを UPDATE、INSERT または DELETE 文のターゲッ
ト表にすることはできません。たとえば、次の文ではエラーが呼び出されます。
UPDATE F(CURSOR(SELECT * FROM tab)) SET col = value;
INSERT INTO f(...) VALUES ('any', 'thing');
ただし、テーブル・ファンクションのビューを作成し、INSTEAD OF トリガーを使用して更新
できます。次に例を示します。
CREATE VIEW BookTable AS SELECT x.Name, x.Author
FROM TABLE(GetBooks('data.txt')) x;
次の INSTEAD OF トリガーは、ユーザーが BookTable ビューに行を挿入すると起動します。
CREATE TRIGGER BookTable_insert
INSTEAD OF INSERT ON BookTable
REFERENCING NEW AS n
FOR EACH ROW
BEGIN
...
PL/SQL アプリケーションのパフォーマンスのチューニング
11-37
パイプライン・ファンクションによる変換の設定
END;
/
INSERT INTO BookTable VALUES (...);
INSTEAD OF トリガーは、テーブル・ファンクションに作成されたビューでのすべての DML
操作について定義できます。
パイプライン・テーブル・ファンクションの例外処理
パイプライン・テーブル・ファンクションの例外処理は、通常のファンクションの場合と同じ
です。
C や Java など、一部の言語には、ユーザー指定の例外処理のためのメカニズムが用意されてい
ます。テーブル・ファンクション内で呼び出された例外が処理される場合に、テーブル・ファ
ンクションは例外ハンドラを実行して処理を継続します。例外ハンドラを終了すると、制御が
外側の有効範囲に移ります。例外が解消されると、実行は通常どおり進行します。
テーブル・ファンクションに未処理の例外があると、親トランザクションがロールバックされ
ます。
11-38
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
12
PL/SQL のオブジェクト型の使用
オブジェクト指向プログラミングは、再利用可能なコンポーネントおよび複雑なアプリケー
ションを作成する場合に特に適しています。PL/SQL のオブジェクト指向のプログラミングは、
オブジェクト型をベースにしています。オブジェクト型を使用することによって、実社会のオ
ブジェクトをモデル化し、インタフェースと実装の細部を分離して、オブジェクト指向のデー
タをデータベースへ永続的に格納することが可能になります。
この章の項目は、次のとおりです。
■
PL/SQL でのオブジェクトの宣言と初期化
■
PL/SQL を使用したオブジェクトの操作
■
PL/SQL コレクション型に相当する SQL の型の定義
■
SQL のオブジェクト型での PL/SQL コレクションの使用
■
オブジェクトでの動的 SQL の使用
オブジェクト型の詳細は、
『Oracle Database アプリケーション開発者ガイド - オブジェクト・
リレーショナル機能』を参照してください。
PL/SQL のオブジェクト型の使用
12-1
PL/SQL でのオブジェクトの宣言と初期化
PL/SQL でのオブジェクトの宣言と初期化
オブジェクト型は、任意の実社会のエンティティを表すことができます。たとえば、オブジェ
クト型によって、学生、銀行口座、コンピュータ・スクリーン、有理数、またはデータ構造体
(待ち行列、スタック、リストなど)を表すことができます。
現在のところ、PL/SQL のブロック、サブプログラムまたはパッケージ内ではオブジェクト型
を定義できません。SQL*Plus では、SQL 文 CREATE TYPE を使用して対話形式で定義できま
す。1-17 ページの例 1-17「オブジェクト型の定義」を参照してください。
SQL の CREATE TYPE 文の詳細は、『Oracle Database SQL リファレンス』を参照してください。
SQL の CREATE TYPE BODY 文の詳細は、
『Oracle Database SQL リファレンス』を参照してく
ださい。
オブジェクト型を宣言してスキーマにインストールすると、任意の PL/SQL ブロック、サブプ
ログラムまたはパッケージの中で、それを使用してオブジェクトを宣言できます。たとえば、
そのオブジェクト型を使用して属性、列、変数、バインド変数、レコード・フィールド、表要
素、仮パラメータまたはファンクション結果のデータ型を指定できます。実行時には、そのオ
ブジェクト型のインスタンスが作成されます。つまり、その型のオブジェクトがインスタンス
化されます。オブジェクトごとに異なる値を保持できます。
そのようなオブジェクトは、通常の有効範囲規則とインスタンス化のルールに従います。ブ
ロックまたはサブプログラムでは、ローカル・オブジェクトは、ブロックまたはサブプログラ
ムに入ったときにインスタンス化され、ブロックまたはサブプログラムが終了した時点で消滅
します。パッケージでは、そのパッケージが初めて参照された時点でオブジェクトのインスタ
ンスが生成され、データベース・セッションが終わった時点で消滅します。
例 12-1 に、オブジェクト型、オブジェクト型本体およびオブジェクト型表を作成する方法を示
します。
例 12-1 オブジェクト型の使用
CREATE TYPE address_typ AS OBJECT (
street
VARCHAR2(30),
city
VARCHAR2(20),
state
CHAR(2),
postal_code
VARCHAR2(6) );
/
CREATE TYPE employee_typ AS OBJECT (
employee_id
NUMBER(6),
first_name
VARCHAR2(20),
last_name
VARCHAR2(25),
email
VARCHAR2(25),
phone_number
VARCHAR2(20),
hire_date
DATE,
job_id
VARCHAR2(10),
salary
NUMBER(8,2),
commission_pct
NUMBER(2,2),
manager_id
NUMBER(6),
department_id
NUMBER(4),
address
address_typ,
MAP MEMBER FUNCTION get_idno RETURN NUMBER,
MEMBER PROCEDURE display_address ( SELF IN OUT NOCOPY employee_typ ) );
/
CREATE TYPE BODY employee_typ AS
MAP MEMBER FUNCTION get_idno RETURN NUMBER IS
BEGIN
RETURN employee_id;
END;
MEMBER PROCEDURE display_address ( SELF IN OUT NOCOPY employee_typ ) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(first_name || ' ' || last_name);
DBMS_OUTPUT.PUT_LINE(address.street);
DBMS_OUTPUT.PUT_LINE(address.city || ', ' || address.state || ' ' ||
12-2
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL でのオブジェクトの宣言と初期化
address.postal_code);
END;
END;
/
CREATE TABLE employee_tab OF employee_typ;
PL/SQL ブロックでのオブジェクトの宣言
CHAR や NUMBER などの組込み型を使用できるところであれば、どこでもオブジェクト型を使
用できます。例 12-2 では、employee_typ 型のオブジェクト emp を宣言しています。その後、
オブジェクト型 employee_typ のコンストラクタをコールして、そのオブジェクトを初期化
します。
例 12-2 PL/SQL ブロックでのオブジェクト型の宣言
DECLARE
emp employee_typ; -- emp is atomically null
BEGIN
-- call the constructor for employee_typ
emp := employee_typ(315, 'Francis', 'Logan', 'FLOGAN',
'555.777.2222', '01-MAY-04', 'SA_MAN', 11000, .15, 101, 110,
address_typ('376 Mission', 'San Francisco', 'CA', '94222'));
DBMS_OUTPUT.PUT_LINE(emp.first_name || ' ' || emp.last_name); -- display details
emp.display_address(); -- call object method to display details
END;
/
オブジェクトは、ファンクションおよびプロシージャの仮パラメータとして宣言できます。そ
のようにすると、オブジェクトをストアド・サブプログラムに渡したり、あるサブプログラム
から別のサブプログラムに渡すことができます。次の例では、オブジェクト型 employee_typ
を使用して仮パラメータのデータ型を指定しています。
PROCEDURE open_acct (new_acct IN OUT employee_typ) IS ...
次の例では、オブジェクト型 employee_typ を使用してファンクションの戻り型を指定して
います。
FUNCTION get_acct (acct_id IN NUMBER) RETURN employee_typ IS ...
PL/SQL による未初期化オブジェクトの処理
オブジェクト型のためのコンストラクタをコールしてそのオブジェクトを初期化するまで、そ
のオブジェクトは基本構造的に NULL になっています。つまり、その属性のみではなくオブ
ジェクトそのものが NULL になっています。
NULL のオブジェクトが別のオブジェクトと等しくなることは決してありません。実際のとこ
ろ、NULL のオブジェクトを別のオブジェクトと比較すると、常に NULL になります。また、
基本構造的に NULL になっているオブジェクトを他のオブジェクトに代入すると、そのオブ
ジェクトも基本構造的に NULL になります(したがって再度初期化する必要があります)。同
じように、値のない NULL をオブジェクトに代入すると、そのオブジェクトは基本構造的に
NULL になります。
式の中で、未初期化オブジェクトの属性は NULL として評価されます。IS NULL 比較演算子を
未初期化オブジェクトまたはその属性に適用すると、結果は TRUE になります。
例 12-3 に、NULL のオブジェクトおよび属性が NULL であるオブジェクトを示します。
例 12-3 PL/SQL ブロックでの NULL のオブジェクト
DECLARE
emp employee_typ; -- emp is atomically null
BEGIN
IF emp IS NULL THEN DBMS_OUTPUT.PUT_LINE('emp is NULL #1'); END IF;
IF emp.employee_id IS NULL THEN
PL/SQL のオブジェクト型の使用
12-3
PL/SQL を使用したオブジェクトの操作
DBMS_OUTPUT.PUT_LINE('emp.employee_id is NULL #1');
END IF;
emp.employee_id := 330;
IF emp IS NULL THEN DBMS_OUTPUT.PUT_LINE('emp is NULL #2'); END IF;
IF emp.employee_id IS NULL THEN
DBMS_OUTPUT.PUT_LINE('emp.employee_id is NULL #2');
END IF;
emp := employee_typ(NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
address_typ(NULL, NULL, NULL, NULL));
-- emp := NULL; -- this would have made the following IF statement TRUE
IF emp IS NULL THEN DBMS_OUTPUT.PUT_LINE('emp is NULL #3'); END IF;
IF emp.employee_id IS NULL THEN
DBMS_OUTPUT.PUT_LINE('emp.employee_id is NULL #3');
END IF;
EXCEPTION
WHEN ACCESS_INTO_NULL THEN
DBMS_OUTPUT.PUT_LINE('Cannot assign value to NULL object');
END;
/
出力は次のとおりです。
emp is NULL #1
emp.employee_id is NULL #1
emp is NULL #2
emp.employee_id is NULL #3
未初期化オブジェクトのメソッドのコールによって、事前定義済の例外
NULL_SELF_DISPATCH が呼び出されます。未初期化オブジェクトの属性を IN パラメータへ
の引数として渡すと、それは NULL と評価されます。OUT または IN OUT パラメータへの引数
として渡されると、書き込むときに例外が呼び出されます。
PL/SQL を使用したオブジェクトの操作
PL/SQL を使用してオブジェクト・メソッドを記述したり、オブジェクトを操作する方法につ
いて説明します。
ドット表記法を使用したオブジェクト属性へのアクセス
属性は名前で参照します。属性にアクセスしたり、その値を変更するには、ドット表記法を使
用します。属性名を連鎖させて、ネストされたオブジェクト型の属性にアクセスできます。次
に例を示します。
例 12-4 オブジェクト属性へのアクセス
DECLARE
emp employee_typ;
BEGIN
emp := employee_typ(315, 'Francis', 'Logan', 'FLOGAN',
'555.777.2222', '01-MAY-04', 'SA_MAN', 11000, .15, 101, 110,
address_typ('376 Mission', 'San Francisco', 'CA', '94222'));
DBMS_OUTPUT.PUT_LINE(emp.first_name || ' ' || emp.last_name);
DBMS_OUTPUT.PUT_LINE(emp.address.street);
DBMS_OUTPUT.PUT_LINE(emp.address.city || ', ' ||emp. address.state || ' ' ||
emp.address.postal_code);
END;
/
12-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL を使用したオブジェクトの操作
オブジェクトコンストラクタおよびメソッドのコール
コンストラクタは、ファンクション・コールが許可されているところでコールできます。12-4
ページの例 12-4 および例 12-5 に示すように、すべてのファンクションと同じく、コンストラク
タは式の一部としてコールされます。
例 12-5 オブジェクト表での行の挿入
DECLARE
emp employee_typ;
BEGIN
INSERT INTO employee_tab VALUES (employee_typ(310, 'Evers', 'Boston', 'EBOSTON',
'555.111.2222', '01-AUG-04', 'SA_REP', 9000, .15, 101, 110,
address_typ('123 Main', 'San Francisco', 'CA', '94111')) );
INSERT INTO employee_tab VALUES (employee_typ(320, 'Martha', 'Dunn', 'MDUNN',
'555.111.3333', '30-SEP-04', 'AC_MGR', 12500, 0, 101, 110,
address_typ('123 Broadway', 'Redwood City', 'CA', '94065')) );
END;
/
パラメータをコンストラクタに渡してコンストラクタをコールすると、インスタンスを生成す
るオブジェクトの属性に初期値が代入されます。すべての属性に値を入れるためにデフォル
ト・コンストラクタをコールする場合、属性には定数や変数とは異なりデフォルト値がないた
め、すべての属性にパラメータを指定する必要があります。位置表記法ではなく名前表記法を
使用してコンストラクタをコールすることもできます。
パッケージ化されたサブプログラムと同じく、メソッドはドット表記法を使用してコールされ
ます。例 12-6 では、オブジェクトの属性を表示するために display_address メソッドが
コールされています。VALUE ファンクションを使用すると、オブジェクトの値が戻されます。
VALUE は相関変数を引数とします。ここでの相関変数とは、オブジェクト表の行に対応付けら
れている行変数または表別名のことです。
例 12-6 オブジェクト・メソッドへのアクセス
DECLARE
emp employee_typ;
BEGIN
SELECT VALUE(e) INTO emp FROM employee_tab e WHERE e.employee_id = 310;
emp.display_address();
END;
/
SQL 文からパラメータのないメソッドをコールするには、空のパラメータ・リストが必要で
す。プロシージャ文では、コールを連鎖しないかぎり空のパラメータ・リストは必要ありませ
ん。連鎖する場合は、最後のコール以外のすべてのコールで空のパラメータ・リストが必要で
す。プロシージャは式の一部としてではなく文としてコールされため、追加のメソッド・コー
ルをプロシージャの右側に連鎖させることはできません。さらに、2 つのファンクション・
コールの連鎖では、1 番目のファンクションは 2 番目のファンクションに渡せるオブジェクト
を戻す必要があります。
静的メソッドの場合、コールでは型のインスタンスを指定するかわりに、表記法
type_name.method_name を使用します。
サブタイプのインスタンスを使用してメソッドをコールする場合、実際に実行されるメソッド
は型の継承での宣言によって決まります。サブタイプがスーパータイプから継承するメソッド
をオーバーライドする場合、コールではサブタイプの実装が使用されます。また、サブタイプ
がメソッドをオーバーライドしない場合、コールではスーパータイプの実装が使用されます。
この機能は動的メソッド・ディスパッチと呼ばれます。
PL/SQL のオブジェクト型の使用
12-5
PL/SQL を使用したオブジェクトの操作
注意 : PL/SQL を使用してメソッドを実装する場合は、super キーワー
ドが指定されたベースまたはスーパータイプのオブジェクト・メソッド、
または導出されたオブジェクト内の同等のメソッドをコールできません。
スーパータイプ、サブタイプおよびオブジェクト・メソッドの詳細は、
『Oracle Database アプリケーション開発者ガイド - オブジェクト・リレー
ショナル機能』を参照してください。
オブジェクトの更新および削除
PL/SQL ブロック内から、オブジェクト表の行を変更および削除できます。
例 12-7 オブジェクト表での行の更新および削除
DECLARE
emp employee_typ;
BEGIN
INSERT INTO employee_tab VALUES (employee_typ(370, 'Robert', 'Myers', 'RMYERS',
'555.111.2277', '07-NOV-04', 'SA_REP', 8800, .12, 101, 110,
address_typ('540 Fillmore', 'San Francisco', 'CA', '94011')) );
UPDATE employee_tab e SET e.address.street = '1040 California'
WHERE e.employee_id = 370;
DELETE FROM employee_tab e WHERE e.employee_id = 310;
END;
/
Ref 修飾子を使用したオブジェクトの操作
ファンクション REF を使用すると、ref を取り出せます。このファンクションは、相関変数を
引数とします。
例 12-8 REF 修飾子を使用したオブジェクト表での行の更新
DECLARE
emp
employee_typ;
emp_ref REF employee_typ;
BEGIN
SELECT REF(e) INTO emp_ref FROM employee_tab e WHERE e.employee_id = 370;
UPDATE employee_tab e
SET e.address = address_typ('8701 College', 'Oakland', 'CA', '94321')
WHERE REF(e) = emp_ref;
END;
/
ref は、変数、パラメータ、フィールド、または属性として宣言できます。ref は SQL の DML
文の中で入力変数または出力変数として使用できます。
PL/SQL では、ref を通してナビゲートできません。たとえば、ref を使用した例 12-9 の代入は
誤りです。オブジェクトにアクセスするにはファンクション DEREF を使用するか、パッケージ
UTL_REF をコールする必要があります。REF ファンクションの詳細は、
『Oracle Database SQL
リファレンス』を参照してください。
例 12-9 SELECT INTO 文での DEREF の使用
DECLARE
emp
emp_ref REF
emp_name
BEGIN
SELECT REF(e)
12-6
employee_typ;
employee_typ;
VARCHAR2(50);
INTO emp_ref FROM employee_tab e WHERE e.employee_id = 370;
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
PL/SQL コレクション型に相当する SQL の型の定義
-- the following assignment raises an error, not allowed in PL/SQL
-- emp_name := emp_ref.first_name || ' ' || emp_ref.last_name;
-- emp := DEREF(emp_ref); not allowed, cannot use DEREF in procedural statements
SELECT DEREF(emp_ref) INTO emp FROM DUAL; -- use dummy table DUAL
emp_name := emp.first_name || ' ' || emp.last_name;
DBMS_OUTPUT.PUT_LINE(emp_name);
END;
/
DEREF ファンクションの詳細は、『Oracle Database SQL リファレンス』を参照してください。
PL/SQL コレクション型に相当する SQL の型の定義
ネストした表および VARRAY をデータベース表の内部に格納するには、CREATE TYPE 文を使
用して SQL の型を宣言することも必要です。SQL の型は、列としてまたは SQL オブジェクト
型の属性として使用できます。SQL の CREATE TYPE 文の詳細は、『Oracle Database SQL リ
ファレンス』を参照してください。SQL の CREATE TYPE BODY 文の詳細は、
『Oracle Database
SQL リファレンス』を参照してください。オブジェクト型の詳細は、
『Oracle Database アプリ
ケーション開発者ガイド - オブジェクト・リレーショナル機能』を参照してください。
PL/SQL 内で相当する型を宣言するか、PL/SQL の変数宣言で SQL の型名を使用できます。
例 12-10 は、SQL で宣言したネストした表をオブジェクト型の属性として使用する方法を示し
ています。
例 12-10 SQL でのネストした表の宣言
CREATE TYPE CourseList AS TABLE OF VARCHAR2(10) -- define type
/
CREATE TYPE student AS OBJECT ( -- create object
id_num INTEGER(4),
name
VARCHAR2(25),
address VARCHAR2(35),
status CHAR(2),
courses CourseList); -- declare nested table as attribute
/
CREATE TABLE sophomores of student
NESTED TABLE courses STORE AS courses_nt;
識別子 courses はネストした表全体を表します。courses の各要素には、'Math 1020' な
どの大学のコース名を入れます。
例 12-11 によって、VARRAY を格納するデータベースの列が作成されます。VARRAY の各要素
には VARCHAR2 型が格納されます。
例 12-11 VARRAY 列を持つ表の作成
-- Each project has a 16-character code name.
-- We will store up to 50 projects at a time in a database column.
CREATE TYPE ProjectList AS VARRAY(50) OF VARCHAR2(16);
/
CREATE TABLE dept_projects ( -- create database table
dept_id NUMBER(2),
name
VARCHAR2(15),
budget NUMBER(11,2),
-- Each department can have up to 50 projects.
projects ProjectList);
PL/SQL のオブジェクト型の使用
12-7
PL/SQL コレクション型に相当する SQL の型の定義
例 12-12 では、行をデータベース表 dept_projects に挿入しています。VARRAY コンストラ
クタ ProjectList() によって、列 projects の値が指定されます。
例 12-12 SQL 文の中での VARRAY コンストラクタ
BEGIN
INSERT INTO dept_projects
VALUES(60, 'Security', 750400,
ProjectList('New Badges', 'Track Computers', 'Check Exits'));
END;
/
例 12-13 では、複数のスカラー値およびネストした表 CourseList を sophomores 表に挿入
しています。
例 12-13 SQL 文の中でのネストした表のコンストラクタ
CREATE TABLE sophomores of student
NESTED TABLE courses STORE AS courses_nt;
BEGIN
INSERT INTO sophomores
VALUES (5035, 'Janet Alvarez', '122 Broad St', 'FT',
CourseList('Econ 2010', 'Acct 3401', 'Mgmt 3100'));
END;
/
SQL での個々のコレクション要素の操作
デフォルトの SQL 操作では、個々の要素ではなく、コレクション全体が格納および取得されま
す。SQL で、コレクションの個々の要素を操作するには、TABLE 演算子を使用します。TABLE
演算子は、副問合せを使用して VARRAY またはネストした表を抽出します。その結果、
INSERT 文、UPDATE 文または DELETE 文が、トップレベルの表ではなく、ネストした表に適
用されます。
PL/SQL のネストした表での DML 操作には、TABLE 演算子と CAST 演算子を使用します。こ
の方法によって、ネストした表をデータベースに実際に格納せずに、SQL 表記法を使用してネ
ストした表で集合演算を実行できます。
CAST のオペランドは、PL/SQL コレクション変数と SQL コレクション型(CREATE TYPE 文
で作成)です。CAST によって、PL/SQL コレクションが SQL の型に変換されます。
例 12-14 CAST を使用した PL/SQL のネストした表での操作の実行
CREATE TYPE Course AS OBJECT
(course_no NUMBER,
title
VARCHAR2(64),
credits
NUMBER);
/
CREATE TYPE CourseList AS TABLE OF course;
/
-- create department table
CREATE TABLE department (
name
VARCHAR2(20),
director VARCHAR2(20),
office VARCHAR2(20),
courses CourseList)
NESTED TABLE courses STORE AS courses_tab;
INSERT INTO department VALUES ('English', 'June Johnson', '491C',
CourseList(Course(1002, 'Expository Writing', 4),
Course(2020, 'Film and Literature', 4),
12-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
SQL のオブジェクト型での PL/SQL コレクションの使用
Course(4210, '20th-Century Poetry', 4),
Course(4725, 'Advanced Workshop in Poetry', 4)));
DECLARE
revised CourseList :=
CourseList(Course(1002, 'Expository Writing', 3),
Course(2020, 'Film and Literature', 4),
Course(4210, '20th-Century Poetry', 4),
Course(4725, 'Advanced Workshop in Poetry', 5));
num_changed INTEGER;
BEGIN
SELECT COUNT(*) INTO num_changed
FROM TABLE(CAST(revised AS CourseList)) new,
TABLE(SELECT courses FROM department
WHERE name = 'English') old
WHERE new.course_no = old.course_no AND
(new.title != old.title OR new.credits != old.credits);
DBMS_OUTPUT.PUT_LINE(num_changed);
END;
/
SQL のオブジェクト型での PL/SQL コレクションの使用
コレクションを使用すると、PL/SQL 内で複雑なデータ型を操作できます。添字を計算してメ
モリー内の特定の要素を処理し、SQL を使用してその結果をデータベース表に格納するように
プログラムを記述できます。
例 12-15 に示すように、SQL*Plus では、PL/SQL のネストした表および VARRAY に対応した
定義を持つ SQL のオブジェクト型を作成できます。列 dept_names 内の各項目は、特定の領
域の部門の名前を格納するネストした表です。データベース表にネストした表の列がある場合
は常に、NESTED TABLE 句が必要です。この句は、ネストした表を識別し、システム生成され
た記憶域表に名前を指定します。Oracle はネストした表のデータをこの記憶域表に格納します。
PL/SQL 内では、ネストした表の要素をループし、TRIM や EXTEND などのメソッドを使用し、
要素の一部またはすべてを更新することによって、ネストした表を操作できます。その後、更
新した表をデータベースに再度格納できます。ネストした表を含む表の行を挿入したり、行を
更新してネストした表を置換したり、PL/SQL 変数に入れるネストした表を選択することがで
きます。ネストした表の個々の要素を、SQL を使用して直接更新または削除することはできま
せん。表からネストした表を選択し、PL/SQL で変更してから、表を更新してその新しいネス
トした表を含める必要があります。
例 12-15 INSERT、
、UPDATE、
、DELETE および SELECT 文でのネストした表の使用
CREATE TYPE dnames_tab AS TABLE OF VARCHAR2(30);
/
CREATE TABLE depts (region VARCHAR2(25), dept_names dnames_tab)
NESTED TABLE dept_names STORE AS dnames_nt;
BEGIN
INSERT INTO depts VALUES('Europe', dnames_tab('Shipping','Sales','Finance'));
INSERT INTO depts VALUES('Americas', dnames_tab('Sales','Finance','Shipping'));
INSERT INTO depts VALUES('Asia', dnames_tab('Finance','Payroll'));
COMMIT;
END;
/
DECLARE
-- Type declaration is not needed, because PL/SQL can access the SQL object type
-- TYPE dnames_tab IS TABLE OF VARCHAR2(30); not needed
-- Declare a variable that can hold a set of department names
v_dnames dnames_tab;
-- Declare a record that can hold a row from the table
-- One of the record fields is a set of department names
v_depts depts%ROWTYPE;
PL/SQL のオブジェクト型の使用
12-9
SQL のオブジェクト型での PL/SQL コレクションの使用
new_dnames dnames_tab;
BEGIN
-- Look up a region and query just the associated department names
SELECT dept_names INTO v_dnames FROM depts WHERE region = 'Europe';
FOR i IN v_dnames.FIRST .. v_dnames.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Department names: ' || v_dnames(i));
END LOOP;
-- Look up a region and query the entire row
SELECT * INTO v_depts FROM depts WHERE region = 'Asia';
-- Now dept_names is a field in a record, so we access it with dot notation
FOR i IN v_depts.dept_names.FIRST .. v_depts.dept_names.LAST LOOP
-- Because we have all the table columns in the record, we can refer to region
DBMS_OUTPUT.PUT_LINE(v_depts.region || ' dept_names = ' ||
v_depts.dept_names(i));
END LOOP;
-- We can replace a set of department names with a new collection
-- in an UPDATE statement
new_dnames := dnames_tab('Sales','Payroll','Shipping');
UPDATE depts SET dept_names = new_dnames WHERE region = 'Europe';
-- Or we can modify the original collection and use it in the UPDATE.
-- We'll add a new final element and fill in a value
v_depts.dept_names.EXTEND(1);
v_depts.dept_names(v_depts.dept_names.COUNT) := 'Finance';
UPDATE depts SET dept_names = v_depts.dept_names
WHERE region = v_depts.region;
-- We can even treat the nested table column like a real table and
-- insert, update, or delete elements. The TABLE operator makes the statement
-- apply to the nested table produced by the subquery.
INSERT INTO TABLE(SELECT dept_names FROM depts WHERE region = 'Asia')
VALUES('Sales');
DELETE FROM TABLE(SELECT dept_names FROM depts WHERE region = 'Asia')
WHERE column_value = 'Payroll';
UPDATE TABLE(SELECT dept_names FROM depts WHERE region = 'Americas')
SET column_value = 'Payroll' WHERE column_value = 'Finance';
COMMIT;
END;
/
例 12-16 に、PL/SQL 文を使用して SQL の VARRY オブジェクト型を操作する方法を示します。
この例では、PL/SQL 変数と SQL 表の間で VARRAY を移します。VARRAY を含む表の行を挿
入したり、行を更新して VARRAY を置換したり、PL/SQL 変数に送信する VARRAY を選択す
ることができます。SQL を使用して、VARRAY の個々の要素を直接更新または削除することは
できません。表から VARRAY を選択し、PL/SQL 内で変更してから、表を更新してその新しい
VARRAY を含める必要があります。
例 12-16 INSERT、
、UPDATE、
、DELETE および SELECT 文での VARRAY の使用
-- By using a varray, we put an upper limit on the number of elements
-- and ensure they always come back in the same order
CREATE TYPE dnames_var IS VARRAY(7) OF VARCHAR2(30);
/
CREATE TABLE depts (region VARCHAR2(25), dept_names dnames_var);
BEGIN
INSERT INTO depts VALUES('Europe', dnames_var('Shipping','Sales','Finance'));
INSERT INTO depts VALUES('Americas', dnames_var('Sales','Finance','Shipping'));
INSERT INTO depts
VALUES('Asia', dnames_var('Finance','Payroll','Shipping','Sales'));
COMMIT;
END;
/
DECLARE
new_dnames dnames_var := dnames_var('Benefits', 'Advertising', 'Contracting',
12-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
オブジェクトでの動的 SQL の使用
'Executive', 'Marketing');
some_dnames dnames_var;
BEGIN
UPDATE depts SET dept_names = new_dnames WHERE region = 'Europe';
COMMIT;
SELECT dept_names INTO some_dnames FROM depts WHERE region = 'Europe';
FOR i IN some_dnames.FIRST .. some_dnames.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('dept_names = ' || some_dnames(i));
END LOOP;
END;
/
例 12-17 では、PL/SQL BULK COLLECT は、オブジェクト型が含まれるマルチレベル・コレク
ションで使用されています。
例 12-17 ネストした表での BULK COLLECT の使用
CREATE TYPE dnames_var IS VARRAY(7) OF VARCHAR2(30);
/
CREATE TABLE depts (region VARCHAR2(25), dept_names dnames_var);
BEGIN
INSERT INTO depts VALUES('Europe', dnames_var('Shipping','Sales','Finance'));
INSERT INTO depts VALUES('Americas', dnames_var('Sales','Finance','Shipping'));
INSERT INTO depts
VALUES('Asia', dnames_var('Finance','Payroll','Shipping','Sales'));
COMMIT;
END;
/
DECLARE
TYPE dnames_tab IS TABLE OF dnames_var;
v_depts dnames_tab;
BEGIN
SELECT dept_names BULK COLLECT INTO v_depts FROM depts;
DBMS_OUTPUT.PUT_LINE(v_depts.COUNT); -- prints 3
END;
/
オブジェクトでの動的 SQL の使用
例 12-18 は、動的 SQL でのオブジェクトとコレクションの使用方法を示しています。まず、オ
ブジェクト型 person_typ および VARRAY 型の hobbies_var を定義してから、これらの型
を使用するパッケージを作成します。
例 12-18 オブジェクト型とコレクションの動的 SQL を使用した TEAMS パッケージ
CREATE TYPE person_typ AS OBJECT (name VARCHAR2(25), age NUMBER);
/
CREATE TYPE hobbies_var AS VARRAY(10) OF VARCHAR2(25);
/
CREATE OR REPLACE PACKAGE teams
AUTHID CURRENT_USER AS
PROCEDURE create_table (tab_name VARCHAR2);
PROCEDURE insert_row (tab_name VARCHAR2, p person_typ, h hobbies_var);
PROCEDURE print_table (tab_name VARCHAR2);
END;
/
CREATE OR REPLACE PACKAGE BODY teams AS
PROCEDURE create_table (tab_name VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE ' || tab_name ||
PL/SQL のオブジェクト型の使用
12-11
オブジェクトでの動的 SQL の使用
' (pers person_typ, hobbs hobbies_var)';
END;
PROCEDURE insert_row (
tab_name VARCHAR2,
p person_typ,
h hobbies_var) IS
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO ' || tab_name ||
' VALUES (:1, :2)' USING p, h;
END;
PROCEDURE print_table (tab_name VARCHAR2) IS
TYPE refcurtyp IS REF CURSOR;
v_cur refcurtyp;
p
person_typ;
h
hobbies_var;
BEGIN
OPEN v_cur FOR 'SELECT pers, hobbs FROM ' || tab_name;
LOOP
FETCH v_cur INTO p, h;
EXIT WHEN v_cur%NOTFOUND;
-- print attributes of 'p' and elements of 'h'
DBMS_OUTPUT.PUT_LINE('Name: ' || p.name || ' - Age: ' || p.age);
FOR i IN h.FIRST..h.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('Hobby(' || i || '): ' || h(i));
END LOOP;
END LOOP;
CLOSE v_cur;
END;
END;
/
無名 PL/SQL ブロックから、パッケージ teams のプロシージャをコールできます。
例 12-19 TEAMS パッケージからのプロシージャのコール
DECLARE
team_name VARCHAR2(15);
BEGIN
team_name := 'Notables';
TEAMS.create_table(team_name);
TEAMS.insert_row(team_name, person_typ('John', 31),
hobbies_var('skiing', 'coin collecting', 'tennis'));
TEAMS.insert_row(team_name, person_typ('Mary', 28),
hobbies_var('golf', 'quilting', 'rock climbing', 'fencing'));
TEAMS.print_table(team_name);
END;
/
12-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
13
PL/SQL の言語要素
この章は、PL/SQL 構文および方法のクイック・リファレンス・ガイドです。コマンド、パラ
メータおよびその他の言語要素を組み合せて PL/SQL 文を作成する方法を示します。また、使
用上の注意および例へのリンクも示します。
PL/SQL 文の構文は、構文図を左から右、上から下の順に読んでください。この図は、バッカ
ス正規形(BNF)の結果を表しています。この図では、四角形の中はキーボード、円の中はデ
リミタ、楕円の中は識別子です。各図は、構文の要素を定義しています。図を通るパスは、そ
れぞれがその要素のフォームとして考えられるものを表しています。矢印の向きに進んでくだ
さい。線がループ状になっている場合は、そのループ内の要素を繰り返すことができます。
この章の項目は、次のとおりです。
■
代入文
■
AUTONOMOUS_TRANSACTION プラグマ
■
ブロック宣言
■
CASE 文
■
CLOSE 文
■
コレクション定義
■
コレクション・メソッド
■
コメント
■
COMMIT 文
■
定数と変数の宣言
■
カーソル属性
■
カーソル変数
■
カーソル宣言
■
DELETE 文
■
EXCEPTION_INIT プラグマ
■
例外定義
■
EXECUTE IMMEDIATE 文
■
EXIT 文
■
式定義
■
FETCH 文
■
FORALL 文
■
ファンクション宣言
■
GOTO 文
PL/SQL の言語要素
13-1
13-2
■
IF 文
■
INSERT 文
■
リテラル宣言
■
LOCK TABLE 文
■
LOOP 文
■
MERGE 文
■
NULL 文
■
オブジェクト型宣言
■
OPEN 文
■
OPEN-FOR 文
■
パッケージ宣言
■
プロシージャ宣言
■
RAISE 文
■
レコード定義
■
RESTRICT_REFERENCES プラグマ
■
RETURN 文
■
RETURNING INTO 句
■
ROLLBACK 文
■
%ROWTYPE 属性
■
SAVEPOINT 文
■
SELECT INTO 文
■
SERIALLY_REUSABLE プラグマ
■
SET TRANSACTION 文
■
SQL カーソル
■
SQLCODE ファンクション
■
SQLERRM ファンクション
■
%TYPE 属性
■
UPDATE 文
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
代入文
代入文
代入文は、変数、フィールド、パラメータまたは要素の現在の値を設定します。代入文は、代
入のターゲットと、それに続く代入演算子および式で構成されています。代入文を実行すると、
式が評価され、結果の値がターゲットに格納されます。詳細は、2-18 ページの「変数への値の
代入」を参照してください。
構文
assignment statement ::=
(
index
)
collection_name
cursor_variable_name
:
host_cursor_variable_name
:
host_variable_name
:
indicator_name
.
attribute_name
.
field_name
:=
expression
;
object_name
parameter_name
record_name
variable_name
キーワードとパラメータの説明
attribute_name
オブジェクト型の属性を指定します。名前はそのオブジェクト型の中で一意である必要があり
ます(他のオブジェクト型内では使用できます)
。属性の宣言内では、代入演算子または
DEFAULT 句を使用しての属性の初期化はできません。また、属性に NOT NULL 制約を課すこと
はできません。
collection_name
現行の有効範囲のうち、これより前の部分で宣言されているネストした表、索引付き表または
VARRAY を指定します。
cursor_variable_name
現行の有効範囲の中で事前に宣言されている PL/SQL カーソル変数を識別します。カーソル変
数に代入できるのは、別のカーソル変数の値のみです。
expression
変数、定数、リテラル、演算子、ファンクション・コールの組合せです。最も単純な式は、1
個の変数で構成されています。expression の構文は、13-44 ページの「式定義」を参照して
ください。代入文を実行すると、式が評価され、結果の値が代入のターゲットに格納されます。
値とターゲットのデータ型には互換性が必要です。
field_name
ユーザー定義のレコードまたは %ROWTYPE レコード内のフィールドを指定します。
PL/SQL の言語要素
13-3
代入文
host_cursor_variable_name
PL/SQL ホスト環境で宣言され、バインド変数として PL/SQL に渡されるカーソル変数を識別
します。ホスト・カーソル変数のデータ型は、PL/SQL カーソル変数の戻り型と互換性があり
ます。ホスト変数には、接頭辞としてコロンを付けてください。
host_variable_name
PL/SQL ホスト環境で宣言され、バインド変数として PL/SQL に渡される変数を識別します。
ホスト変数には、接頭辞としてコロンを付けてください。
index
戻される値が PLS_INTEGER 型の値、BINARY_INTEGER 型の値、またはそのデータ型に暗黙
的に変換可能な値になる数値式です。
indicator_name
PL/SQL ホスト環境で宣言され、PL/SQL に渡される標識変数を識別します。標識変数には、
接頭辞としてコロンを付ける必要があります。標識変数は、関連付けられたホスト変数の値ま
たは条件を示します。たとえば、Oracle プリコンパイラ環境では、標識変数を使用して出力ホ
スト変数内の NULL や切り捨てられた値を検出できます。
object_name
現行の有効範囲のうち、これより前の部分で宣言されているオブジェクト型のインスタンスを
識別します。
parameter_name
代入文が使用されているサブプログラムの仮パラメータ OUT または IN OUT を識別します。
record_name
現行の有効範囲のうち、これより前に宣言されているユーザー定義のレコードまたは
%ROWTYPE レコードを識別します。
variable_name
現行の有効範囲の中で事前に宣言されている PL/SQL 変数を識別します。
使用上の注意
デフォルトでは、宣言で初期化されていない変数は、ブロックまたはサブプログラムに入るた
びに NULL に初期化されます。変数を式の中で使用する前に、その変数に値を代入する必要が
あります。
NOT NULL と定義されている変数には NULL を代入できません。NULL を代入しようとすると、
PL/SQL は事前定義の例外 VALUE_ERROR を呼び出します。ブール変数に代入できるのは、値
TRUE、FALSE および NULL のみです。比較またはその他のテスト結果をブール変数に代入でき
ます。
式の値をレコード内の特定のフィールドに代入できます。レコード内のすべてのフィールドに
一度に値を代入できます。PL/SQL では、レコードの宣言で同じカーソルまたは表が参照され
ている場合は、レコード全体の間での集計代入ができます。1-6 ページの例 1-2「代入演算子を
使用した変数への値の代入」に、レコード内のすべてのフィールドの値を別のレコードにコ
ピーする方法を示します。
コレクション名に添字を付けると、式の値をコレクションの特定の要素に代入できます。
13-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
代入文
例
例 13-1 に、値を宣言し、値を変数に代入する様々な方法を示します。
例 13-1 宣言および変数への値の代入
DECLARE
wages
NUMBER;
hours_worked NUMBER := 40;
hourly_salary CONSTANT NUMBER := 17.50; -- constant value does not change
country
VARCHAR2(64) := 'UNKNOWN';
unknown
BOOLEAN;
TYPE comm_tab IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
commissions
comm_tab;
TYPE jobs_var IS VARRAY(10) OF employees.job_id%TYPE;
jobids
jobs_var;
CURSOR c1 IS SELECT department_id FROM departments; -- cursor declaration
deptid
departments.department_id%TYPE;
emp_rec
employees%ROWTYPE; -- do not need TYPE declaration in this case
BEGIN
/* the following are examples of assignment statements */
wages := hours_worked * hourly_salary; -- compute wages
country := UPPER('italy');
unknown := (country = 'UNKNOWN');
commissions(5) := 20000 * 0.15; commissions(8) := 20000 * 0.18;
jobids := jobs_var('ST_CLERK'); jobids.EXTEND(1); jobids(2) := 'SH_CLERK';
OPEN c1; FETCH c1 INTO deptid; CLOSE c1;
emp_rec.department_id := deptid; emp_rec.job_id := jobids(2);
END;
/
次の例を参照してください。
例 1-2「代入演算子を使用した変数への値の代入」
(1-6 ページ)
例 1-3「SELECT INTO を使用した変数への値の代入」
(1-6 ページ)
例 1-4「サブプログラムのパラメータとしての変数への値の代入」
(1-7 ページ)
例 2-10「%ROWTYPE 宣言を使用したレコードへの値の代入」(2-12 ページ)
関連項目
「変数への値の代入」(2-18 ページ)
「定数と変数の宣言」(13-24 ページ)
「式定義」(13-44 ページ)
「SELECT INTO 文」(13-105 ページ)
PL/SQL の言語要素
13-5
AUTONOMOUS_TRANSACTION プラグマ
AUTONOMOUS_TRANSACTION プラグマ
AUTONOMOUS_TRANSACTION プラグマは、トランザクション内のサブプログラムの動作方法を
変更します。このプラグマでマークされたサブプログラムは、メイン・トランザクションで
データをコミットまたはロールバックすることなく、実行した SQL 操作をコミットまたはロー
ルバックできます。詳細は、6-35 ページの「自律型トランザクションによる独立した作業単位
の実行」を参照してください。
構文
pragma autonomous_transaction ::=
PRAGMA
AUTONOMOUS_TRANSACTION
;
キーワードとパラメータの説明
PRAGMA
文がプラグマ(コンパイラ・ディレクティブ)であることを表します。プラグマは、実行時で
はなくコンパイル時に処理されます。プラグマは、コンパイラに情報を渡します。
使用上の注意
このプラグマは次のものに適用できます。
■
トップレベル(ネストしていない)の無名 PL/SQL ブロック
■
ローカル、スタンドアロンおよびパッケージのファンクションとプロシージャ
■
SQL オブジェクト型のメソッド
■
データベース・トリガー
このプラグマは、パッケージ全体またはオブジェクト型全体には適用できません。かわりに、
各パッケージ・サブプログラムまたはオブジェクト・メソッドに適用できます。
プラグマは、宣言部の任意の場所でコーディングできます。見やすくするために、セクション
の先頭にプラグマをコーディングしてください。
自律型トランザクションは、開始すると完全に独立します。ロック、リソースまたはコミット
依存関係をメイン・トランザクションと共有することはありません。メイン・トランザクショ
ンがロールバックする場合でも、イベントや増分再試行カウンタなどのログを取ることができ
ます。
通常のトリガーとは異なり、自律型トリガーには、COMMIT、ROLLBACK などのトランザクショ
ン制御文を含めることができます。また、EXECUTE IMMEDIATE 文を使用して DDL 文
(CREATE、DROP など)を発行できます。
自律型トランザクションによって行われた変更は、自律型トランザクションがコミットすると、
他のトランザクションから参照できるようになります。変更は、メイン・トランザクションが
再開するとメイン・トランザクションからも参照できるようになりますが、これは分離レベル
が READ COMMITTED(デフォルト)に設定されている場合のみです。メイン・トランザクショ
ンの分離レベルを SERIALIZABLE に設定すると、その自律型トランザクションによって行わ
れた変更は、メイン・トランザクションが再開してもメイン・トランザクションからは参照で
きません。
メイン・トランザクション内で、自律型サブプログラムをコールする前にマークされたセーブ
ポイントまでロールバックしても、自律型トランザクションはロールバックされません。自律
型トランザクションは、メイン・トランザクションからは完全に独立していることに注意して
ください。
13-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
AUTONOMOUS_TRANSACTION プラグマ
メイン・トランザクション(自律型ルーチンの終了まで再開できない)が保持するリソースに、
自律型トランザクションがアクセスしようとすると、デッドロックが発生します。この場合、
Oracle は自律型トランザクションで例外を呼び出します。例外が未処理になった場合、自律型
トランザクションはロールバックされます。
コミットまたはロールバックせずにアクティブな自律型トランザクションを終了しようとする
と、Oracle は例外を呼び出します。例外が未処理になった場合、またはその他の未処理例外が
発生してトランザクションが終了した場合、トランザクションはロールバックされます。
例
次の例を参照してください。
例 6-43「パッケージでの自律型ファンクションの宣言」(6-36 ページ)
例 6-44「自立型スタンドアロン・プロシージャの宣言」(6-36 ページ)
例 6-45「自律型 PL/SQL ブロックの宣言」
(6-37 ページ)
例 6-46「自律型トリガーの宣言」(6-37 ページ)
関連項目
「EXCEPTION_INIT プラグマ」
(13-37 ページ)
「RESTRICT_REFERENCES プラグマ」(13-96 ページ)
「SERIALLY_REUSABLE プラグマ」
(13-109 ページ)
PL/SQL の言語要素
13-7
ブロック宣言
ブロック宣言
PL/SQL におけるプログラムの基本単位はブロックです。PL/SQL ブロックは、キーワード
DECLARE、BEGIN、EXCEPTION および END で定義します。これらのキーワードは、ブロック
を宣言部、実行部、例外処理部に分けます。このうち必ず存在する必要があるのは実行部のみ
です。ブロックの中では、実行可能文を置ける場所ならば別のブロックをネストできます。詳
細は、1-5 ページの「PL/SQL ブロック構造」および 2-15 ページの「PL/SQL の識別子の有効
範囲と可視性」を参照してください。
構文
plsql block ::=
<<
BEGIN
label_name
>>
DECLARE
type_definition
function_declaration
item_definition
procedure_declaration
statement
EXCEPTION
exception_handler
label_name
END
;
type definition ::=
record_type_definition
ref_cursor_type_definition
table_type_definition
subtype_definition
varray_type_definition
subtype definition ::=
(
SUBTYPE
13-8
subtype_name
IS
base_type
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
constraint
)
NOT
NULL
ブロック宣言
item definition ::=
collection_declaration
constant_declaration
cursor_declaration
cursor_variable_declaration
exception_declaration
object_declaration
object_ref_declaration
record_declaration
variable_declaration
sql_statement ::=
commit_statement
delete_statement
insert_statement
lock_table_statement
rollback_statement
savepoint_statement
select_statement
set_transaction_statement
update_statement
PL/SQL の言語要素
13-9
ブロック宣言
statement ::=
assignment_statement
close_statement
execute_immediate_statement
exit_statement
fetch_statement
forall_statement
goto_statement
<<
label_name
>>
if_statement
loop_statement
null_statement
open_statement
open_for_statement
plsql_block
raise_statement
return_statement
sql_statement
キーワードとパラメータの説明
base_type
任意のスカラーまたは CHAR、DATE、RECORD などのユーザー定義の PL/SQL データ型指定子
です。
BEGIN
PL/SQL ブロックの実行部の開始を示すキーワードです。実行部には実行可能文が置かれます。
PL/SQL ブロックには 1 つ以上の実行可能文(NULL 文でも可)が含まれている必要がありま
す。1-5 ページの「PL/SQL ブロック構造」を参照してください。
collection_declaration
コレクションを宣言します(索引付き表、ネストした表または VARRAY)
。
collection_declaration の構文は、13-16 ページの「コレクション定義」を参照してくだ
さい。
constant_declaration
定数を宣言します。constant_declaration の構文は、13-24 ページの「定数と変数の宣言」
を参照してください。
constraint
CHAR や NUMBER などの制約できるデータ型にのみ適用されます。文字データ型の場合は、最
大サイズのバイト数を指定します。数値データ型の場合は、精度と位取りの最大値を指定しま
す。
13-10
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
ブロック宣言
cursor_declaration
明示カーソルを宣言します。cursor_declaration の構文は、13-32 ページの「カーソル宣
言」を参照してください。
cursor_variable_declaration
カーソル変数を宣言します。cursor_variable_declaration の構文は、13-29 ページの
「カーソル変数」を参照してください。
DECLARE
PL/SQL ブロックの宣言部の開始を示すキーワードです。宣言部にはローカル宣言が置かれま
す。ローカルに宣言された項目は現行のブロックとそのすべてのサブブロックにのみ存在し、
外側のブロックからは見えません。PL/SQL ブロックの宣言部はオプションです。宣言部は、
ブロックの実行部の開始を示すキーワード BEGIN によって暗黙的に終了します。詳細は、2-9
ページの「宣言」を参照してください。
PL/SQL では前方参照ができません。他の文で項目を参照するときは、事前に宣言しておく必
要があります。ただし、サブプログラムは、その他すべてのプログラム項目の後の宣言部の末
尾で宣言してください。
END
PL/SQL ブロックの終わりを示すキーワードです。これはブロック中の最後のキーワードにす
る必要があります。END はトランザクションの終わりを通知しないことに注意してください。
ブロックが複数のトランザクションにまたがることができるように、トランザクションも複数
のブロックにまたがることができます。1-5 ページの「PL/SQL ブロック構造」を参照してくだ
さい。
EXCEPTION
PL/SQL ブロックの例外処理部の開始を示すキーワードです。例外が呼び出されると、ブロッ
クの通常の実行が停止され、制御が適切な例外ハンドラに移ります。例外ハンドラが終了する
と、ブロック直後の文から実行が再開されます。1-5 ページの「PL/SQL ブロック構造」を参照
してください。
呼び出された例外の例外ハンドラが現行のブロックに存在しないと、制御は外側のブロックに
渡されます。この過程が、例外ハンドラが見つかるまで、または外側にブロックがなくなるま
で繰り返されます。PL/SQL が、例外を処理するための例外ハンドラを見つけられない場合、
実行は停止され、
「未処理例外」エラーがホスト環境に戻されます。例外の詳細は、第 10 章を
参照してください。
exception_declaration
例外を宣言します。exception_declaration の構文は、13-38 ページの「例外定義」を参照
してください。
exception_handler
例外ハンドラです。例外が呼び出されると、その例外に関連付けられた一連の文を実行します。
exception_handler の構文は、13-38 ページの「例外定義」を参照してください。
function_declaration
ファンクションを宣言します。function_declaration の構文は、13-58 ページの「ファン
クション宣言」を参照してください。
label_name
PL/SQL ブロックまたは文に任意のラベルを付ける未宣言の識別子です。使用する場合は、
label_name を二重の山カッコで囲み、ラベルを付けるブロックまたは文の先頭に置く必要が
あります。必要に応じて、ブロックのラベル付けに使用する場合は、label_name を山カッコ
で囲まずにブロックの末尾に置くこともできます。1 つのブロックまたは文に複数のラベルを
使用できますが、ラベルは、各ブロックまたは文に対して一意である必要があります。
PL/SQL の言語要素
13-11
ブロック宣言
外側のブロックで宣言されたグローバル識別子を、サブブロックで再宣言できます。この場合、
ローカルでの宣言が優先され、ブロック・ラベルを使用して参照を修飾しなければ、サブブ
ロックではグローバル識別子を参照できなくなります。2-17 ページの例 2-19「複数の重複した
ラベルを使用する PL/SQL ブロック」を参照してください。
object_declaration
オブジェクト型のインスタンスを宣言します。object_declaration の構文は、13-77 ページ
の「オブジェクト型宣言」を参照してください。
procedure_declaration
プロシージャを宣言します。procedure_declaration の構文は、13-89 ページの「プロシー
ジャ宣言」を参照してください。
record_declaration
ユーザー定義のレコードを宣言します。record_declaration の構文は、13-93 ページの「レ
コード定義」を参照してください。
statement
実行可能文です(宣言文ではない)
。一連の文の中には、RAISE などのプロシージャ文、
UPDATE などの SQL 文および PL/SQL ブロックを含めることができます。PL/SQL 文は自由形
式です。つまり、PL/SQL 文は、キーワード、デリミタ、リテラルが複数の行にまたがらない
かぎり、何行でも続けることができます。文の終わりは、セミコロン(;)です。
subtype_name
任意のスカラーまたは CHAR、DATE、RECORD などのユーザー定義の PL/SQL データ型指定子
を使用して定義したユーザー定義のサブタイプを識別します。
variable_declaration
変数を宣言します。variable_declaration の構文は、13-24 ページの「定数と変数の宣言」
を参照してください。
PL/SQL は、データ操作、カーソル制御およびトランザクション制御文を含む SQL 文のサブ
セットをサポートしています。ただし、ALTER、CREATE、GRANT、REVOKE などのデータ定義
およびデータ制御文はサポートしていません。
例
次の例を参照してください。
例 1-4「サブプログラムのパラメータとしての変数への値の代入」
(1-7 ページ)
例 2-19「複数の重複したラベルを使用する PL/SQL ブロック」
(2-17 ページ)
例 13-1「宣言および変数への値の代入」(13-5 ページ)
関連項目
「定数と変数の宣言」(13-24 ページ)
「例外定義」(13-38 ページ)
「ファンクション宣言」(13-58 ページ)
「プロシージャ宣言」(13-89 ページ)
13-12
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
CASE 文
CASE 文
CASE 文を使用すると、一連の条件を基に、対応する文を選択して実行できます。CASE 文は、
単一の式を評価していくつかの可能性のある値と比較するか、または複数のブール式を評価し
て最初に TRUE となった式を選択します。
構文
searched case statement ::=
label_name
CASE
WHEN
ELSE
boolean_expression
statement
THEN
statement
;
;
label_name
END
CASE
;
simple case statement ::=
label_name
CASE
case_operand
WHEN
when_operand
ELSE
statement
THEN
statement
;
;
label_name
END
CASE
;
キーワードとパラメータの説明
単純な CASE 文の場合、CASE オペランドと WHEN オペランドの値は、BLOB、BFILE、オブ
ジェクト型、PL/SQL レコード、索引付き表、VARRAY またはネストした表以外であれば、任
意の PL/SQL データ型にできます。
ELSE 句を省略すると、デフォルトのアクションが代用されます。CASE 文の場合、条件が一致
しなければ、デフォルトで CASE_NOT_FOUND 例外が呼び出されます。CASE 式の場合は、デ
フォルトで NULL が戻されます。
PL/SQL の言語要素
13-13
CASE 文
使用上の注意
WHEN 句は順番に実行されます。各 WHEN 句はそれぞれ 1 度のみ実行されます。一致する WHEN
句が 1 つでも見つかると、後続の WHEN 句は実行されません。WHEN 句の後に複数の文を使用で
きます。また、WHEN 句の式にはリテラル、変数、ファンクション・コールまたはその他の任意
の式を使用できます。WHEN 句では、すべての条件に同じ変数をテストしたり同じ演算子を使用
するのではなく、それぞれ異なる条件を使用できます。
WHEN 句の文でデータベースを変更し、非決定的なファンクションをコールできます。C 言語の
switch 文のような fall-through のメカニズムはありません。WHEN 句が一致し、その文が実行
されると、CASE 文は終了します。
CASE 文は、オプションごとにアクションが異なる場合に適しています。複数の値から値を選択
して変数に代入するのみの場合、かわりに CASE 式を使用して代入文を記述できます。
たとえば、DECODE ファンクション、またはある値を別の値に変換する他のファンクションを
コールするかわりに、SQL 問合せ内に CASE 式を含めることができます。
例
例 13-2 に、単純な CASE 文の使用を示します。
例 13-2 CASE 文の使用
DECLARE
jobid
employees.job_id%TYPE;
empid
employees.employee_id%TYPE := 115;
sal_raise NUMBER(3,2);
BEGIN
SELECT job_id INTO jobid from employees WHERE employee_id = empid;
CASE
WHEN jobid = 'PU_CLERK' THEN sal_raise := .09;
WHEN jobid = 'SH_CLERK' THEN sal_raise := .08;
WHEN jobid = 'ST_CLERK' THEN sal_raise := .07;
ELSE sal_raise := 0;
END CASE;
END;
/
次の例を参照してください。
例 1-7「IF-THEN_ELSE 文および CASE 文を使用した条件制御」(1-10 ページ)
例 4-6「CASE-WHEN 文の使用」
(4-4 ページ)
例 4-7「検索 CASE 文の使用」
(4-5 ページ)
関連項目
「条件テスト : IF 文および CASE 文」(4-2 ページ)
「CASE 式」
(2-25 ページ)
「CASE 文の使用」
(4-4 ページ)
『Oracle Database SQL リファレンス』の「NULLIF ファンクション」および「COALESCE ファ
ンクション」
13-14
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
CLOSE 文
CLOSE 文
CLOSE 文は、カーソルまたはカーソル変数からのフェッチが終了し、カーソルが占有していた
リソースを再利用できるようになったことを示します。
構文
close ::=
cursor_name
CLOSE
cursor_variable_name
:
;
host_cursor_variable_name
キーワードとパラメータの説明
cursor_name、
、cursor_variable_name、
、host_cursor_variable_name
カーソルをクローズする際、現行の有効範囲の中で事前に宣言され、現在オープンされている
明示カーソルまたは PL/SQL カーソル変数を指定できます。
また、PL/SQL ホスト環境で宣言され、バインド変数として PL/SQL に渡されるカーソル変数
も指定できます。ホスト・カーソル変数のデータ型は、PL/SQL カーソル変数の戻り型と互換
性があります。ホスト変数には、接頭辞としてコロンを付けてください。
使用上の注意
一度クローズしたカーソルまたはカーソル変数を再オープンする場合は、それぞれ OPEN 文ま
たは OPEN-FOR 文を使用します。カーソルは再オープンする前に、一度クローズする必要があ
ります。そうしないと、PL/SQL によって事前定義の例外 CURSOR_ALREADY_OPEN が呼び出
されます。カーソル変数を再オープンする場合は、その前にクローズする必要はありません。
すでにクローズされているか一度もオープンされたことのないカーソルまたはカーソル変数を
クローズしようとすると、PL/SQL によって事前定義の例外 INVALID_CURSOR が呼び出され
ます。
例
次の例を参照してください。
例 4-17「LOOP での EXIT の使用」
(4-12 ページ)
例 6-10「カーソルを使用したフェッチ」(6-9 ページ)
例 6-13「カーソルを使用したバルク・データのフェッチ」(6-11 ページ)
例 13-1「宣言および変数への値の代入」(13-5 ページ)
関連項目
「カーソルのクローズ」(6-11 ページ)
「FETCH 文」
(13-52 ページ)
「OPEN 文」(13-79 ページ)
「OPEN-FOR 文」
(13-81 ページ)
「PL/SQL を使用したデータの問合せ」
(6-14 ページ)
PL/SQL の言語要素
13-15
コレクション定義
コレクション定義
コレクションは、すべて同じ型の要素の順序付きグループです。たとえば、あるクラスの生徒
の成績です。各要素には一意の添字が付いています。その番号によって、集合の中での要素の
位置が決まります。PL/SQL には、結合配列、ネストした表および VARRAY(可変サイズの配
列)の、3 種類のコレクションがあります。ネストした表は、結合配列(以前の「PL/SQL 表」
または「索引付き表」
)の機能を拡張します。
コレクションは、ほとんどの第 3 世代のプログラミング言語で見られる配列と同様の働きをし
ます。コレクションにあるのは、1 次元のみです。ほとんどのコレクションは整数で索引付け
されますが、結合配列では文字列も使用できます。マルチディメンション配列のモデルを作成
する場合には、項目として他のコレクションを持つコレクションを宣言できます。
ネストした表や VARRAY にオブジェクト型のインスタンスを格納したり、また、逆にネストし
た表や VARRAY がオブジェクト型の属性であったりします。コレクションは、パラメータとし
て渡すこともできます。それらを使用して、データの列をデータベースの表に出し入れしたり、
クライアント側アプリケーションとストアド・サブプログラムとの間でデータの列を移動でき
ます。
詳細は、5-6 ページの「コレクション型の定義とコレクション変数の宣言」を参照してくださ
い。
注意 : CREATE TYPE 文を使用して作成されたスキーマ・レベルのコレク
ション型の構文は、PL/SQL コレクション型の構文とは異なります。SQL
の CREATE TYPE 文の詳細は、『Oracle Database SQL リファレンス』を参
照してください。SQL の CREATE TYPE BODY 文の詳細は、
『Oracle
Database SQL リファレンス』を参照してください。
構文
table type definition ::=
TYPE
type_name
IS
TABLE
OF
NOT
NULL
size_limit
)
element_type
PLS_INTEGER
INDEX
BY
BINARY_INTEGER
VARCHAR2
(
v_size
)
;
varray type definition ::=
VARRAY
TYPE
type_name
IS
(
VARRYING
NOT
OF
ARRAY
NULL
element_type
;
collection type definition ::=
collection_name
13-16
type_name
;
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクション定義
element type definition ::=
cursor_name
%
ROWTYPE
%
ROWTYPE
.
column_name
db_table_name
object_name
%
%
TYPE
%
TYPE
TYPE
REF
object_type_name
.
field_name
record_name
record_type_name
scalar_datatype_name
variable_name
%
TYPE
キーワードとパラメータの説明
element_type
PL/SQL コレクション要素の型を指定します。REF CURSOR を除く任意の PL/SQL データ型を
使用できます。
INDEX BY type_name
オプションです。結合配列を定義します。システムで添字値を順に定義するのではなく、ユー
ザーが使用する添字値を指定します。
type_name は、BINARY_INTEGER、PLS_INTEGER または VARCHAR2 あるいは VARCHAR2 サ
ブタイプ VARCHAR、STRING または LONG にすることができます。v_size は、VARCHAR2
キーの長さを指定します。
size_limit
正の整数のリテラルであり、VARRAY の最大サイズ、つまり VARRAY に格納できる要素数の
最大値を指定します。最大値には制限があります。5-11 ページの「コレクション要素の参照」
を参照してください。
type_name
データ型指定子 TABLE または VARRAY を使用して定義されたユーザー定義のコレクション型を
識別します。
使用上の注意
ネストした表は、結合配列(以前の索引付き表)の機能を拡張したものであるため、いくつか
の点で異なります。5-5 ページの「ネストした表と結合配列の選択」を参照してください。
すべての要素参照には、コレクション名およびカッコで囲まれた 1 つ以上の添字が含まれてお
り、この添字によって、処理される要素が決まります。負の添字を持つことができる結合配列
を除き、コレクションの添字の下限は 1(固定)です。マルチレベル・コレクションの添字は、
任意の順序で評価されます。添字に、別の添字の値を変更する式が含まれている場合の結果は、
未定義になります。5-11 ページの「コレクション要素の参照」を参照してください。
3 つのすべてのコレクション型は、任意の PL/SQL ブロック、サブプログラムまたはパッケー
ジの宣言部で定義できます。ただし、ネストした表と VARRAY 型のみを Oracle データベース
内に作成して格納できます。
PL/SQL の言語要素
13-17
コレクション定義
結合配列とネストした表は疎である(添字が連続していない)場合があります。ただし、
VARRAY は常に密です(添字が連続しています)
。ネストした表とは異なり、VARRAY はデー
タベースに格納されるときにその順序と添字が保たれます。最初、結合配列は疎です。そのた
め、たとえば、主キー(口座番号や従業員番号など)を索引として使用して、参照データを一
時変数に格納できます。
コレクションは、通常の有効範囲とインスタンス化の規則に従います。パッケージの中では、
そのパッケージが初めて参照された時点でコレクションのインスタンスが生成され、データ
ベース・セッションが終わった時点で消滅します。ブロックまたはサブプログラムの中で、
ローカル・コレクションは、ブロックまたはサブプログラムに入ったときにインスタンス化さ
れ、ブロックまたはサブプログラムが終了した時点で消滅します。
ネストした表または VARRAY は、初期化するまでは基本構造的に NULL(つまりコレクション
の要素ではなく、コレクション自体が NULL)です。ネストした表または VARRAY を初期化す
るには、コンストラクタ(コレクション型と同じ名前のシステム定義ファンクション)を使用
します。このファンクションは、コレクションに渡される要素から、コレクションを構成(作
成)します。
可能なコレクションの比較の詳細は、5-15 ページの「コレクションの比較」を参照してくださ
い。
コレクションにオブジェクト型のインスタンスを格納したり、また、逆にコレクションがオブ
ジェクト型の属性であったりします。コレクションは、パラメータとして渡すこともできます。
それらを使用して、データの列をデータベースの表に出し入れしたり、クライアント側アプリ
ケーションとストアド・サブプログラムとの間でデータの列を移動できます。
コレクションを戻すファンクションをコールする場合、次の構文を使用してコレクション内の
要素を参照します。
function_name(parameter_list)(subscript)
5-11 ページの例 5-16「結合配列の要素の参照」および B-2 ページの例 B-2「ドット表記法を使
用した名前の修飾」を参照してください。
Oracle Call Interface(OCI)または Oracle プリコンパイラを使用すると、サブプログラムの仮
パラメータとして宣言された結合配列(索引付き表)にホスト配列をバインドできます。これ
によって、ホスト配列をストアド・ファンクションやプロシージャに渡すことができます。
例
次の例を参照してください。
例 5-1「コレクション型の宣言」
(5-3 ページ)
例 5-3「ネストした表、VARRAY および結合配列の宣言」(5-7 ページ)
例 5-4「%TYPE を使用したコレクションの宣言」(5-7 ページ)
例 5-5「ネストした表としてのプロシージャのパラメータの宣言」
(5-8 ページ)
例 5-42「レコード型の宣言および初期化」(5-28 ページ)
例 13-1「宣言および変数への値の代入」(13-5 ページ)
関連項目
「コレクション・メソッド」(13-19 ページ)
「オブジェクト型宣言」(13-77 ページ)
「レコード定義」(13-93 ページ)
13-18
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクション・メソッド
コレクション・メソッド
コレクション・メソッドとは、コレクションに対する操作を実行するための、ドット表記法を
使用してコールされる組込みファンクションまたはプロシージャです。メソッド EXISTS、
COUNT、LIMIT、FIRST、LAST、PRIOR、NEXT、EXTEND、TRIM および DELETE を使用して、
サイズが不明または多様なコレクションを管理できます。
EXISTS、COUNT、LIMIT、FIRST、LAST、PRIOR および NEXT は、コレクションのプロパ
ティまたは個のコレクション要素をチェックするファンクションです。EXTEND、TRIM および
DELETE は、コレクションを変更するプロシージャです。
EXISTS、PRIOR、NEXT、TRIM、EXTEND および DELETE は整数パラメータを取ります。文字
列キーを持つ結合配列の場合、EXISTS、PRIOR、NEXT および DELETE は、VARCHAR2 パラ
メータも取ります。EXTEND と TRIM は、索引付き表では使用できません。
詳細は、5-18 ページの「コレクション・メソッドの使用」を参照してください。
構文
collection call method ::=
COUNT
,
(
index
index
)
DELETE
EXISTS
(
index
)
,
collection_name
.
(
number
index
)
index
)
EXTEND
FIRST
LAST
LIMIT
NEXT
PRIOR
(
(
index
(
)
number
)
TRIM
キーワードとパラメータの説明
collection_name
現行の有効範囲のうち、これより前の部分で宣言されている結合配列、ネストした表または
VARRAY を指定します。
COUNT
コレクションに現在含まれている要素の数を戻します。コレクションの現行のサイズが不明な
場合があるため、そのようなときに役立ちます。COUNT は、整数式が使用できる位置ならどこ
でも使用できます。VARRAY の場合、COUNT は常に LAST と同じです。ネストした表の場合、
COUNT は通常、LAST と同じです。ただし、ネストした表の途中から要素を削除すると、
COUNT は LAST より小さくなります。
PL/SQL の言語要素
13-19
コレクション・メソッド
DELETE
このプロシージャには 3 つの形式があります。DELETE は、コレクションからすべての要素を
削除します。DELETE(n) は、n 番目の要素を結合配列またはネストした表から削除します。n
が NULL である場合、DELETE(n) は何も実行しません。DELETE(m,n) は、結合配列または
ネストした表から m ~ n の範囲のすべての要素を削除します。m が n より大きい場合、または
m か n が NULL である場合、DELETE(m,n) は何も実行しません。
EXISTS
EXISTS(n) は、コレクションに n 番目の要素が存在する場合に TRUE を戻します。それ以外の
場合、EXISTS(n) は FALSE を戻します。主に EXISTS は、DELETE とともに、疎であるネス
トした表のメンテナンスのために使用します。また、EXISTS を使用すると、存在しない要素
を参照した場合に呼び出される例外を回避できます。範囲外の添字を渡した場合、EXISTS は
SUBSCRIPT_OUTSIDE_LIMIT を呼び出さずに、FALSE を戻します。
EXTEND
このプロシージャには 3 つの形式があります。EXTEND は、コレクションに 1 つの NULL 要素
を追加します。EXTEND(n) は、コレクションに n 個の NULL 要素を追加します。
EXTEND(n,i) は、コレクションに i 番目の要素のコピーを n 個追加します。EXTEND は、コ
レクションの内部サイズに対して操作します。EXTEND は削除された要素を見つけると、それ
らの要素を数に含めます。結合配列で EXTEND を使用することはできません。
FIRST、
、LAST
FIRST と LAST は、それぞれコレクションの最初と最後(最小と最大)の添字値を戻します。
通常、添字値は整数ですが、結合配列では文字列の場合もあります。コレクションが空の場合、
FIRST と LAST は NULL を戻します。コレクションに含まれる要素の数が 1 つのみの場合、
FIRST と LAST は同じ添字値を戻します。VARRAY の場合、FIRST は常に 1 を戻し、LAST は
常に COUNT と同じです。ネストした表の場合、LAST は通常、COUNT と同じです。ただし、ネ
ストした表の途中から要素を削除すると、LAST は COUNT より大きくなります。
index
ほとんどの場合は整数が戻される(または暗黙的に整数に変換される)式、文字列キーを使用
して宣言した結合配列の場合は文字列です。
LIMIT
最大サイズがないネストした表の場合、LIMIT は NULL を戻します。VARRAY の場合、LIMIT
は VARRAY に入れることのできる(型定義で指定する必要がある)要素の最大数を戻します。
NEXT、
、PRIOR
PRIOR(n) は、コレクションの索引 n の前の添字を戻します。NEXT(n) は、索引 n の後の添
字を戻します。n の前の番号がない場合、PRIOR(n) は NULL を戻します。同様に、n の後の番
号がない場合、NEXT(n) は NULL を戻します。
TRIM
このプロシージャには 2 つの形式があります。TRIM は、コレクションの末尾から 1 つの要素を
削除します。TRIM(n) は、コレクションの末尾から n 個の要素を削除します。n が COUNT よ
り大きいと、TRIM(n) は SUBSCRIPT_BEYOND_COUNT を呼び出します。索引付き表で TRIM
を使用することはできません。TRIM は、コレクションの内部サイズ上での処理です。TRIM は
削除された要素を見つけると、それらの要素を数に含めます。
13-20
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
コレクション・メソッド
使用上の注意
コレクション・メソッドは SQL 文では使用できません。使用すると、コンパイル・エラーにな
ります。
基本構造的に NULL であるコレクションに適用されるのは EXISTS のみです。それ以外のメ
ソッドをそのようなコレクションに適用すると、PL/SQL は COLLECTION_IS_NULL を呼び出
します。
コレクション要素の添字が連続している場合、FOR ループで collection.FIRST ..
collection.LAST を使用して、すべての要素に対して反復処理を実行できます。PRIOR また
は NEXT を使用すると、任意の添字列を索引とするコレクション内を移動できます。たとえば、
PRIOR または NEXT を使用すると、要素をいくつか削除したネストした表内、または添字が文
字列の値である結合配列内を移動できます。
EXTEND は、削除された要素を含むコレクションの内部サイズに対して操作します。EXTEND
を使用して、基本構造的に NULL であるコレクションの初期化はできません。また、NOT
NULL 制約を TABLE または VARRAY 型に指定した場合、EXTEND の最初の 2 つの形式はその型
のコレクションに適用できません。
削除対象の要素が存在しない場合でも、DELETE は単にその要素をスキップするため、例外は
呼び出されません。VARRAY は密であるため、個の要素は削除できません。PL/SQL は削除さ
れた要素のプレースホルダを保持するため、削除された要素に新しい値を代入して、その要素
を置き換えることができます。ただし、PL/SQL は切り捨てられた(TRIM)要素のプレースホ
ルダは保持しません。
ネストした表に割り当てられるメモリーの量は、動的に増減します。要素を削除すると、メモ
リーはページ単位で解放されます。表全体を削除した場合は、すべてのメモリーが解放されま
す。
一般に、TRIM と DELETE の間の相互作用には依存しないでください。ネストした表は、固定
サイズの配列のように扱って DELETE のみを使用するか、またはスタックのように扱って
TRIM と EXTEND のみを使用することをお薦めします。
サブプログラム内で、コレクション・パラメータは引数のプロパティがバインドされているこ
とを前提にしています。メソッド FIRST、LAST、COUNT などをそのようなパラメータに適用
できます。VARRAY パラメータの場合、パラメータ・モードに関係なく、LIMIT の値は常にパ
ラメータの型定義から導出されます。
例
次の例を参照してください。
例 5-28「コレクション要素の EXISTS のチェック」(5-19 ページ)
例 5-29「COUNT を使用したコレクションの要素のカウント」(5-19 ページ)
例 5-30「LIMIT を使用したコレクションの最大サイズのチェック」
(5-20 ページ)
例 5-31「コレクションでの FIRST および LAST の使用」(5-20 ページ)
例 5-32「PRIOR および NEXT を使用したコレクションの要素へのアクセス」
(5-21 ページ)
例 5-34「EXTEND を使用したコレクションのサイズの拡大」(5-22 ページ)
例 5-35「TRIM を使用したコレクションのサイズの縮小」
(5-23 ページ)
例 5-37「コレクションに対する DELETE メソッドの使用」(5-25 ページ)
例 13-1「宣言および変数への値の代入」(13-5 ページ)
関連項目
「コレクション定義」(13-16 ページ)
PL/SQL の言語要素
13-21
コメント
コメント
コメントを使用すると、コードの内容を説明する任意のテキストをコード内に含めることがで
きます。また、廃止されたコード部分や作成途中のコード部分をコメントに入れて無効化する
こともできます。
PL/SQL では、単一行コメントと複数行コメントの 2 種類のコメント・スタイルがサポートさ
れています。行の中の任意の位置(文字リテラルの中は除く)に二重ハイフン(--)を挿入す
ると、その行の残りの部分がコメントになります。複数行コメントは、スラッシュ - アスタリ
スク(/*)で始まってアスタリスク - スラッシュ(*/)で終わります。詳細は、2-7 ページの
「コメント」を参照してください。
構文
comment ::=
––
text
/*
text
*/
使用上の注意
プログラムのテストやデバッグのときに、コード中の複数の行を無効にする場合があります。
単一行コメントは、行の末尾ならば、文の途中に置くこともできます。単一行コメントは複数
行コメント内に含めることができますが、複数行コメントはネストできません。
また、Oracle プリコンパイラ・プログラムが動的に処理する PL/SQL ブロックの中では、単一
行コメントは使用できません。これは、行の終わりを示す文字が無視され、単一行コメントが
ブロックの終わりまで続いてしまうためです。この場合、複数行コメントを使用してください。
複数行コメントのデリミタを使用すると、コードの一部分をすべてコメントにできます。
例
次の例を参照してください。
例 2-4「単一行コメントの使用」
(2-8 ページ)
例 2-5「複数行コメントの使用」
(2-8 ページ)
例 13-1「宣言および変数への値の代入」(13-5 ページ)
13-22
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
COMMIT 文
COMMIT 文
COMMIT 文は、カレント・トランザクションでデータベースに加えられた変更を確定します。
また、コミットは変更内容が他のユーザーからも見えるようにします。PL/SQL トランザク
ション処理の詳細は、6-28 ページの「PL/SQL におけるトランザクション処理の概要」を参照
してください。
SQL の COMMIT 文は、静的 SQL として PL/SQL に埋め込むことができます。SQL の COMMIT
文の構文の詳細は、
『Oracle Database SQL リファレンス』を参照してください。『Oracle
Database アプリケーション開発者ガイド - 基礎編』のトランザクションのコミットに関する項、
および『Oracle Database リファレンス』の COMMIT_WRITE 初期化パラメータに関する項を参
照してください。
使用上の注意
COMMIT 文は、すべての行と表のロックを解除します。また、最後のコミットまたはロール
バック以降にマークされたすべてのセーブポイントを消去します。変更がコミットされるまで
は、次のような状況になっています。
■
■
自分で変更を加えた表に問合せを発行するとその変更内容が見えますが、他のユーザーか
ら変更内容は見えません。
考えを変えた場合や間違いを修正する場合は、ROLLBACK 文を使用して変更内容をロール
バック(取消し)できます。
FOR UPDATE カーソルがオープンしているときにコミットした場合、そのカーソルでそれ以降
フェッチすると例外が呼び出されます。カーソルはオープンしたままのため、クローズしてく
ださい。詳細は、6-33 ページの「FOR UPDATE の使用」を参照してください。
例
次の例を参照してください。
例 6-1「PL/SQL を使用したデータ操作」
(6-2 ページ)
例 6-3「PL/SQL 変数の置換」
(6-2 ページ)
例 6-36「WRITE 句と COMMIT の併用」
(6-29 ページ)
例 6-40「SET TRANSACTION を使用した読取り専用トランザクションの開始」
(6-32 ページ)
例 6-43「パッケージでの自律型ファンクションの宣言」(6-36 ページ)
関連項目
「ROLLBACK 文」(13-101 ページ)
「SAVEPOINT 文」
(13-104 ページ)
「トランザクション制御」(6-3 ページ)
「コミットにまたがるフェッチ」(6-34 ページ)
PL/SQL の言語要素
13-23
定数と変数の宣言
定数と変数の宣言
定数と変数は、任意の PL/SQL ブロック、サブプログラムまたはパッケージの宣言部で宣言で
きます。宣言によって、値の記憶域を割り当て、データ型を指定し、参照できるように名前を
指定します。また、初期値を代入したり、NOT NULL 制約を付けることもできます。詳細は、
2-9 ページの「宣言」を参照してください。
構文
variable declaration ::=
NOT
NULL
:=
expression
DEFAULT
variable_name
datatype
;
datatype ::=
collection_name
%
TYPE
collection_type_name
cursor_name
%
ROWTYPE
cursor_variable_name
%
TYPE
%
ROWTYPE
.
column_name
db_table_name
object_name
%
%
TYPE
TYPE
REF
object_type_name
record_name
%
TYPE
record_type_name
ref_cursor_type_name
scalar_datatype_name
variable_name
%
TYPE
constant ::=
NOT
constant_name
CONSTANT
NULL
:=
datatype
expression
;
DEFAULT
キーワードとパラメータの説明
collection_name
現行の有効範囲のうち、これより前の部分で宣言されているコレクション(結合配列、ネスト
した表または VARRAY)を識別します。
13-24
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
定数と変数の宣言
collection_type_name
データ型指定子 TABLE または VARRAY を使用して定義されたユーザー定義のコレクション型を
識別します。
CONSTANT
定数の宣言であることを示します。定数は宣言部で初期化してください。初期化された定数の
値は変更できません。
constant_name
プログラム定数を識別します。ネーミング規則は、2-3 ページの「識別子」を参照してくださ
い。
cursor_name
現行の有効範囲の中で、事前に宣言されている明示カーソルを識別します。
cursor_variable_name
現行の有効範囲の中で事前に宣言されている PL/SQL カーソル変数を識別します。
db_table_name
宣言が PL/SQL コンパイラによって処理されるときにアクセスできる必要があるデータベース
の表(またはビュー)を識別します。
db_table_name.column_name
宣言が PL/SQL コンパイラによって処理されるときにアクセスできる必要があるデータベース
の表および列を識別します。
expression
変数、定数、リテラル、演算子、ファンクション・コールの組合せです。最も単純な式は、1
個の変数で構成されています。宣言が PL/SQL コンパイラによって処理されるとき、
expression の値が定数または変数に代入されます。その値と定数または変数のデータ型には
互換性が必要です。
NOT NULL
プログラムで NULL 値を変数または定数に代入できないようにするための制約です。NOT
NULL として定義された変数に NULL を代入しようとすると、事前定義の例外 VALUE_ERROR
が呼び出されます。NOT NULL 制約の後には初期化句が続く必要があります。
object_name
現行の有効範囲のうち、これより前の部分で宣言されているオブジェクト型のインスタンスを
識別します。
record_name
現行の有効範囲のうち、これより前に宣言されているユーザー定義のレコードまたは
%ROWTYPE レコードを識別します。
record_name.field_name
現行の有効範囲のうち、これより前に宣言されているユーザー定義のレコードまたは
%ROWTYPE レコードのフィールドを識別します。
record_type_name
データ型指定子 RECORD を使用して定義するユーザー定義のレコード型を識別します。
PL/SQL の言語要素
13-25
定数と変数の宣言
ref_cursor_type_name
データ型指定子 REF CURSOR を使用して定義されたユーザー定義のカーソル変数型を識別しま
す。
%ROWTYPE
データベース表の中の行、またはカーソルを保持できるレコードを表します。レコードの中の
フィールドと行の中の列は、同じ名前とデータ型を持ちます。
scalar_datatype_name
事前定義済のスカラー・データ型(BOOLEAN、NUMBER、VARCHAR2 など)を識別します。サ
イズ、精度、または文字とバイトのセマンティクスの修飾子が含まれます。
%TYPE
これより前に宣言されたコレクション、カーソル変数、フィールド、オブジェクト、レコード、
データベース列または変数のデータ型を表します。
variable_name
プログラム変数を識別します。
使用上の注意
定数と変数は、ブロックまたはサブプログラムに入るたびに初期化されます。デフォルトでは、
変数は NULL に初期化されます。パッケージの仕様部で宣言された定数と変数は、パブリック
であるかプライベートであるかにかかわらず、セッションごとに 1 回のみ初期化されます。
NOT NULL 変数を宣言する場合、および定数を宣言する場合には、必ず初期化の句が必要です。
%ROWTYPE を使用して変数を宣言する場合は、初期化できません。
代入値を戻すファンクションをコールして、リテラル値または事前定義済コンストラクタを持
たない複合型の定数を定義できます。たとえば、この方法で定数の結合配列を作成できます。
例
次の例を参照してください。
例 1-1「PL/SQL 変数の宣言」
(1-6 ページ)
例 1-2「代入演算子を使用した変数への値の代入」
(1-6 ページ)
例 1-3「SELECT INTO を使用した変数への値の代入」
(1-6 ページ)
例 2-9「%ROWTYPE 属性の使用」
(2-11 ページ)
例 13-1「宣言および変数への値の代入」(13-5 ページ)
関連項目
「変数の宣言」(1-5 ページ)
「宣言」(2-9 ページ)
「事前定義された PL/SQL データ型の概要」(3-2 ページ)
「代入文」(13-3 ページ)
「式定義」(13-44 ページ)
「%ROWTYPE 属性」
(13-102 ページ)
「%TYPE 属性」
(13-117 ページ)
13-26
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
カーソル属性
カーソル属性
どの明示カーソルおよびカーソル変数にも %FOUND、%ISOPEN、%NOTFOUND および
%ROWCOUNT の 4 つの属性があります。これらの属性をカーソルまたはカーソル変数に付加する
と、DML 文の実行について役立つ情報が戻されます。詳細は、6-27 ページの「カーソル式の使
用」を参照してください。
暗黙カーソル SQL にはさらに属性 %BULK_ROWCOUNT および %BULK_EXCEPTIONS がありま
す。詳細は、13-113 ページの「SQL カーソル」を参照してください。
構文
cursor attribute ::=
FOUND
cursor_name
ISOPEN
cursor_variable_name
%
NOTFOUND
:
host_cursor_variable_name
ROWCOUNT
キーワードとパラメータの説明
cursor_name
現行の有効範囲の中で、事前に宣言されている明示カーソルを識別します。
cursor_variable_name
現行の有効範囲の中で、事前に宣言されている PL/SQL カーソル変数(またはパラメータ)を
識別します。
%FOUND 属性
カーソル属性で、カーソルまたはカーソル変数の名前に追加できます。カーソルがオープンさ
れてから最初のフェッチまでの cursor_name%FOUND は、NULL を戻します。その後、直前の
フェッチが行を戻した場合は TRUE を戻し、直前のフェッチが行を戻さなかった場合は FALSE
を戻します。
host_cursor_variable_name
PL/SQL ホスト環境で宣言され、バインド変数として PL/SQL に渡されるカーソル変数を識別
します。ホスト・カーソル変数のデータ型は、PL/SQL カーソル変数の戻り型と互換性があり
ます。ホスト変数には、接頭辞としてコロンを付けてください。
%ISOPEN 属性
カーソル属性で、カーソルまたはカーソル変数の名前に追加できます。カーソルがオープンさ
れていると、cursor_name%ISOPEN は TRUE を戻し、それ以外の場合は FALSE を戻します。
%NOTFOUND 属性
カーソル属性で、カーソルまたはカーソル変数の名前に追加できます。カーソルがオープンさ
れてから最初のフェッチまでの cursor_name%NOTFOUND は、NULL を戻します。その後、直
前のフェッチが行を戻した場合は FALSE を戻し、直前のフェッチが行を戻さなかった場合は
TRUE を戻します。
PL/SQL の言語要素
13-27
カーソル属性
%ROWCOUNT 属性
カーソル属性で、カーソルまたはカーソル変数の名前に追加できます。カーソルがオープンさ
れると %ROWCOUNT は 0(ゼロ)になります。最初のフェッチまでは、
cursor_name%ROWCOUNT は 0(ゼロ)を戻します。その後は、これまでにフェッチした行数
を戻します。フェッチで行が戻されるたびに、数値は増加します。
使用上の注意
カーソルの属性は、すべてのカーソルおよびカーソル変数に適用されます。たとえば、複数の
カーソルをオープンし、%FOUND または %NOTFOUND を使用して、まだフェッチしていない行
が残っているカーソルがどれかを判別できます。同様に、%ROWCOUNT を使用して、これまでに
フェッチした行の数を知ることができます。
カーソルまたはカーソル変数をオープンしていない場合、%FOUND、%NOTFOUND あるいは
%ROWCOUNT でカーソルやカーソル変数を参照すると、事前定義の例外 INVALID_CURSOR が呼
び出されます。
カーソルまたはカーソル変数をオープンすると、対応する問合せを満たす行が識別され、結果
セットが形成されます。行は、結果セットから一度に 1 行ずつフェッチされます。
SELECT INTO 文が複数の行を戻した場合、PL/SQL によって事前定義の例外 TOO_MANY_ROWS
が呼び出され、%ROWCOUNT は、問合せを満たす行の実数ではなく、1 に設定されます。
最初のフェッチの前は、%NOTFOUND の評価結果は NULL です。FETCH が正常に実行されない
場合は、EXIT WHEN 条件が TRUE とならず、ループは終了しません。安全のために、次の
EXIT 文をかわりに使用できます。
EXIT WHEN c1%NOTFOUND OR c1%NOTFOUND IS NULL;
カーソル属性は、プロシージャ文では使用できますが、SQL 文では使用できません。
例
次の例を参照してください。
例 6-7「SQL%FOUND の使用」(6-7 ページ)
例 6-8「SQL%ROWCOUNT の使用」(6-7 ページ)
例 6-10「カーソルを使用したフェッチ」(6-9 ページ)
例 6-15「%ISOPEN の使用」(6-12 ページ)
関連項目
「カーソル宣言」(13-32 ページ)
「カーソル変数」(13-29 ページ)
「PL/SQL でのカーソルの管理」
(6-6 ページ)
13-28
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
カーソル変数
カーソル変数
複数行の問合せを実行するために、Oracle は処理情報を格納する名前の付けられていない作業
領域をオープンします。この領域にアクセスするには、作業領域の名前を示す明示カーソル、
または作業領域を指すカーソル変数を使用します。カーソル変数を作成するには、REF CURSOR
型を定義してから、その型のカーソル変数を宣言します。
カーソル変数は、C や Pascal のポインタに類似しており、項目のかわりに項目のアドレスを保
持します。カーソル変数を宣言すると、項目ではなくポインタが作成されます。
詳細は、6-19 ページの「カーソル変数(REF CURSOR)の使用」を参照してください。
構文
ref cursor type definition ::=
TYPE
type_name
IS
REF
CURSOR
db_table_name
cursor_name
%
ROWTYPE
cursor_variable_name
RETURN
record_name
%
TYPE
record_type_name
ref_cursor_type_name
;
ref cursor variable declaration ::=
cursor_variable_name
type_name
;
キーワードとパラメータの説明
cursor_name
現行の有効範囲の中で、事前に宣言されている明示カーソルを識別します。
cursor_variable_name
現行の有効範囲の中で事前に宣言されている PL/SQL カーソル変数を識別します。
db_table_name
宣言が PL/SQL コンパイラによって処理されるときにアクセスできる必要があるデータベース
の表またはビューを識別します。
record_name
現行の有効範囲の中で事前に宣言されているユーザー定義のレコードを識別します。
record_type_name
データ型指定子 RECORD を使用して定義されたユーザー定義のレコード型を識別します。
PL/SQL の言語要素
13-29
カーソル変数
REF CURSOR
すべてのカーソル変数がデータ型 REF CURSOR に属します。
RETURN
カーソル変数の戻り値のデータ型を指定します。RETURN 句で %ROWTYPE 属性を使用すると、
データベース表の行や、カーソルまたは強い型指定のカーソル変数によって戻される行を表す
レコード型を与えることができます。また、%TYPE 属性を使用して、事前に宣言されたレコー
ドのデータ型を与えることもできます。
%ROWTYPE
データベース表の中の行、またはカーソルや強い型指定のカーソル変数からフェッチされる行
を表すレコード型を指定します。レコードの中のフィールドと、それに対応する行の中の列は、
同じ名前とデータ型を持ちます。
%TYPE
事前に宣言されているユーザー定義のレコードのデータ型を指定します。
type_name
REF CURSOR として定義されたユーザー定義のカーソル変数型を識別します。
使用上の注意
カーソル変数は、すべての PL/SQL クライアントで使用します。たとえば、OCI や Pro*C プロ
グラムなどの PL/SQL ホスト環境の中でカーソル変数を宣言し、それをバインド変数として
PL/SQL に渡すことができます。PL/SQL エンジンを備えたアプリケーション開発ツールでは、
クライアント側でカーソル変数を完全に使用できます。
データベース・リンクによるリモート・プロシージャ・コールを通じて、アプリケーションと
データベース・サーバーの間でカーソル変数をやり取りできます。クライアント側に PL/SQL
エンジンがあれば、どちらの側でもカーソル変数を使用できます。たとえば、クライアント側
でカーソル変数を宣言し、それをサーバー側でオープンしてフェッチした後で、クライアント
側で引き続きフェッチすることができます。
カーソル変数は、PL/SQL のストアド・サブプログラムとクライアント・プログラムとの間で
問合せの結果セットを渡すために使用します。PL/SQL とクライアント・プログラムはどちら
も結果セットを所有せず、結果セットが格納されている作業領域を指すポインタを共有してい
ます。たとえば、OCI プログラム、Oracle Forms アプリケーションおよびデータベースがすべ
て同じ作業領域を参照する場合があります。
REF CURSOR 型には、強いものと弱いものがあります。強い REF CURSOR 型定義では戻り型を
指定しますが、弱い型定義では戻り型を指定しません。強い REF CURSOR 型の方が、エラー発
生の可能性は少なくなります。これは、PL/SQL の場合、強い型指定のカーソル変数は型互換
性のある問合せにしか関連付けることができないためです。弱い REF CURSOR 型は、より柔軟
です。弱い型指定のカーソル変数は、どの問合せにも関連付けることができます。
REF CURSOR 型を一度定義すれば、その型のカーソル変数を宣言できます。%TYPE を使用する
と、レコード変数のデータ型を与えることができます。また、REF CURSOR 型定義の RETURN
句では、%ROWTYPE を使用して、強い型指定(弱い型指定ではなく)のカーソル変数によって
戻される行を表すレコード型を指定できます。
現在のところ、カーソル変数にはいくつかの制限があります。6-26 ページの「カーソル変数の
制限」を参照してください。
カーソル変数の制御には、OPEN-FOR、FETCH および CLOSE の 3 つの文を使用します。まず、
OPEN-FOR 文でカーソル変数を複数行問合せ用にオープンします。次に、FETCH 文で結果セッ
トから行を取り出します。すべての行が処理された後に、CLOSE 文でカーソル変数をクローズ
します。
13-30
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
カーソル変数
その他の OPEN-FOR 文は、異なる複数の問合せ用に同じカーソル変数をオープンできます。
カーソル変数を再オープンする場合、その前にクローズする必要はありません。別の問合せ用
にカーソル変数を再オープンすると、前の問合せは失われます。
PL/SQL では、カーソル変数の戻り型が、必ず FETCH 文の INTO 句と互換性を持ちます。カー
ソル変数に関連付けられた問合せが戻す列の値に対して、INTO 句の中に、対応する、型互換性
のあるフィールドまたは変数が存在している必要があります。また、フィールドまたは変数の
数は、列の値の数と一致する必要があります。それ以外の場合はエラーになります。
代入に関係する両方のカーソル変数が強い型指定である場合は、両方が同じデータ型であるこ
とが必要です。ただし、一方または両方のカーソル変数が弱い型指定である場合は、同じデー
タ型でなくてもかまいません。
カーソル変数を、そのカーソル変数からフェッチするか、またはそのカーソル変数をクローズ
するサブプログラムの仮パラメータとして宣言する場合は、IN または IN OUT モードを指定す
る必要があります。サブプログラムがカーソル変数をオープンする場合は、IN OUT モードを指
定する必要があります。
カーソル変数をパラメータとして渡す場合は注意が必要です。実パラメータと仮パラメータの
戻り型に互換性がないと、実行時に PL/SQL によって ROWTYPE_MISMATCH が呼び出されま
す。
カーソル属性 %FOUND、%NOTFOUND、%ISOPEN、%ROWCOUNT をカーソル変数に適用できます。
問合せ作業領域を指していないカーソル変数に対してフェッチまたはクローズを実行するか、
カーソルの属性を適用しようとすると、PL/SQL によって事前定義の例外 INVALID_CURSOR
が呼び出されます。カーソル変数(またはパラメータ)が問合せ作業領域を指すようにするに
は、次の 2 通りの方法があります。
■
■
OPEN-FOR 文でカーソル変数を問合せ用にオープンします。
OPEN 文ですでにオープンされたホスト・カーソル変数または PL/SQL カーソル変数の値
を、カーソル変数に代入します。
問合せ作業領域は、それを指すカーソル変数が存在するかぎりアクセスできます。したがって、
カーソル変数の値は、1 つの有効範囲から別の有効範囲へ自由に渡すことができます。たとえ
ば、Pro*C プログラムに組み込まれた PL/SQL ブロックにホスト・カーソル変数を渡す場合、
カーソル変数が指す作業領域は、そのブロックの終了後もアクセス可能な状態のままです。
例
次の例を参照してください。
例 6-9「カーソルの宣言」
(6-8 ページ)
例 6-10「カーソルを使用したフェッチ」(6-9 ページ)
例 6-13「カーソルを使用したバルク・データのフェッチ」(6-11 ページ)
例 6-27「REF CURSOR のパラメータとしての引渡し」
(6-21 ページ)
例 6-29「REF CURSOR をオープンするストアド・プロシージャ」
(6-22 ページ)
例 6-30「別の問合せで REF CURSOR をオープンするストアド・プロシージャ」(6-22 ページ)
例 6-31「異なる戻り型を持つカーソル変数」(6-23 ページ
関連項目
「CLOSE 文」(13-15 ページ)
「カーソル属性」(13-27 ページ)
「カーソル宣言」(13-32 ページ)
「FETCH 文」
(13-52 ページ)
「OPEN-FOR 文」
(13-81 ページ)
PL/SQL の言語要素
13-31
カーソル宣言
カーソル宣言
複数行の問合せを実行するために、Oracle は処理情報を格納する名前の付けられていない作業
領域をオープンします。カーソルを使用すると、作業領域の名前付け、情報へのアクセス、行
の個別処理が可能です。詳細は、6-14 ページの「PL/SQL を使用したデータの問合せ」を参照
してください。
構文
cursor declaration ::=
,
(
CURSOR
cursor_parameter_declaration
)
cursor_name
RETURN
rowtype
IS
select_statement
;
cursor spec ::=
,
CURSOR
cursor_name
RETURN
rowtype
(
cursor_parameter_declaration
(
cursor_parameter_declaration
)
;
cursor body ::=
,
CURSOR
cursor_name
RETURN
rowtype
IS
select_statement
)
;
cursor parameter declaration ::=
:=
expression
IN
parameter_name
13-32
DEFAULT
datatype
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
カーソル宣言
rowtype ::=
db_table_name
cursor_name
%
ROWTYPE
cursor_variable_name
record_name
%
TYPE
record_type_name
キーワードとパラメータの説明
cursor_name
現行の有効範囲の中で、事前に宣言されている明示カーソルを識別します。
datatype
型指定子です。datatype の構文は、13-24 ページの「定数と変数の宣言」を参照してくださ
い。
db_table_name
宣言が PL/SQL コンパイラによって処理されるときにアクセスできる必要があるデータベース
の表(またはビュー)を識別します。
expression
変数、定数、リテラル、演算子、ファンクション・コールの組合せです。最も単純な式は、1
個の変数で構成されています。宣言が PL/SQL コンパイラによって処理されるときに、
expression の値がパラメータに代入されます。その値とパラメータのデータ型には互換性が
必要です。
parameter_name
カーソルの仮パラメータとして宣言された変数を識別します。カーソルのパラメータは、問合
せの中で定数が使用できる場所であれば、どこででも使用できます。カーソルの仮パラメータ
は IN パラメータにしてください。問合せは、有効範囲の他の PL/SQL 変数を参照することも
できます。
record_name
現行の有効範囲の中で事前に宣言されているユーザー定義のレコードを識別します。
record_type_name
データ型指定子 RECORD を使用して定義されたユーザー定義のレコード型を識別します。
RETURN
カーソルの戻り値のデータ型を指定します。RETURN 句で %ROWTYPE 属性を使用すると、デー
タベースの表の行や、事前に宣言されたカーソルによって戻される行を表すレコード型を与え
ることができます。また、%TYPE 属性を使用して、事前に宣言されたレコードのデータ型を与
えることもできます。
カーソル本体には、SELECT 文と、対応するカーソル仕様部と同じ RETURN 句が必要です。さ
らに、SELECT 句の中の選択項目の数、順序およびデータ型は、RETURN 句と一致している必
要があります。
PL/SQL の言語要素
13-33
カーソル宣言
%ROWTYPE
データベース表の中の行、または事前に宣言されたカーソルやカーソル変数からフェッチされ
る行を表すレコード型を指定します。レコードの中のフィールドと、それに対応する行の中の
列は、同じ名前とデータ型を持ちます。
select_statement
行の結果セットを戻す問合せです。構文は select_into_statement の構文と似ていますが、
INTO 句は使用できません。13-105 ページの「SELECT INTO 文」を参照してください。カーソ
ル宣言でパラメータを宣言した場合は、すべてのパラメータを問合せで使用する必要がありま
す。
%TYPE
事前に宣言されているユーザー定義のレコードのデータ型を指定します。
使用上の注意
OPEN 文、FETCH 文または CLOSE 文でカーソルを参照する前に、そのカーソルを宣言します。
カーソル宣言で変数を参照する前に、その変数を宣言します。SQL という語は、暗黙カーソル
のデフォルト名として PL/SQL によって予約されており、カーソル宣言の中では使用できませ
ん。
カーソル名に値を代入したり、カーソル名を式の中で使用することはできません。ただし、
カーソルの有効範囲規則は変数の有効範囲規則と同じです。詳細は、2-15 ページの「PL/SQL
の識別子の有効範囲と可視性」を参照してください。
カーソルからデータを取り出す場合は、まずカーソルをオープンし、そこからフェッチします。
FETCH 文ではターゲットとなる変数を指定するため、cursor_declaration の SELECT 文で
INTO 句を使用するのは冗長かつ誤りです。
カーソルのパラメータの有効範囲は、カーソルに対してローカルです。つまり、カーソル宣言
の中で使用されている問合せの内側からしか参照できません。カーソルのパラメータ値は、
カーソルがオープンされているときに、カーソルに関連付けられた問合せから使用できます。
問合せは、有効範囲の他の PL/SQL 変数を参照することもできます。
カーソルのパラメータのデータ型は、無制約で指定する必要があります(数値の精度と位取り、
および文字列の長さは指定しません)
。
例
次の例を参照してください。
例 6-9「カーソルの宣言」
(6-8 ページ)
例 6-10「カーソルを使用したフェッチ」(6-9 ページ)
例 6-13「カーソルを使用したバルク・データのフェッチ」(6-11 ページ)
例 6-27「REF CURSOR のパラメータとしての引渡し」
(6-21 ページ)
例 6-29「REF CURSOR をオープンするストアド・プロシージャ」
(6-22 ページ)
例 6-30「別の問合せで REF CURSOR をオープンするストアド・プロシージャ」(6-22 ページ)
例 13-1「宣言および変数への値の代入」(13-5 ページ)
関連項目
「CLOSE 文」(13-15 ページ)
「FETCH 文」
(13-52 ページ)
「OPEN 文」(13-79 ページ)
「SELECT INTO 文」(13-105 ページ)
「カーソルの宣言」(6-8 ページ)
13-34
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
DELETE 文
DELETE 文
DELETE 文は、指定された表またはビューから、行のデータを削除します。DELETE 文の詳細
は、
『Oracle Database SQL リファレンス』を参照してください。
構文
delete ::=
table_reference
FROM
DELETE
(
alias
subquery
TABLE
(
)
subquery2
)
search_condition
WHERE
CURRENT_OF
cursor_name
returning_clause
;
table_reference ::=
schema
.
table_name
@
dblink
view_name
キーワードとパラメータの説明
alias
参照される表またはビューの別名(通常は短縮名)です。通常、WHERE 句の中で参照されま
す。
BULK COLLECT
RETURNING INTO リストで指定した場合と同様に、削除された行から PL/SQL コレクションに
列を戻します。対応する列には、
(複合値ではなく)スカラー値が格納されている必要がありま
す。詳細は、11-8 ページの「バルク SQL による、DML 文および問合せのループ・オーバー
ヘッドの削減」を参照してください。
returning_clause
削除された行から値を戻します。そのため、最初に行を SELECT で選択しておく必要はありま
せん。取り出した列値は、個の変数またはコレクションに代入できます。RETURNING 句はリ
モートまたはパラレルでの削除には使用できません。文を実行しても行に影響がない場合、
RETURNING 句で指定した変数の値は未定義になります。13-99 ページの「RETURNING INTO
句」を参照してください。
subquery
処理する行セットを提供する SELECT 文です。構文は select_into_statement の構文と似
ていますが、INTO 句は使用できません。13-105 ページの「SELECT INTO 文」を参照してくだ
さい。
PL/SQL の言語要素
13-35
DELETE 文
table_reference
表またはビューを指定します。指定された表またはビューは、DELETE 文の実行時にアクセス
できる必要があり、ユーザーは DELETE 権限を持つ必要があります。
TABLE (subquery2)
TABLE のオペランドは、1 つの列値を戻す SELECT 文です。これはネストした表である必要が
あります。演算子 TABLE は、値がスカラー値ではなくコレクションであることを Oracle に通
知します。
WHERE CURRENT OF cursor_name
cursor_name で識別されるカーソルに関連付けられている FETCH 文によって処理された最後
の行を参照します。カーソルは、FOR UPDATE であること、さらにオープンされていて行に置
かれていることが必要です。カーソルがオープンされていないと、CURRENT OF 句でエラーが
発生します。
カーソルがオープンされていても、フェッチされた行がないか、最後のフェッチで行が戻され
なかった場合は、PL/SQL によって事前定義の例外 NO_DATA_FOUND が呼び出されます。
WHERE search_condition
参照された表またはビューから削除する行を条件に従って選択します。検索条件を満たす行の
みが削除されます。WHERE 句を省略すると、表またはビューのすべての行が削除されます。
使用上の注意
DELETE WHERE CURRENT OF 文は、オープンされているカーソルからのフェッチ(カーソル
FOR ループで実行される暗黙的なフェッチを含む)の後で使用できます。ただし、そのために
は、関連付けられた問合せが FOR UPDATE であることが必要です。この文は現在行、つまり直
前にフェッチされた行を削除します。
暗黙カーソル SQL と、カーソル属性 %NOTFOUND、%FOUND および %ROWCOUNT を使用すると、
DELETE 文の実行に関する有用な情報にアクセスできます。
例
次の例を参照してください。
例 6-1「PL/SQL を使用したデータ操作」
(6-2 ページ)
例 6-5「CURRVAL と NEXTVAL の使用」
(6-4 ページ)
例 6-7「SQL%FOUND の使用」(6-7 ページ)
例 6-8「SQL%ROWCOUNT の使用」(6-7 ページ)
例 6-29「REF CURSOR をオープンするストアド・プロシージャ」
(6-22 ページ)
例 6-30「別の問合せで REF CURSOR をオープンするストアド・プロシージャ」(6-22 ページ)
例 11-2「ループでの DELETE 文の発行」(11-9 ページ)
例 11-16「BULK COLLECT での FORALL の使用」(11-18 ページ)
関連項目
「FETCH 文」
(13-52 ページ)
「INSERT 文」
(13-65 ページ)
「SELECT INTO 文」(13-105 ページ)
「UPDATE 文」(13-119 ページ)
13-36
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
EXCEPTION_INIT プラグマ
EXCEPTION_INIT プラグマ
EXCEPTION_INIT プラグマは、例外名を Oracle エラー番号に関連付けます。OTHERS ハンド
ラを使用するかわりに、ORA- エラーを回避し、専用のハンドラを作成できます。詳細は、10-7
ページの「PL/SQL 例外と番号の関連付け : EXCEPTION_INIT プラグマ」を参照してくださ
い。
構文
exception_init pragma ::=
PRAGMA
EXCEPTION_INIT
(
exception_name
,
error_number
)
;
キーワードとパラメータの説明
error_number
任意の有効な Oracle エラー番号です。これは SQLCODE ファンクションが戻すエラー番号(常
に負の値)と同じです。
exception_name
現行の有効範囲の中で宣言されているユーザー定義の例外を識別します。
PRAGMA
文がコンパイラ・ディレクティブであることを表します。
使用上の注意
EXCEPTION_INIT は、任意の PL/SQL ブロック、サブプログラムまたはパッケージの宣言部
で使用できます。このプラグマは、関連付けられた例外と同じ宣言部の中で、例外宣言の後の
どこかに指定する必要があります。
1 つのエラー番号に割り当てる例外名は 1 つのみです。
例
次の例を参照してください。
例 10-4「PRAGMA EXCEPTION_INIT の使用」
(10-7 ページ)
例 11-9「例外が発生しても継続するバルク操作」
(11-14 ページ)
関連項目
「AUTONOMOUS_TRANSACTION プラグマ」(13-6 ページ)
「例外定義」(13-38 ページ)
「SQLCODE ファンクション」
(13-115 ページ)
PL/SQL の言語要素
13-37
例外定義
例外定義
例外は、事前定義またはユーザー定義可能な、ランタイム・エラーまたは警告状態です。事前
定義の例外は実行時システムによって暗黙的(自動的)に呼び出されます。ユーザー定義の例
外は RAISE 文によって明示的に呼び出す必要があります。呼び出された例外を処理するには、
例外ハンドラと呼ばれる独立したルーチンを作成します。詳細は、第 10 章「PL/SQL エラーの
処理」を参照してください。
構文
exception ::=
exception_name
EXCEPTION
;
exception handler ::=
OR
exception_name
exception_name
WHEN
THEN
statement
OTHERS
キーワードとパラメータの説明
exception_name
ZERO_DIVIDE のような事前定義の例外、または現行の有効範囲の中で事前に宣言されている
ユーザー定義の例外を識別します。
OTHERS
ブロックの例外処理部で明示的に名前を指定していないすべての例外を表します。OTHERS の
使用はオプションで、ブロックの最後の例外ハンドラとしてのみ使用できます。キーワード
WHEN に続く例外のリストの中では、OTHERS を使用できません。
statement
実行可能文です。statement の構文は、13-8 ページの「ブロック宣言」を参照してください。
WHEN
例外ハンドラの開始を知らせるキーワードです。キーワード WHEN に続けて、キーワード OR で
区切った例外のリストを指定すると、複数の例外で一連の同一文を実行できます。リスト中の
いずれかの例外が呼び出されると、それに関連付けられた文が実行されます。
使用上の注意
例外宣言はブロック、サブプログラム、またはパッケージの宣言部でのみ使用できます。例外
の有効範囲の規則は変数と同じです。ただし、変数とは異なり、例外をパラメータとしてサブ
プログラムに渡すことができません。
例外のいくつかは PL/SQL によって事前に定義されています。これらの例外のリストは、10-4
ページの「事前定義の PL/SQL 例外のまとめ」を参照してください。PL/SQL は、事前定義済
の例外をパッケージ STANDARD でグローバルに宣言しているため、ユーザーが宣言する必要は
ありません。
13-38
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
例外定義
事前定義の例外を再宣言すると、ローカルな宣言がグローバルな宣言をオーバーライドするた
め、エラーが発生しやすくなります。この場合は、ドット表記法を使用して、次のように事前
定義の例外を指定する必要があります。
EXCEPTION
WHEN invalid_number OR STANDARD.INVALID_NUMBER THEN ...
PL/SQL ブロックの例外処理部はオプションです。例外ハンドラはブロックの末尾に置く必要
があります。例外処理部はキーワード EXCEPTION で始まります。ブロックの例外処理部の終
わりは、ブロックの終わりも示すキーワード END です。例外ハンドラから参照できる変数は、
カレント・ブロックから参照できる変数のみです。
例外を呼び出すのは、処理の続行が不可能、あるいは望ましくないようなエラーが発生した場
合のみにしてください。呼び出された例外に対応する例外ハンドラがカレント・ブロックに存
在しない場合、例外は次の規則に従って伝播します。
■
■
カレント・ブロックの外側にブロックがある場合、例外はそのブロックに渡されます。こ
の場合、例外が渡されたブロックがカレント・ブロックになります。呼び出された例外に
対応するハンドラが見つからない場合は、この過程が繰り返されます。
カレント・ブロックの外側にブロックがない場合、
「未処理例外」エラーがホスト環境に戻
されます。
ブロックの例外処理部でアクティブになれる例外は一度に 1 つのみです。このため、ハンドラ
の内側で例外が呼び出されると、カレント・ブロックの外側のブロックが、新しく呼び出され
た例外に対するハンドラを検索するための最初のブロックになります。それ以降の例外の伝播
は通常どおりに行われます。
例
次の例を参照してください。
例 1-9「WHILE-LOOP を使用した制御」
(1-11 ページ)
例 1-12「ストアド・サブプログラムの作成」(1-13 ページ)
例 2-19「複数の重複したラベルを使用する PL/SQL ブロック」
(2-17 ページ)
例 5-35「TRIM を使用したコレクションのサイズの縮小」
(5-23 ページ)
例 5-38「コレクションに関する例外」(5-26 ページ)
例 6-37「ROLLBACK の使用」
(6-30 ページ)
例 7-1「動的 SQL の例」(7-3 ページ)
例 8-1「単純な PL/SQL プロシージャ」(8-2 ページ)
例 9-3「emp_admin パッケージの作成」
(9-6 ページ)
例 10-1「ランタイム・エラー処理」(10-2 ページ)
例 10-3「PL/SQL 例外の有効範囲」(10-6 ページ)
例 10-9「PL/SQL 例外の再呼出し」(10-12 ページ)
例 11-6「FORALL でのロールバックの使用」(11-11 ページ)
例 11-9「例外が発生しても継続するバルク操作」
(11-14 ページ)
例 12-3「PL/SQL ブロックでの NULL のオブジェクト」
(12-3 ページ)
関連項目
「ブロック宣言」(13-8 ページ)
「EXCEPTION_INIT プラグマ」
(13-37 ページ)
「RAISE 文」
(13-92 ページ)
PL/SQL の言語要素
13-39
EXECUTE IMMEDIATE 文
EXECUTE IMMEDIATE 文
EXECUTE IMMEDIATE 文は、動的 SQL 文または無名 PL/SQL ブロックを実行します。この文
を使用すると、PL/SQL で直接表せない SQL 文を発行したり、一部の表名、WHERE 句などが
事前に不明な場合でも文を作成できます。詳細は、7-2 ページの「PL/SQL での EXECUTE
IMMEDIATE 文の使用」を参照してください。
構文
EXECUTE_IMMEDIATE
dynamic_string
,
define_variable
INTO
record_name
,
collection_name
BULK
COLLECT
INTO
:
host_array_name
,
IN
OUT
IN
OUT
bind_argument
USING
returning_clause
;
キーワードとパラメータの説明
bind_argument
動的 SQL 文に渡される値を持つ式か、または動的 SQL 文から戻された値を格納する変数です。
BULK COLLECT
1 つ以上のコレクションに結果の値を格納します。FETCH 文を使用したループよりも高速な問
合せが可能です。詳細は、11-8 ページの「バルク SQL による、DML 文および問合せのルー
プ・オーバーヘッドの削減」を参照してください。
collection_name
フェッチした select_item 値を格納するための、宣言されたコレクションを識別します。
select_item ごとに、リストの中に、対応する型互換のコレクションが存在している必要が
あります。
13-40
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
EXECUTE IMMEDIATE 文
host_array_name
フェッチした select_item 値を格納するための配列を識別します。この配列は、PL/SQL ホ
スト環境で宣言され、バインド変数として PL/SQL に渡されます。select_item ごとに、リ
ストの中に、対応する型互換の配列が存在している必要があります。ホスト配列には、接頭辞
としてコロンが必要です。
define_variable
選択された列の値を格納する変数を識別します。
dynamic_string
1 つの SQL 文または PL/SQL ブロックを表す文字列リテラル、変数または式です。NCHAR 型ま
たは NVARCHAR2 型ではなく、CHAR 型または VARCHAR2 型である必要があります。
INTO ...
単一行の問合せの場合に使用され、取り出された列値を入れる変数またはレコードを指定しま
す。問合せによって取り出された値それぞれに対して、INTO 句の中に、対応する型互換性変数
が存在している必要があります。
record_name
選択された行を格納するユーザー定義のレコードまたは %ROWTYPE レコードを識別します。
returning_clause
挿入された行から値を戻します。そのため、後で行を SELECT で選択する必要がありません。
取り出した列値は、変数またはコレクションに代入できます。RETURNING 句はリモートまたは
パラレルでの挿入には使用できません。文を実行しても行に影響がない場合、RETURNING 句で
指定した変数の値は未定義になります。returning_clause の構文は、13-99 ページの
「RETURNING INTO 句」を参照してください。
USING ...
入力または出力バインド引数(あるいはその両方)のリストを指定します。デフォルトのパラ
メータ・モードは IN です。
使用上の注意
複数行の問合せの場合を除いて、動的文字列には任意の SQL 文(最後のセミコロンなし)また
は任意の PL/SQL ブロック(最後のセミコロン付き)を含めることができます。また、バイン
ド引数のプレースホルダも含めることができます。バインド引数を使用してスキーマ・オブ
ジェクトの名前を動的 SQL 文に渡すことはできません。
バインド引数は、すべて USING 句に入れることができます。デフォルトのパラメータ・モード
は IN です。RETURNING 句を持つ DML 文の場合は、パラメータ・モード OUT を定義して指定
しなくても、OUT 引数を RETURNING INTO 句に入れることができます。USING 句と
RETURNING INTO 句の両方を使用する場合、USING 句には IN 引数のみを含めることができま
す。
実行時に、バインド引数は動的文字列内の対応するプレースホルダを置き換えます。すべての
プレースホルダを USING 句内または RETURNING INTO 句内(あるいはその両方)のバインド
引数に関連付ける必要があります。数値リテラル、文字リテラルおよび文字列リテラルはバイ
ンド引数として使用できますが、ブール・リテラル(TRUE、FALSE および NULL)は使用でき
ません。動的文字列に NULL を渡すには、回避策を使用する必要があります。7-10 ページの
「動的 SQL への NULL の引渡し」を参照してください。
動的 SQL はすべての SQL データ型をサポートしています。たとえば、定義変数やバインド引
数をコレクション、LOB、オブジェクト型のインスタンスおよび ref とすることができます。動
的 SQL は PL/SQL 固有の型をサポートしていません。たとえば、定義変数やバインド引数を
ブールまたは索引付き表にすることはできません。例外として、PL/SQL レコードを INTO 句
に入れることができます。
PL/SQL の言語要素
13-41
EXECUTE IMMEDIATE 文
動的 SQL 文は、バインド引数の新しい値を使用して繰り返し実行できます。ただし、EXECUTE
IMMEDIATE は実行のたびに動的文字列を準備するため、オーバーヘッドが発生します。
EXECUTE IMMEDIATE コマンドの文字列引数に、NCHAR、NVARCHAR2 などの各国語キャラク
タ・タイプを使用することはできません。
注意 : PL/SQL で動的 SQL を使用する場合は、SQL インジェクションの
リスクを認識しておく必要があります。SQL インジェクションによって、
セキュリティの問題が発生する可能性があります。SQL インジェクション
および発生する可能性がある問題の詳細は、
『Oracle Database アプリケー
ション開発者ガイド - 基礎編』を参照してください。SQL インジェクショ
ンについては、Oracle Technology Network の
http://www.oracle.com/technology で検索することもできます。
例
次の例を参照してください。
例 7-1「動的 SQL の例」(7-3 ページ)
例 7-2「表名および WHERE 句を受け入れる動的 SQL プロシージャ」(7-4 ページ)
例 7-4「BULK COLLECT INTO 句を使用した動的 SQL」
(7-6 ページ)
例 7-5「RETURNING BULK COLLECT INTO 句を使用した動的 SQL」(7-6 ページ)
例 7-6「FORALL 文中の動的 SQL」(7-7 ページ)
関連項目
「OPEN-FOR 文」
(13-81 ページ)
13-42
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
EXIT 文
EXIT 文
EXIT 文は、ループを終了します。EXIT 文には、無条件 EXIT と、条件付き EXIT WHEN とい
う 2 つの形式があります。どちらの形式でも、終了するループの名前を指定できます。詳細は、
4-7 ページの「ループの反復の制御 : LOOP 文と EXIT 文」を参照してください。
構文
exit ::=
label_name
WHEN
boolean_expression
EXIT
;
キーワードとパラメータの説明
boolean_expression
TRUE、FALSE または NULL のいずれかのブール値を戻す式です。この式は、ループが繰り返さ
れるたびに評価されます。式が TRUE を戻す場合、カレント・ループ(または label_name の
ラベルの付いたループ)はただちに終了します。boolean_expression の構文は、13-44 ペー
ジの「式定義」を参照してください。
EXIT
無条件の(つまり WHEN 句のない)EXIT 文は、カレント・ループをただちに終了します。実行
はループの直後の文から再開されます。
label_name
終了するループを識別します。カレント・ループ、またはラベルが付けられている外側のルー
プのいずれかになります。
使用上の注意
EXIT 文は、ループの内側でのみ使用できます。ブロックからは直接終了できません。PL/SQL
では無限ループをコーディングできます。たとえば、次のループは通常の方法では永久に終了
しないため、EXIT 文を使用して終了させます。
WHILE TRUE LOOP ...END LOOP;
EXIT 文を使用してカーソル FOR ループを途中で終了させると、カーソルは自動的にクローズ
されます。ループの内側で例外が呼び出された場合も、カーソルは自動的にクローズされます。
例
次の例を参照してください。
例 4-8「EXIT 文の使用」(4-7 ページ)
例 4-17「LOOP での EXIT の使用」
(4-12 ページ)
例 4-18「LOOP でのラベル付き EXIT の使用」
(4-13 ページ)
関連項目
「式定義」(13-44 ページ)
「LOOP 文」
(13-71 ページ)
PL/SQL の言語要素
13-43
式定義
式定義
式は、変数、定数、リテラル、演算子、ファンクション・コールの任意の組合せです。最も単
純な式は、1 個の変数で構成されています。
PL/SQL コンパイラは、式を構成する変数、定数、リテラルおよび演算子の型から、式のデー
タ型を決定します。式が評価されたときは、その型の 1 つの値が結果として得られます。詳細
は、2-19 ページの「PL/SQL の式および比較」を参照してください。
構文
expression ::=
boolean_expression
(
)
character_expression
date_expression
numeric_expression
boolean_expression ::=
boolean_constant_name
boolean_function_call
NOT
boolean_literal
boolean_variable_name
other_boolean_form
boolean_constant_name
AND
NOT
boolean_function_call
boolean_literal
OR
boolean_variable_name
other_boolean_form
13-44
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
式定義
other boolean form ::=
collection_name
.
EXISTS
(
index
)
cursor_name
FOUND
cursor_variable_name
%
:
ISOPEN
host_cursor_variable_name
NOTFOUND
SQL
relational_operator expression
NOT
IS
NULL
expression
LIKE
NOT
pattern
BETWEEN
expression
AND
expression
,
IN
expression
character expression ::=
character_constant_name
character_function_call
character_literal
character_variable_name
:
:
indicator_name
host_variable_name
character_constant_name
character_function_call
||
character_literal
character_variable_name
:
:
indicator_name
host_variable_name
PL/SQL の言語要素
13-45
式定義
numeric subexpression ::=
cursor_name
cursor_variable_name
%
:
ROWCOUNT
host_cursor_variable_name
SQL
SQL
%
BULK_ROWCOUNT
:
:
(
integer
)
indicator_name
host_variable_name
**
numeric_constant_name
numeric_function_call
numeric_literal
numeric_variable_name
COUNT
FIRST
collection_name
.
LAST
LIMIT
NEXT
(
index
)
PRIOR
date expression ::=
date_constant_name
date_function_call
date_literal
date_variable_name
:
:
indicator_name
host_variable_name
+
numeric_expression
–
numeric expression ::=
+
–
numeric_subexpression
*
/
numeric_subexpression
13-46
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
exponent
式定義
キーワードとパラメータの説明
BETWEEN
この比較演算子は、ある値が指定範囲の中にあるかどうかをテストします。つまり、下限以上、
上限以下にあるかどうかがテストされます。
boolean_constant_name
BOOLEAN 型の定数を指定します。このような定数は、TRUE、FALSE、または NULL に初期化
される必要があります。ブール定数に対する算術演算は許可されていません。
boolean_expression
TRUE、FALSE または NULL のいずれかのブール値を戻す式です。
boolean_function_call
ブール値を戻すファンクション・コールです。
boolean_literal
事前定義の値 TRUE、FALSE、または NULL(存在しない値、不明な値または適用できない値を
表す)です。データベース列に値 TRUE や FALSE を挿入できません。
boolean_variable_name
BOOLEAN 型の変数を識別します。BOOLEAN 変数に代入できるのは、値 TRUE、FALSE および
NULL のみです。列の値を選択またはフェッチして BOOLEAN 変数に入れることはできません。
BOOLEAN 変数に対する算術演算も許可されていません。
%BULK_ROWCOUNT
FORALL 文で使用するように設計された、暗黙カーソル SQL の複合属性です。詳細は 13-113
ページの「SQL カーソル」を参照してください。
character_constant_name
文字値を格納する、事前に宣言された定数を識別します。この定数は、文字値または暗黙的に
文字値に変換可能な値に初期化される必要があります。
character_expression
文字または文字列を戻す式です。
character_function_call
文字値または暗黙的に文字値に変換可能な値を戻すファンクション・コールです。
character_literal
文字値または暗黙的に文字値に変換可能な値を表すリテラルです。
character_variable_name
文字値を格納する、事前に宣言された変数を識別します。
collection_name
現行の有効範囲のうち、これより前の部分で宣言されているコレクション(ネストした表、索
引付き表または VARRAY)を指定します。
cursor_name
現行の有効範囲の中で、事前に宣言されている明示カーソルを識別します。
PL/SQL の言語要素
13-47
式定義
cursor_variable_name
現行の有効範囲の中で事前に宣言されている PL/SQL カーソル変数を識別します。
date_constant_name
日付値を格納する、事前に宣言された定数を識別します。この定数は、日付値、または暗黙的
に日付値に変換可能な値に初期化される必要があります。
date_expression
日付 / 時刻値を戻す式です。
date_function_call
日付値、または暗黙的に日付値に変換可能な値を戻すファンクション・コールです。
date_literal
日付値、または暗黙的に日付値に変換可能な値を表すリテラルです。
date_variable_name
日付値を格納する、事前に宣言された変数を識別します。
EXISTS、
、COUNT、
、FIRST、
、LAST、
、LIMIT、
、NEXT、
、PRIOR
コレクション・メソッドです。コレクションの名前にこれらを付加すると、有用な情報が戻さ
れます。たとえば、EXISTS(n) は、コレクションに n 番目の要素が存在する場合に TRUE を戻
します。それ以外の場合、EXISTS(n) は FALSE を戻します。詳細は、13-19 ページの「コレ
クション・メソッド」を参照してください。
exponent
数値を戻す式です。
%FOUND、
、%ISOPEN、
、%NOTFOUND、
、%ROWCOUNT
カーソルの属性です。カーソル名またはカーソル変数名にこれらの属性を追加すると、複数行
の問合せの実行に関する有用な情報が戻されます。これらの属性は暗黙カーソル SQL にも追加
できます。
host_cursor_variable_name
PL/SQL ホスト環境で宣言され、バインド変数として PL/SQL に渡されるカーソル変数を識別
します。ホスト・カーソル変数には、接頭辞としてコロンを付ける必要があります。
host_variable_name
PL/SQL ホスト環境で宣言され、バインド変数として PL/SQL に渡される変数を識別します。
ホスト変数のデータ型は、適切な PL/SQL のデータ型に暗黙的に変換できる必要があります。
また、ホスト変数には、接頭辞としてコロンを付ける必要があります。
IN
セット・メンバーシップをテストする比較演算子です。集合のいずれかのメンバーと等しいか
どうかがテストされます。集合には NULL が含まれていてもかまいませんが、NULL は無視さ
れます。さらに、次の形式の式の場合、
value NOT IN set
集合に NULL が含まれている場合は、FALSE が戻されます。
13-48
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
式定義
index
戻される値が BINARY_INTEGER 型の値、PLS_INTEGER 型の値、またはその型に暗黙的に変
換可能な値になる数値式です。
indicator_name
PL/SQL ホスト環境で宣言され、PL/SQL に渡される標識変数を識別します。標識変数には、
接頭辞としてコロンを付ける必要があります。標識変数は、関連付けられたホスト変数の値ま
たは条件を示します。たとえば、Oracle プリコンパイラ環境では、標識変数を使用して出力ホ
スト変数内の NULL や切り捨てられた値を検出できます。
IS NULL
オペランドが NULL の場合はブール値 TRUE を戻し、オペランドが NULL でない場合は
FALSE を戻す比較演算子です。
LIKE
文字値とパターンを比較する比較演算子です。大 / 小文字が区別されます。LIKE は、文字の
パターンが一致した場合はブール値 TRUE、一致しない場合は FALSE を戻します。
NOT、
、AND、
、OR
2-20 ページの表 2-3 の 3 値論理に従う論理演算子です。AND は、オペランドの両方が TRUE の
場合にのみ TRUE を戻します。OR は、オペランドの片方が TRUE ならば TRUE を戻します。
NOT はオペランドの反対の値(論理否定)を戻します。詳細は、2-20 ページの「論理演算子」
を参照してください。
NULL
NULL を表すキーワードです。存在しない値、不明な値または適用できない値を示します。数
値式または日付式の中で NULL を使用すると、結果は NULL になります。
numeric_constant_name
数値を格納する、事前に宣言された定数を識別します。この定数は、数値または暗黙的に数値
に変換可能な値に初期化される必要があります。
numeric_expression
整数または実数を戻す式です。
numeric_function_call
数値または暗黙的に数値に変換可能な値を戻すファンクション・コールです。
numeric_literal
数値または暗黙的に数値に変換可能な値を表すリテラルです。
numeric_variable_name
数値を格納する、事前に宣言された変数を識別します。
pattern
LIKE 演算子によって、指定された文字列値と比較される文字列です。pattern には、ワイルド
カードと呼ばれる特殊目的の文字を 2 種類使用できます。アンダースコア(_)は 1 つの文字を
表し、パーセント記号(%)は 0(ゼロ)個以上の文字を表します。パターンの後に ESCAPE
'character_literal' を使用することもできます。文字列の中で、パーセント記号またはア
ンダースコアの前にエスケープ文字があると、それらはワイルドカードとして認識されません。
PL/SQL の言語要素
13-49
式定義
relational_operator
式を比較する演算子です。各演算子の意味は、2-21 ページの「比較演算子」を参照してくださ
い。
SQL
SQL の DML 文を処理するために、Oracle によって暗黙的にオープンされるカーソルを識別し
ます。暗黙カーソル SQL は常に、直前に実行された SQL 文を参照します。
+, -, /, *, **
加算、減算、除算、乗算、指数の演算子を示す記号です。
||
連結演算子です。次の例に示すように、string1 と string2 を連結した結果は、string1 の後に
string2 が続く文字列になります。
'Good' || ' morning!'= 'Good morning!'
次の例では、NULL は連結の結果に影響しないことを示します。
'suit' || NULL || 'case' = 'suitcase'
長さが 0(ゼロ)の文字列('')は NULL 文字列と呼ばれ、NULL と同じように扱われます。
使用上の注意
ブール式では、互換性のあるデータ型を持つ値のみを比較できます。詳細は、3-20 ページの
「PL/SQL データ型の変換」を参照してください。
条件制御文においてブール式が TRUE を戻すと、関連する一連の文が実行されます。ただし、
式が FALSE または NULL を戻すと、関連する一連の文は実行されません。
関係演算子は、BOOLEAN 型のオペランドに適用できます。定義によれば、TRUE は FALSE より
も大きい値を持ちます。NULL の関係する比較は、常に NULL を戻します。ブール式の値は
ブール変数にしか代入できず、ホスト変数やデータベースの列には代入できません。また、
BOOLEAN 型からの、または BOOLEAN 型へのデータ型変換はできません。
次の例に示すように、加算演算子または減算演算子を使用すると、日付値を増減できます。
hire_date := '10-MAY-95';
hire_date := hire_date + 1;
hire_date := hire_date - 5;
-- makes hire_date '11-MAY-95'
-- makes hire_date '06-MAY-95'
PL/SQL がブール式を評価する場合は、優先順位が最も高いのが NOT 演算子で、次が AND 演算
子、最後が OR 演算子です。ただし、カッコを使用すると、演算子のデフォルトの優先順位を
変更できます。
式の中では、事前定義の優先順位に従って演算が実行されます。デフォルトの演算順序を、優
先順位の高いものから順に示すと、次のようになります。
カッコ
指数
単項演算子
乗算および除算
加算、減算および連結
PL/SQL では、優先順位の等しい演算子を評価する順序は特に決まっていません。ある式の一
部にカッコで囲まれた別の式が含まれている場合、PL/SQL では、カッコで囲まれた式を先に
評価し、その結果の値を外側の式で使用します。カッコで囲まれた式がネストされている場合、
PL/SQL では、最も内側にある式を 1 番目に評価し、最も外側にある式を最後に評価します。
13-50
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
式定義
例
式の例を次に示します。
(a + b) > c
NOT finished
TO_CHAR(acct_no)
'Fat ' || 'cats'
'15-NOV-05'
MONTHS_BETWEEN(d1, d2)
pi * r**2
emp_cv%ROWCOUNT
---------
Boolean expression
Boolean expression
character expression
character expression
date expression
date expression
numeric expression
numeric expression
1-6 ページの例 1-2「代入演算子を使用した変数への値の代入」を参照してください。
関連項目
「代入文」(13-3 ページ)
「定数と変数の宣言」(13-24 ページ)
「EXIT 文」(13-43 ページ)
「IF 文」(13-63 ページ)
「LOOP 文」
(13-71 ページ)
PL/SQL の言語要素
13-51
FETCH 文
FETCH 文
FETCH 文は、複数行の問合せの結果セットから、行データを取り出します。一度に 1 行、複数
の行、またはすべての行をフェッチできます。データは問合せが選択した列に対応する変数ま
たはフィールドに格納されます。詳細は、6-14 ページの「PL/SQL を使用したデータの問合せ」
を参照してください。
構文
fetch statement ::=
cursor_name
FETCH
cursor_variable_name
:
host_cursor_variable_name
,
variable_name
INTO
record_name
;
collection_name
BULK
COLLECT
,
LIMIT
numeric_expression
INTO
:
host_array_name
キーワードとパラメータの説明
BULK COLLECT
コレクションを PL/SQL エンジンに戻す前にバルク・バインド出力するように、SQL エンジン
に指示します。SQL エンジンは、INTO リスト内で参照されるすべてのコレクションをバルク・
バインドします。
collection_name
バルク・フェッチした列値を格納するための、宣言されたコレクションを識別します。問合せ
select_item ごとに、リストの中に、対応する型互換のコレクションが存在している必要が
あります。
cursor_name
現行の有効範囲の中で宣言されている明示カーソルを識別します。
cursor_variable_name
現行の有効範囲の中で宣言されている PL/SQL カーソル変数(またはパラメータ)を識別しま
す。
host_array_name
バルク・フェッチした列値を格納するための配列を識別します。この配列は、PL/SQL ホスト
環境で宣言され、バインド変数として PL/SQL に渡されます。問合せ select_item ごとに、
リストの中に、対応する型互換の配列が存在している必要があります。ホスト配列には、接頭
辞としてコロンが必要です。
13-52
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
FETCH 文
host_cursor_variable_name
PL/SQL ホスト環境で宣言され、バインド変数として PL/SQL に渡されるカーソル変数を識別
します。ホスト・カーソル変数のデータ型は、PL/SQL カーソル変数の戻り型と互換性があり
ます。ホスト変数には、接頭辞としてコロンを付けてください。
LIMIT
バルク(スカラーではない)FETCH 文の中でのみ許されるオプションの句です。結果セット全
体ではなく、一度にいくつかの行をバルク・フェッチします。
record_name
フェッチした行の値を格納する、ユーザー定義のレコードまたは %ROWTYPE レコードを識別し
ます。カーソルまたはカーソル変数に関連付けられた問合せが戻す列の値に対して、レコード
の中に、対応する型互換のフィールドが存在している必要があります。
variable_name
フェッチした列値を格納するための変数を識別します。カーソルまたはカーソル変数に関連付
けられた問合せが戻す列の値に対して、リストの中に、対応する型互換の変数が存在している
必要があります。
使用上の注意
複数行の問合せを処理するには、カーソル FOR ループか FETCH 文を使用します。
問合せの WHERE 句に含まれる変数は、カーソルまたはカーソル変数がオープンされたときにの
み評価されます。結果セットや問合せの中の変数の値を変更するには、カーソルまたはカーソ
ル変数を、新しい値に設定して再オープンする必要があります。
カーソルを再オープンするには、まずクローズしてください。ただし、カーソル変数を再オー
プンする場合には、その前にクローズする必要はありません。
同じカーソルまたはカーソル変数を使用した別のフェッチで、異なる INTO リストを使用でき
ます。個の FETCH 文で別の行を取り出し、ターゲット変数に値を代入します。
結果セットの中に行が残っていない状態で FETCH 文を実行すると、ターゲット・フィールドの
値またはターゲット変数の値は予測不能となり、%NOTFOUND 属性は TRUE を戻します。
PL/SQL では、カーソル変数の戻り型が、必ず FETCH 文の INTO 句と互換性を持ちます。カー
ソル変数に関連付けられた問合せが戻す列の値に対して、INTO 句の中に、対応する、型互換性
のあるフィールドまたは変数が存在している必要があります。また、フィールドまたは変数の
数は、列の値の数と一致する必要があります。
カーソル変数を、そのカーソル変数からフェッチするサブプログラムの仮パラメータとして宣
言する場合は、IN または IN OUT モードを指定する必要があります。ただし、サブプログラム
がカーソル変数もオープンする場合は、IN OUT モードを指定する必要があります。
一連の FETCH 文では取り出すデータが常に不足するため、FETCH がデータを戻さない場合で
も例外は呼び出されません。この状態を検出するには、カーソル属性 %FOUND または
%NOTFOUND を使用する必要があります。
クローズしている、または一度もオープンされていないカーソルまたはカーソル変数から
フェッチを実行すると、PL/SQL によって事前定義の例外 INVALID_CURSOR が呼び出されま
す。
BULK COLLECT の制限
BULK COLLECT 句には、次の制限が適用されます。
■
■
キーが文字列型の結合配列に対しては BULK COLLECT を使用できません。
BULK COLLECT 句はサーバー側(クライアント側ではなく)のプログラムの中でしか使用
できません。クライアント側で使用すると、
「この機能はクライアント側のプログラムでは
サポートされていません。
」というエラーが表示されます。
PL/SQL の言語要素
13-53
FETCH 文
■
■
■
■
BULK COLLECT INTO 句に示されるすべてのターゲット変数は、コレクションである必要が
あります。
コンポジット・ターゲット(オブジェクトなど)を RETURNING INTO 句で使用することは
できません。使用すると、
「RETURNING 句ではサポートされていない機能です。
」というエ
ラーが発生します。
暗黙的なデータ型変換が必要な場合、複数のコンポジット・ターゲットを BULK COLLECT
INTO 句で使用することはできません。
暗黙的なデータ型変換が必要な場合、コンポジット・ターゲットのコレクション(オブ
ジェクトのコレクションなど)を BULK COLLECT INTO 句で使用することはできません。
例
次の例を参照してください。
例 6-10「カーソルを使用したフェッチ」(6-9 ページ)
例 6-13「カーソルを使用したバルク・データのフェッチ」(6-11 ページ)
例 6-23「明示カーソルへのパラメータの引渡し」(6-18 ページ)
例 6-27「REF CURSOR のパラメータとしての引渡し」
(6-21 ページ)
例 6-32「カーソル変数からレコードへのフェッチ」(6-24 ページ)
例 6-33「カーソル変数からコレクションへのフェッチ」(6-24 ページ)
例 6-35「カーソル式の使用」(6-28 ページ)
例 6-41「CURRENT OF を使用した、カーソルからフェッチされた最新行の更新」
(6-33 ページ)
例 7-4「BULK COLLECT INTO 句を使用した動的 SQL」
(7-6 ページ)
例 13-1「宣言および変数への値の代入」(13-5 ページ)
関連項目
「CLOSE 文」(13-15 ページ)
「カーソル宣言」(13-32 ページ)
「カーソル変数」(13-29 ページ)
「LOOP 文」
(13-71 ページ)
「OPEN 文」(13-79 ページ)
「OPEN-FOR 文」
(13-81 ページ)
「RETURNING INTO 句」
(13-99 ページ)
13-54
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
FORALL 文
FORALL 文
FORALL 文は、一連の静的 DML 文または動的 DML 文を発行します。通常、FOR ループを使用
する場合より高速に処理を実行できます。この文には、いくつかの設定コードが必要です。こ
れは、ループが繰り返されるたびに、VALUES 句または WHERE 句内の 1 つ以上のコレクション
の値が使用されるためです。詳細は、11-8 ページの「バルク SQL による、DML 文および問合
せのループ・オーバーヘッドの削減」を参照してください。
構文
for all statement ::=
SAVE
FORALL
index_name
IN
bounds_clause
EXCEPTIONS
sql_statement
;
bounds_clause ::=
lower_bound
..
upper_bound
BETWEEN
INDICES
OF
collection
VALUES
OF
index_collection
lower_bound
AND
upper_bound
キーワードとパラメータの説明
INDICES OF collection_name
索引変数の値が指定したコレクション要素の添字に対応するように指定する句です。この句を
使用すると、いくつかの要素が削除されたネストした表、または数値の添字を持つ結合配列で、
FORALL を使用できます。
BETWEEN lower_bound AND upper_bound
INDICES OF 句の添字の範囲を制限します。範囲内の添字がコレクションに存在しない場合、
その添字はスキップされます。
VALUES OF index_collection_name
FORALL 索引変数の添字に、index_collection_name で指定した別のコレクションの要素
の値が使用されるように指定する句です。ここで使用する別のコレクションは、ポインタの
セットとして機能します。index_collection_name で指定する要素に応じて、FORALL は
任意の順序で添字に対する反復処理を実行できます(同じ添字を複数回使用することもできま
す)
。
索引コレクションは、ネストした表であるか、または PLS_INTEGER か BINARY_INTEGER に
よって索引付けされ、要素も PLS_INTEGER か BINARY_INTEGER である結合配列である必要
があります。索引コレクションが空の場合、例外が呼び出され、FORALL 文は実行されません。
index_name
コレクションの添字として、FORALL 文の中でのみ参照できる、未宣言の識別子です。
index_name の暗黙的な宣言は、ループの外側での宣言をオーバーライドします。文の中では
同じ名前の別の変数を参照できません。FORALL 文の中では、index_name は式に使用したり
値を代入できません。
PL/SQL の言語要素
13-55
FORALL 文
lower_bound .. upper_bound
連続した索引番号の有効範囲を指定する数式です。必要に応じて、PL/SQL はこれらの番号を
最も近い整数に四捨五入します。SQL エンジンは、範囲内の各索引番号に対して一度ずつ SQL
文を実行します。この式は、FORALL 文を入力すると、一度評価されます。
SAVE EXCEPTIONS
一部の DML 操作が失敗しても FORALL ループを継続させるオプションのキーワードです。プ
ログラムでは、例外をただちに呼び出すのではなく、FORALL 文の終了後に例外を 1 つ呼び出
します。エラーの詳細は、SQL%BULK_EXCEPTIONS でループの後に取得できます。プログラム
では、発生するたびに例外を個別に処理するのではなく、FORALL ループの後ですべてのエ
ラーをレポートまたはクリーンアップできます。11-13 ページの「%BULK_EXCEPTIONS 属性
を持つ FORALL 例外の処理」を参照してください。
sql_statement
VALUES 句または WHERE 句内のコレクション要素を参照する UPDATE または DELETE などの静
的 DML 文、あるいは動的(EXECUTE IMMEDIATE)DML 文です。
使用上の注意
SQL 文は複数のコレクションを参照できますが、パフォーマンス上のメリットは、添字付きコ
レクションにのみ適用されます。
FORALL 文が失敗すると、データベースの変更は、各 SQL 文の実行の前にマークされた暗黙的
なセーブポイントまでロールバックされます。前回の FORALL ループの反復中に行われた変更
はロールバックされません。
制限
FORALL 文には、次の制限が適用されます。
■
■
■
■
■
■
■
■
■
13-56
キーが文字列型の結合配列の要素は、ループできません。
FORALL ループ内では、UPDATE 文の SET 句と WHERE 句の両方で、同じコレクションを参
照することはできません。この場合は、そのコレクションの 2 つ目のコピーを作成し、
WHERE 句では新しい名前を参照する必要があります。
FORALL 文を使用できるのは、クライアント側ではなく、サーバー側のプログラム内のみ
です。
INSERT 文、UPDATE 文または DELETE 文では少なくとも 1 つのコレクションを参照する必
要があります。たとえば、ループで一連の定数値を挿入する FORALL 文では、例外が呼び
出されます。
明示的な範囲を指定する場合は、その範囲内のすべてのコレクション要素が存在している
必要があります。要素が存在しなかったり削除されていた場合は、エラーが発生します。
INDICES OF 句または VALUES OF 句を使用する場合、DML 文で参照されるすべてのコレ
クションの添字が、索引変数の値と一致している必要があります。DELETE、EXTEND など
の操作は、どのコレクションも同じ添字のセットを持つように、すべてのコレクションに
適用してください。参照されている要素がいずれかのコレクション内に存在しない場合は、
エラーが発生します。SAVE EXCEPTIONS 句を使用している場合、このエラーは他のエ
ラーと同じように扱われ、FORALL 文は停止されません。
FORALL 文によってコールされる DML 文内のレコード・フィールドを個別に参照すること
はできません。かわりに、UPDATE 文の SET ROW 句か、または INSERT 文の VALUES 句
でレコード全体を指定できます。
コレクションの添字は式(i+1 など)ではなく、索引変数(i など)である必要がありま
す。
カーソル属性 %BULK_ROWCOUNT は、他のコレクションに代入したり、パラメータとしてサ
ブプログラムに渡すことはできません。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
FORALL 文
例
次の例を参照してください。
例 11-2「ループでの DELETE 文の発行」(11-9 ページ)
例 11-3「ループでの INSERT 文の発行」(11-9 ページ)
例 11-4「コレクションの一部での FORALL の使用」
(11-10 ページ)
例 11-5「連続していない索引値での FORALL の使用」
(11-10 ページ)
例 11-9「例外が発生しても継続するバルク操作」
(11-14 ページ)
例 11-16「BULK COLLECT での FORALL の使用」(11-18 ページ)
関連項目
「BULK COLLECT 句を使用した、問合せ結果のコレクションへの取出し」(11-15 ページ)
PL/SQL の言語要素
13-57
ファンクション宣言
ファンクション宣言
ファンクションとは、パラメータを指定して単一の値を戻すことができるサブプログラムのこ
とです。ファンクションには、仕様部と本体の 2 つの部分があります。ファンクションの仕様
部はキーワード FUNCTION で始め、戻り値のデータ型を指定する RETURN 句で終わります。パ
ラメータ宣言はオプションです。パラメータを取らないファンクションではカッコを書きませ
ん。ファンクション本体は、キーワード IS(または AS)で始め、キーワード END で終わりま
す。END の後には、オプションとしてファンクション名を続けることができます。
ファンクション本体には、宣言部(オプション)
、実行部、例外処理部(オプション)の 3 つの
部分があります。宣言部には、型、カーソル、定数、変数、例外およびサブプログラムが含ま
れます。これらの項目はローカルで、ファンクションを終了すると消去されます。実行部には、
値の代入、実行の制御およびデータの操作を実行する文があります。例外処理部には、実行の
途中で呼び出された例外を処理する例外ハンドラがあります。詳細は、8-4 ページの「PL/SQL
ファンクション」を参照してください。ファンクション宣言の例は、9-6 ページの例 9-3 を参照
してください。
PL/SQL ブロックまたはパッケージでのファンクション宣言は、SQL でのファンクションの作
成とは異なります。SQL の CREATE FUNCTION 文の詳細は、
『Oracle Database SQL リファレン
ス』を参照してください。
構文
function specification ::=
,
(
FUNCTION
parameter_declaration
)
function_name
DETERMINISTIC
PARALLEL_ENABLE
RETURN
PIPELINED
datatype
;
function declaration ::=
,
(
FUNCTION
function_name
PIPELINED
RETURN
parameter_declaration
IS
datatype
AS
13-58
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
)
ファンクション宣言
function body ::=
PRAGMA
AUTONOMOUS_TRANSACTION
;
type_definition
function_body
item_body
procedure_body
BEGIN
EXCEPTION
exception_handler
statement
function_name
END
;
parameter declaration ::=
IN
NOCOPY
OUT
IN
parameter_name
OUT
datatype
:=
expression
DEFAULT
キーワードとパラメータの説明
datatype
型指定子です。datatype の構文は、13-24 ページの「定数と変数の宣言」を参照してくださ
い。
DETERMINISTIC
オプティマイザが冗長なファンクション・コールを回避するために役立つヒントです。ストア
ド・ファンクションが同じ引数で事前にコールされた場合は、オプティマイザは前の結果を使
用できます。ファンクションの結果をセッション変数の状態またはスキーマ・オブジェクトに
依存させないでください。さもないと、コールごとに結果が異なる可能性があります。
DETERMINISTIC ファンクションのみが、ファンクションベースの索引またはクエリー・リラ
イトを使用可能にしたマテリアライズド・ビューからコールできます。DETERMINISTIC オプ
ションの詳細および可能性がある制限は、
『Oracle Database SQL リファレンス』の「CREATE
FUNCTION 文」を参照してください。『Oracle Database SQL リファレンス』の「CREATE
INDEX 文」も参照してください。
exception_handler
例外ハンドラです。例外が呼び出されると、その例外に関連付けられた一連の文を実行します。
exception_handler の構文は、13-38 ページの「例外定義」を参照してください。
expression
変数、定数、リテラル、演算子、ファンクション・コールの任意の組合せです。最も単純な式
は、1 個の変数で構成されています。宣言が PL/SQL コンパイラによって処理されるときに、
expression の値がパラメータに代入されます。その値とパラメータのデータ型には互換性が
必要です。
PL/SQL の言語要素
13-59
ファンクション宣言
function_name
ファンクションに選択する名前を指定します。
IN、
、OUT、
、IN OUT
仮パラメータの動作を定義するパラメータ・モードです。IN パラメータは、コールされるサブ
プログラムに値を渡します。OUT パラメータは、サブプログラムのコール元に値を戻します。
IN OUT パラメータは、コール先のサブプログラムに初期値を渡し、更新された値をコール元に
戻します。
item_declaration
プログラム・オブジェクトを宣言します。構文は、13-8 ページの「ブロック宣言」を参照して
ください。
NOCOPY
コンパイラ・ヒント(ディレクティブではなく)です。これによって、PL/SQL コンパイラは
OUT および IN OUT パラメータを、デフォルトの値方式ではなく、参照方式で渡すことができ
ます。このファンクションは、これらのパラメータの一時コピーを作成する必要がないため、
高速で実行できます。ただし、ファンクションが未処理例外を戻して終了すると、結果が異な
る場合があります。詳細は、8-9 ページの「サブプログラムのパラメータのデフォルト値の使
用」を参照してください。
PARALLEL_ENABLE
ストアド・ファンクションがパラレル DML 評価のスレーブ・セッションで安全に使用される
ことを宣言します。メイン(ログオン)
・セッションの状態が、スレーブ・セッションと共有さ
れることはありません。スレーブ・セッションごとに固有の状態があり、セッション開始時に
初期化されます。ファンクションの結果がセッション(static)変数の状態に依存しないよう
にしてください。さもないと、セッションごとに結果が異なる可能性があります。
PARALLEL_ENABLE オプションの詳細は、
『Oracle Database SQL リファレンス』の「CREATE
FUNCTION 文」を参照してください。
parameter_name
仮パラメータを識別します。仮パラメータとは、ファンクションの仕様部で宣言され、ファン
クション本体の中で参照される変数のことです。
PIPELINED
PIPELINED は、テーブル・ファンクションの結果を反復的に戻すことを指定します。テーブ
ル・ファンクションは、SQL データ型の要素を含むコレクション型(ネストした表または
VARRAY)を戻します。SQL 問合せの FROM 句のファンクション名の前に TABLE キーワードを
使用して、テーブル・ファンクションを問い合せることができます。詳細は、11-31 ページの
「パイプライン・ファンクションによる変換の設定」を参照してください。
AUTONOMOUS_TRANSACTION プラグマ
ファンクションを自律型としてマークします。自律型トランザクションは、メイン・トランザ
クションによって開始される独立したトランザクションです。自律型トランザクションを使用
すると、メイン・トランザクションを停止し、SQL 操作を実行してその操作をコミットまたは
ロールバックしてから、メイン・トランザクションを再開できます。詳細は、6-35 ページの
「自律型トランザクションによる独立した作業単位の実行」を参照してください。
procedure_declaration
プロシージャを宣言します。procedure_declaration の構文は、13-89 ページの「プロシー
ジャ宣言」を参照してください。
13-60
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
ファンクション宣言
RETURN
RETURN 句の開始を知らせるキーワードです。この句では、戻り値のデータ型を定義します。
type_definition
ユーザー定義のデータ型を指定します。構文は、13-8 ページの「ブロック宣言」を参照してく
ださい。
:= | DEFAULT
IN パラメータをデフォルト値に初期化します。
使用上の注意
ファンクションは、式の一部としてコールされます。
promotable := sal_ok(new_sal, new_title) AND (rating > 3);
ストアド・ファンクションは、副作用を制御する特定の規則に従っている場合にのみ、SQL 文
からコールできます。8-23 ページの「PL/SQL サブプログラムの副作用の制御」を参照してく
ださい。
ファンクションには、RETURN 文へ導く少なくとも 1 つの実行パスが必要です。実行パスがな
い場合は、実行時に「ファンクションが値なしで戻されました」というエラーが発生します。
RETURN 文には、RETURN 文の実行時に評価される式が含まれている必要があります。結果と
して得られる値がファンクション識別子に代入されます。ファンクション識別子は変数のよう
に取り扱われます。
ファンクションの仕様部と本体を合わせて 1 つの単位として作成できます。また、ファンク
ションの仕様部と本体を別にすることもできます。このように、ファンクションをパッケージ
に入れると、実装上の細部を隠ぺいできます。パッケージ仕様部でファンクション仕様部を宣
言せずに、パッケージ本体でファンクションを定義できます。ただし、このようなファンク
ションは、パッケージの中からのみコールできます。
ファンクションの中では、IN パラメータは定数のように取り扱われるため、値は代入できませ
ん。OUT パラメータはローカル変数のように取り扱われるため、値を変更して参照できます。
IN OUT パラメータは初期化された変数のように取り扱われるため、値を代入したり、その値を
他の変数に代入できます。パラメータ・モードの詳細は、8-9 ページの表 8-1 を参照してくださ
い。
ファンクションでは、OUT モードと IN OUT モードを使用しないでください。ファンクション
の目的は、0(ゼロ)個以上のパラメータを取り、単一の値を戻すことです。サブプログラム専
用ではない変数の値を変更するという副作用も避ける必要があります。
例
次の例を参照してください。
例 1-13「パッケージおよびパッケージ本体の作成」(1-13 ページ)
例 2-15「名前解決でのサブプログラムの使用」(2-14 ページ)
例 2-27「CASE 文での検索条件の使用」(2-26 ページ)
例 5-44「ファンクションからレコードを戻す」(5-30 ページ)
例 6-43「パッケージでの自律型ファンクションの宣言」(6-36 ページ)
例 6-48「自律型ファンクションのコール」(6-40 ページ)
例 9-3「emp_admin パッケージの作成」
(9-6 ページ)
関連項目
「パッケージ宣言」(13-84 ページ)
「プロシージャ宣言」(13-89 ページ)
PL/SQL の言語要素
13-61
GOTO 文
GOTO 文
GOTO 文は、文ラベルまたはブロック・ラベルに無条件に分岐します。ラベルは有効範囲の中で
他と重複しないもので、実行可能文か PL/SQL ブロックの前に置かれている必要があります。
GOTO 文によって、制御はラベルの付いた文またはブロックに移ります。詳細は、4-13 ページ
の「GOTO 文の使用」を参照してください。
構文
label declaration ::=
<<
label_name
>>
goto statement ::=
GOTO
label_name
;
キーワードとパラメータの説明
label_name
実行可能文または PL/SQL ブロックに付けるラベル名です。GOTO 文を使用すると、
<<label_name>> の後に指定した文またはブロックに制御を移すことができます。
使用上の注意
GOTO 文のラベルは、実行可能文か PL/SQL ブロックの前に付けてください。GOTO 文は IF
文、LOOP 文またはサブブロックには分岐できません。実行可能文のない場所へ分岐するには、
NULL 文を追加します。
GOTO 文では、カレント・ブロックから同じブロックの別の場所、または囲みブロックには分岐
できますが、例外ハンドラには分岐できません。例外ハンドラの GOTO 文は、囲みブロックに
は分岐できますが、カレント・ブロックには分岐できません。
GOTO 文を使用してカーソル FOR ループを途中で終了させると、カーソルは自動的にクローズ
されます。ループの内側で例外が呼び出された場合も、カーソルは自動的にクローズされます。
ある 1 つのブロックの中では、1 つのラベルは一度のみ使用できます。ただし、囲みブロック
やサブブロックなどの他のブロックでそのラベルを使用できます。ターゲット・ラベルがカレ
ント・ブロックにない場合、GOTO 文は囲みブロックのうちそのラベルが存在する最初のものに
分岐します。
例
次の例を参照してください。
例 4-19「簡単な GOTO 文の使用」
(4-13 ページ)
例 4-21「GOTO 文を使用した外側のブロックへの分岐」(4-14 ページ)
13-62
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
IF 文
IF 文
IF 文を使用すると、ブール式の値に応じて、一連の文を実行するか、またはスキップできま
す。詳細は、4-2 ページの「条件テスト : IF 文および CASE 文」を参照してください。
構文
if statement ::=
IF
boolean_expression
ELSIF
ELSE
THEN
boolean_expression
statement
THEN
statement
statement
END
IF
;
キーワードとパラメータの説明
boolean_expression
TRUE、FALSE または NULL のいずれかのブール値を戻す式です。たとえば、等価、以上、未満
などの比較があります。THEN キーワードに続く一連の文は、式が TRUE を戻した場合にのみ
実行されます。
ELSE
制御がこのキーワードに達すると、その直後の一連の文が実行されます。以前の条件テストが
いずれも TRUE を戻さなかった場合に発生します。
ELSIF
以前の条件がいずれも TRUE を戻さなかった場合に評価されるブール式の開始を知らせます。
THEN
式が TRUE を戻した場合、THEN キーワードの後の文が実行されます。
使用上の注意
IF 文には、IF-THEN、IF-THEN-ELSE および IF-THEN-ELSIF の 3 つの形式があります。IF
文の最も単純な形式では、ブール式を、キーワード THEN と END IF で囲まれた一連の文に関連
付けます。一連の文は、式が TRUE を戻す場合にのみ実行されます。式が FALSE または NULL
を戻す場合、IF 文は何も実行しません。いずれの場合も、制御は次の文に渡されます。
IF 文の 2 つ目の形式では、キーワード ELSE が追加され、その後に一連の代替文を続けます。
ブール式が FALSE または NULL を戻す場合にのみ、ELSE 句内の一連の文が実行されます。こ
のように、ELSE 句では必ず一連の文が実行されます。
IF 文の 3 つ目の形式では、キーワード ELSIF を使用して別のブール式を追加します。最初の
式が FALSE または NULL を戻す場合、ELSIF 句は別の式を評価します。IF 文は任意の数の
ELSIF 句を持つことができます。最後の ELSE 句はオプションです。ブール式は上から下に 1
つずつ評価されます。いずれかの式が TRUE を戻す場合は、それに関連する一連の文が実行さ
れ、制御は次の文に移ります。すべての式が FALSE または NULL を戻す場合は、ELSE 句内の
一連の文が実行されます。
PL/SQL の言語要素
13-63
IF 文
一連の文が 1 つでも実行されると、IF 文の処理は終了します。このため、一連の文が複数回実
行されることはありません。ただし、THEN 句と ELSE 句には、さらに IF 文を入れることがで
きます。つまり、IF 文はネストできます。
例
例 13-3 に、IF-THEN-ELSIF-ELSE 文の例を示します。
例 13-3 IF 文の使用
DECLARE
jobid
employees.job_id%TYPE;
empid
employees.employee_id%TYPE := 115;
sal_raise NUMBER(3,2);
BEGIN
SELECT job_id INTO jobid from employees WHERE employee_id = empid;
IF jobid = 'PU_CLERK' THEN sal_raise := .09;
ELSIF jobid = 'SH_CLERK' THEN sal_raise := .08;
ELSIF jobid = 'ST_CLERK' THEN sal_raise := .07;
ELSE sal_raise := 0;
END IF;
END;
/
次の例を参照してください。
例 1-7「IF-THEN_ELSE 文および CASE 文を使用した条件制御」(1-10 ページ)
例 4-1「単純な IF-THEN 文の使用」(4-2 ページ)
例 4-2「単純な IF-THEN-ELSE 文の使用」
(4-3 ページ)
例 4-3「IF 文のネスト」(4-3 ページ)
例 4-4「IF-THEN-ELSEIF 文の使用」
(4-4 ページ)
関連項目
「条件テスト : IF 文および CASE 文」(4-2 ページ)
「CASE 文」
(13-13 ページ)
「式定義」(13-44 ページ)
13-64
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
INSERT 文
INSERT 文
INSERT 文は、データベース表に 1 つ以上の新しい行データを追加します。INSERT 文の詳細
は、
『Oracle Database SQL リファレンス』を参照してください。
構文
insert statement ::=
table_reference
INSERT
INTO
(
subquery
TABLE
(
alias
)
subquery2
)
,
(
column_name
)
,
VALUES
(
sql_expression
returning_clause
)
;
subquery3
キーワードとパラメータの説明
alias
参照される表またはビューの別名(通常は短縮名)です。
column_name[, column_name]...
データベースの表またはビューの列のリストを識別します。VALUES 句の式が同じ順序でリス
トに示されているかぎり、列はどのような順序で指定してもかまいません。各列の名前はリス
トの中で一度のみ指定できます。表の列のうち、リストに含まれていないものがある場合、そ
れらの列はそれぞれ NULL、または CREATE TABLE 文で指定されたデフォルト値に設定されま
す。
returning_clause
挿入された行から値を戻します。そのため、後で行を SELECT で選択する必要がありません。
取り出した列値は、変数またはコレクションに代入できます。RETURNING 句はリモートまたは
パラレルでの挿入には使用できません。文を実行しても行に影響がない場合、RETURNING 句で
指定した変数の値は未定義になります。returning_clause の構文は、13-99 ページの
「RETURNING INTO 句」を参照してください。
sql_expression
任意の有効な SQL の式です。たとえば、リテラル、PL/SQL 変数、単一の値を戻す SQL 問合
せなどがあります。詳細は、
『Oracle Database SQL リファレンス』を参照してください。
PL/SQL では、ここでレコード変数も使用できます。
subquery
処理する行セットを提供する SELECT 文です。構文は select_into_statement の構文と似
ていますが、INTO 句は使用できません。13-105 ページの「SELECT INTO 文」を参照してくだ
さい。
PL/SQL の言語要素
13-65
INSERT 文
subquery3
行セットを戻す SELECT 文です。この SELECT 文によって戻された各行が、表に挿入されま
す。この副問合せは、列リストのすべての列について値を戻す必要があります。また、列リス
トが存在しない場合は、表の中のすべての列について値を戻す必要があります。
table_reference
表またはビューを指定します。指定された表またはビューは、INSERT 文の実行時にアクセス
できる必要があり、ユーザーは INSERT 権限を持つ必要があります。table_reference の構
文は、13-35 ページの「DELETE 文」を参照してください。
TABLE (subquery2)
TABLE のオペランドは、1 つの列値を戻す SELECT 文です。これはネストした表を表します。
この演算子は、値がスカラー値ではなくコレクションになるように指定します。
VALUES (...)
式の値を、列リストの中の対応する列に代入します。列リストが指定されていない場合、最初
の値は CREATE TABLE 文で定義された最初の列に、2 番目の値は 2 番目の列に、というように
挿入されます。列リストの中では、各列につき指定できる値は 1 つです。挿入される値のデー
タ型は、列リストの対応する列のデータ型との互換性が必要です。
使用上の注意
VALUES リストの中の文字リテラルと日付リテラルは、引用符(')で囲む必要があります。数
値リテラルは引用符で囲みません。
暗黙的な SQL カーソルとカーソル属性 %NOTFOUND、%FOUND、%ROWCOUNT および %ISOPEN
を使用すると、INSERT 文の実行に関する有用な情報にアクセスできます。
例
次の例を参照してください。
例 6-1「PL/SQL を使用したデータ操作」
(6-2 ページ)
例 6-5「CURRVAL と NEXTVAL の使用」
(6-4 ページ)
例 6-7「SQL%FOUND の使用」(6-7 ページ)
例 6-37「ROLLBACK の使用」
(6-30 ページ)
例 6-38「ROLLBACK と SAVEPOINT の併用」
(6-30 ページ)
例 6-46「自律型トリガーの宣言」(6-37 ページ)
例 6-48「自律型ファンクションのコール」(6-40 ページ)
例 7-1「動的 SQL の例」(7-3 ページ)
例 9-3「emp_admin パッケージの作成」
(9-6 ページ)
関連項目
「DELETE 文」(13-35 ページ)
「SELECT INTO 文」(13-105 ページ)
「UPDATE 文」(13-119 ページ)
13-66
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
リテラル宣言
リテラル宣言
リテラルは、識別子によって表現する必要がない明示的な数値、文字、文字列またはブール値
です。たとえば、数値リテラル 135 や文字列リテラル 'hello world' などです。詳細は、2-5
ページの「リテラル」を参照してください。
構文
numeric literal ::=
+
–
integer
real_number
integer literal ::=
digit
real number literal ::=
+
.
integer
E
–
integer
integer
.
e
.
integer
character literal ::=
’
character
’
’’
string literal ::=
’
character
’
’’
boolean literal ::=
TRUE
FALSE
NULL
PL/SQL の言語要素
13-67
リテラル宣言
キーワードとパラメータの説明
character
PL/SQL キャラクタ・セットのメンバーです。詳細は、2-2 ページの「キャラクタ・セットおよ
び字句単位」を参照してください。
digit
数字 0 ~ 9 のうちのいずれかです。
TRUE、
、FALSE、
、NULL
事前定義のブール値です。
使用上の注意
算術式では、整数と実数の数値リテラルを使用できます。数値リテラルは、句読点文字で区切
る必要があります。句読点以外に空白も使用できます。詳細は、2-5 ページの「数値リテラル」
を参照してください。
文字リテラルは引用符(アポストロフィ)で囲まれた 1 文字のことです。文字リテラルには、
PL/SQL キャラクタ・セットのすべての印刷可能文字(英字、数字、空白および特殊記号)を
使用できます。文字リテラルの中で、PL/SQL は大 / 小文字を区別します。たとえば、
PL/SQL はリテラル 'Q' と 'q' を異なるものとみなします。詳細は、2-6 ページの「文字リテ
ラル」を参照してください。
文字列リテラルは、引用符(')で囲まれた 0(ゼロ)個以上の文字の並びです。NULL 文字列
('')は 0(ゼロ)個の文字です。文字列リテラルは最大 32,767 個の文字を保持できます。文
字列リテラルの中で、PL/SQL は大 / 小文字を区別します。たとえば、PL/SQL はリテラル
'white' と 'White' を異なるものとみなします。
文字列の中でアポストロフィを表現する場合は、引用符(')を 1 つではなく、2 つ入力します。
引用符を 2 つ入力すると不都合があるか、またはわかりにくくなるリテラルでは、q'esc_char
... esc_char' という表記法を使用して、エスケープ文字を指定できます。このエスケープ文字
は、その文字列の他の箇所では使用されていない必要があります。
文字列リテラルの中では、値に後続する空白が意味を持ちます。つまり、'abc' と 'abc ' は
異なります。文字列リテラルの中の後続する空白は、PL/SQL の処理中には切り捨てられませ
んが、表の CHAR 型の列にその値を挿入すると切り捨てられます。NCHAR 文字列リテラルを含
む詳細は、2-6 ページの「文字列リテラル」を参照してください。
ブール値 TRUE および FALSE はデータベース列に挿入できません。詳細は、2-7 ページの
「ブール・リテラル」を参照してください。
例
次に数値リテラルの例を示します。
25
6.34
7E2
25e-03
.1
1.
+17
-4.4
-4.5D
-4.6F
次に文字リテラルの例を示します。
'H'
'&'
' '
'9'
']'
'g'
次に文字列リテラルの例を示します。
'$5,000'
'02-AUG-87'
'Don''t leave until you''re ready and I''m ready.'
q'#Don't leave until you're ready and I'm ready.#'
13-68
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
リテラル宣言
次の例を参照してください。
例 2-3「日時リテラルの使用」
(2-7 ページ)
例 2-34「データベースのバージョンでの条件付きコンパイルの使用」(2-34 ページ)
関連項目
「定数と変数の宣言」(13-24 ページ)
「式定義」(13-44 ページ)
「リテラル」(2-5 ページ)
PL/SQL の言語要素
13-69
LOCK TABLE 文
LOCK TABLE 文
LOCK TABLE 文は、データベース表全体を指定のロック・モードでロックします。これによっ
て、表の整合性を維持したまま、表アクセスの共有や拒否ができます。詳細は、6-34 ページの
「LOCK TABLE の使用」を参照してください。
Oracle には、複数のプログラムで、一貫性のあるデータのビューを個別に参照してデータの読
取りと書込みを同時に実行できる様々な自動機能が備わっています。そのため、ほとんどの場
合、ユーザーが表をロックする必要はありません。SQL の LOCK TABLE 文の詳細は、『Oracle
Database SQL リファレンス』を参照してください。
構文
lock table statement ::=
NOWAIT
LOCK
TABLE
table_reference
IN
lock_mode
MODE
;
キーワードとパラメータの説明
table_reference
ロックする対象の表またはビューです。LOCK TABLE 文を実行する場合は、この表または
ビューがアクセス可能である必要があります。table_reference の構文は、13-35 ページの
「DELETE 文」を参照してください。
lock_mode
ロックのタイプを指定します。これは、ROW SHARE、ROW EXCLUSIVE、SHARE UPDATE、
SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE のいずれかです。
NOWAIT
これはオプションのキーワードであり、これを指定すると Oracle は他のユーザーが表をロック
していると待機しません。制御はただちにプログラムに戻されるため、他の処理を実行してか
ら、改めてロックを試みてください。
使用上の注意
キーワード NOWAIT を省略すると、Oracle は表が利用できるようになるまで待ちます。待機時
間に制限はありません。表ロックは、トランザクションがコミットまたはロールバックを発行
したときに解除されます。表がロックされていても、他のユーザーは表に対して問合せできま
すが、問合せを実行しても表のロックを取得できません。プログラムに SQL ロッキング文が含
まれている場合は、ロックを要求している Oracle ユーザーが、ロックのために必要な権限を
持っていることを確認してください。DBA は、任意の表をロックできます。他のユーザーは、
自分が所有する表か、SELECT、INSERT、UPDATE、DELETE などの権限が付与されている表を
ロックできます。
例
次の文は、NOWAIT オプションを使用して、employees 表を行共有モードでロックします。
LOCK TABLE employees IN ROW SHARE MODE NOWAIT;
関連項目
「COMMIT 文」(13-23 ページ)
「ROLLBACK 文」(13-101 ページ)
13-70
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
LOOP 文
LOOP 文
LOOP 文は一連の文を複数回実行します。LOOP キーワードと END LOOP キーワードで文を囲
みます。PL/SQL では、基本ループ、WHILE ループ、FOR ループ、カーソル FOR ループの 4 種
類がサポートされています。使用方法は、4-7 ページの「ループの反復の制御 : LOOP 文と
EXIT 文」を参照してください。
構文
loop statement ::=
<<
label_name
>>
label_name
LOOP
statement
END
LOOP
;
while loop statement ::=
<<
label_name
>>
WHILE
boolean_expression
label_name
LOOP
statement
END
LOOP
;
for loop statement ::=
<<
label_name
>>
FOR
index_name
IN
REVERSE
lower_bound
..
upper_bound
label_name
LOOP
statement
END
LOOP
;
cursor for loop statement ::=
<<
label_name
>>
FOR
record_name
IN
,
(
cursor_parameter_name
)
cursor_name
(
select_statement
)
label_name
LOOP
statement
END
LOOP
;
PL/SQL の言語要素
13-71
LOOP 文
キーワードとパラメータの説明
basic_loop_statement
回数の制限なしに実行するループです。LOOP キーワードと END LOOP キーワードで一連の文を
囲みます。ループが繰り返されるたびに一連の文が実行され、制御がループの先頭に戻ります。
EXIT、GOTO または RAISE 文は、ループの外に分岐します。例外が呼び出された場合もループ
は終了します。
boolean_expression
TRUE、FALSE または NULL のいずれかのブール値を戻す式です。式が TRUE を戻す場合にのみ
実行される一連の文が関連付けられています。boolean_expression の構文は、13-44 ページ
の「式定義」を参照してください。
cursor_for_loop_statement
SQL 問合せを発行し、結果セットの行をループします。この手法を使用すると、問合せの処理
が、他のプログラミング言語でテキスト行を読み取る場合と同様に簡単になります。
カーソル FOR ループは、ループ索引を %ROWTYPE 属性のレコードとして暗黙的に宣言し、カー
ソルをオープンして、結果セットから行の値をフェッチしてレコード内のフィールドに入れる
一連の作業を繰り返し、すべての行を処理した後にカーソルをクローズします。
cursor_name
現行の有効範囲の中で、事前に宣言されている明示カーソルを識別します。カーソル FOR ルー
プに入ると、cursor_name は、OPEN 文または外側のカーソル FOR ループによって、すでに
オープンされたカーソルを参照できません。
cursor_parameter_name
カーソルの仮パラメータとして宣言された変数を識別します。
cursor_parameter_declaration の構文は、13-32 ページの「カーソル宣言」を参照してく
ださい。カーソルのパラメータは、問合せの中で定数が使用できる場所であれば、どこででも
使用できます。カーソルの仮パラメータは IN パラメータにしてください。
for_loop_statement
数値の FOR_LOOP ループは、指定された整数の範囲内でループを繰り返し実行します。繰返し
の範囲は、キーワード FOR と LOOP に囲まれた反復スキームの一部です。
繰返しの範囲は FOR ループに入った段階で評価され、それ以降は評価されません。ループ本体
は、lower_bound..upper_bound によって定義された範囲の整数 1 つにつき 1 回実行されま
す。1 回の繰返しが終わると、ループ索引に増分が加えられます。
index_name
ループ索引に名前を付ける未宣言の識別子です(ループ・カウンタと呼ばれる場合もありま
す)
。有効範囲はループ自体になるため、ループの外側では索引を参照できません。
index_name の暗黙的な宣言は、ループの外側での宣言をオーバーライドします。同じ名前の
別の変数を参照するには、次のようにラベルを使用します。4-12 ページの例 4-15「ループの外
で変数を参照する場合のラベルの使用」を参照してください。
ループの内側では、索引は定数のように扱われるため、式の中で使用できます。ただし、値は
代入できません。
label_name
オプションとしてループに付けるラベル名で、未宣言の識別子です。label_name を使用する
場合は、二重の山カッコで囲み、ループの先頭に置く必要があります。必要に応じて、
label_name を山カッコで囲まずにループの最後に置くこともできます。
13-72
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
LOOP 文
label_name を EXIT 文の中で使用すると、label_name によってラベル付けされているルー
プを終了できます。カレント・ループのみでなく、外側のループも終了できます。
外側の FOR ループと、その内側のネストされた FOR ループの索引が同じ名前である場合、ネス
トされたループから外側のループの索引を参照できません。ただし、外側のループが
label_name でラベル付けされている場合は、次のようにドット表記法を使用すれば参照でき
ます。4-12 ページの例 4-16「ループのラベルを使用した参照」を参照してください。
lower_bound .. upper_bound
数値を戻す式です。それ以外の場合、PL/SQL は事前定義の例外 VALUE_ERROR を呼び出しま
す。式は、最初にループに入ったときにのみ評価されます。下限は 1 である必要はありません。
FOR i IN -5..10 のように負の整数にすることができます。ループ・カウンタの増分値(ま
たは減分値)は 1 である必要があります。
内部的に、PL/SQL は PLS_INTEGER 一時変数に境界の値を代入します。さらに、必要に応じ
てその値を最も近い整数に四捨五入します。PLS_INTEGER の大きさの範囲は、32 ビットで表
すと、-2147483648 ~ 2147483647 です。範囲外の数値を評価した場合、PL/SQL が代入をする
と、数値オーバーフローのエラーが発生します。3-4 ページの「PLS_INTEGER データ型」を参
照してください。
デフォルトでは、ループ索引には lower_bound の値が代入されます。この値が
upper_bound の値を超えていない場合、ループの中の一連の文が実行され、索引が増分され
ます。索引の値が upper_bound の値を超えていない場合、一連の文がもう一度実行されます。
この処理は、索引の値が upper_bound の値を超えるまで繰り返されます。下回った時点で、
ループが終了します。
record_name
暗黙的に宣言されたレコードを識別します。このレコードは cursor_name または
select_statement によって取り出された行と同じ構造を持ちます。
レコードはループの内側のみで定義されています。ループの外側からこのレコードのフィール
ドを参照できません。record_name の暗黙的な宣言は、ループの外側での宣言をオーバーラ
イドします。同じ名前のレコードは、ブロック・ラベルを使用して参照を修飾しないかぎり、
ループの内側から参照できません。
レコード中のフィールドには、暗黙のうちにフェッチされた行の列値が格納されます。フィー
ルドの名前とデータ型は、対応する列の名前とデータ型と同じです。フィールドの値にアクセ
スするには、次のようにドット表記法を使用します。
record_name.field_name
FOR ループのカーソルによってフェッチされた選択項目の名前は、単純名にしてください。ま
た、それらが式である場合は、別名を持つ必要があります。次の例では、選択項目
salary+NVL(commission_pct,0)*1000 の別名として wages を指定しています。
CURSOR c1 IS SELECT employee_id,
salary + NVL(commission_pct,0) * 1000 wages FROM employees ...
REVERSE
デフォルトでは、反復は、範囲の下限から上限に上向きに進みます。キーワード REVERSE を
使用すると、反復は上限から下限に下向きに進みます。次に例を示します。
BEGIN
FOR i IN REVERSE 1..10 LOOP -- i starts at 10, ends at 1
DBMS_OUTPUT.PUT_LINE(i); -- statements here execute 10 times
END LOOP;
END;
/
PL/SQL の言語要素
13-73
LOOP 文
ループ索引には upper_bound の値が割り当てられます。この値が lower_bound の値を下
回っていない場合、ループの中の一連の文が実行され、索引が減分されます。索引の値がまだ
lower_bound の値を下回っていない場合、一連の文がもう一度実行されます。この処理は、
索引の値が lower_bound の値を下回るまで繰り返されます。下回った時点で、ループが終了
します。
select_statement
使用不可能な内部カーソルに関連付けられた問合せです。構文は select_into_statement
の構文と似ていますが、INTO 句は使用できません。13-105 ページの「SELECT INTO 文」を参
照してください。PL/SQL は内部カーソルを自動的に宣言し、オープンし、データをフェッチ
してクローズします。select_statement は独立した文ではないため、暗黙カーソル SQL は
適用されません。
while_loop_statement
WHILE-LOOP 文は、ブール式を、キーワード LOOP と END LOOP で囲まれた一連の文に関連付
けます。ループを反復する前に条件が評価されます。式が TRUE を戻す場合、一連の文が実行
されてから、ループの先頭で制御が再開します。式が FALSE または NULL を戻す場合、ループ
は実行されず、制御は次の文に渡されます。
使用上の注意
EXIT WHEN 文を使用すると、任意のループを途中で終了できます。WHEN 句の中のブール式が
TRUE を戻す場合、ループはただちに終了します。
カーソル FOR ループを終了すると、EXIT 文または GOTO 文を使用してループを途中で終了し
た場合でも、カーソルは自動的にクローズされます。ループの内側で例外が呼び出された場合
も、カーソルは自動的にクローズされます。
例
次の例を参照してください。
例 4-18「LOOP でのラベル付き EXIT の使用」
(4-13 ページ)
例 6-10「カーソルを使用したフェッチ」(6-9 ページ)
例 6-13「カーソルを使用したバルク・データのフェッチ」(6-11 ページ)
関連項目
「ループの反復の制御 : LOOP 文と EXIT 文」
(4-7 ページ)
「カーソル宣言」(13-32 ページ)
「EXIT 文」(13-43 ページ)
「FETCH 文」
(13-52 ページ)
「OPEN 文」(13-79 ページ)
13-74
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
MERGE 文
MERGE 文
MERGE 文は、一部の行の挿入と他の行の更新を 1 回の操作で行います。ターゲット表に対して
更新と挿入のどちらを行うかは、結合条件に基づいて決定されます。つまり、ターゲット表の
うち結合条件と一致する既存の行は更新され、それ以外の場合は別個の副問合せからの値を使
用して 1 行が挿入されます。
MERGE 文の詳細と例は、『Oracle Database SQL リファレンス』を参照してください。
使用上の注意
この文は、主として大量のデータが頻繁に挿入および更新されるデータ・ウェアハウスの場合
に有効です。単一の行のみを挿入または更新する必要がある場合は、通常の PL/SQL で処理を
実行する方が効率的です。行の更新を試みて、更新される行がない場合はかわりに挿入を行い、
行の挿入を試みて、表がすでにその主キーを含んでいるために例外が呼び出された場合はかわ
りに更新を行います。
PL/SQL の言語要素
13-75
NULL 文
NULL 文
NULL 文は、制御を次の文に渡す以外は何もしません。IF-THEN 句、ループまたはプロシー
ジャの本体で、NULL 文はプレースホルダの役割を果たします。詳細は、4-15 ページの「NULL
文の使用」を参照してください。
構文
null statement ::=
NULL
;
使用上の注意
NULL 文には、条件文の意味とアクションを明確にすることによって、コードをわかりやすくす
る効果があります。読み手に対して、代替アクションを誤って見逃したのではなく、アクショ
ンが不要であると判断したことを伝えることができます。
IF 文、例外ハンドラなどの PL/SQL の特定の句には、1 つ以上の実行可能文が必要です。
NULL 文を使用すると、アクションを実行することなく、これらの構造体をコンパイルできま
す。
次の文が実行可能文ではなく、END、END IF などであるため、GOTO 文で特定の場所に分岐で
きない場合があります。この場合、分岐する場所に NULL 文を置くことができます。
NULL 文とブール値 NULL は無関係です。
例
次の例を参照してください。
例 1-12「ストアド・サブプログラムの作成」(1-13 ページ)
例 1-16「レコード型の宣言」(1-16 ページ)
例 4-20「GOTO をラベルに使用するために NULL を使用」
(4-14 ページ)
例 4-22「アクションを起こさないことを明示する NULL 文の使用」
(4-15 ページ)
例 4-23「サブプログラム作成時のプレースホルダとしての NULL の使用」
(4-15 ページ)
関連項目
「順次制御 : GOTO 文と NULL 文」(4-13 ページ)
13-76
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
オブジェクト型宣言
オブジェクト型宣言
オブジェクト型は、データの操作に必要なファンクションおよびプロシージャとともにデータ
構造をカプセル化するユーザー定義の複合データ型です。データ構造を形成する変数は、属性
と呼ばれます。オブジェクト型の動作を特徴付けるファンクションとプロシージャはメソッド
と呼ばれます。コンストラクタと呼ばれる特殊な種類のメソッドは、オブジェクト型の新規イ
ンスタンスを作成し、その属性を記入します。
オブジェクト型は、SQL で作成し、Oracle データベースに格納して、多くのプログラムで共有
できるようにする必要があります。CREATE TYPE 文を使用してオブジェクト型を定義する場合
は、実世界のオブジェクトに対応する抽象テンプレートを作成します。テンプレートでは、ア
プリケーション環境でオブジェクトに必要な属性と動作を指定します。SQL の CREATE TYPE
文の詳細は、
『Oracle Database SQL リファレンス』を参照してください。SQL の CREATE
TYPE BODY 文の詳細は、
『Oracle Database SQL リファレンス』を参照してください。
属性の集合によって形成されるデータ構造はパブリック(クライアント・プログラムから参照
可能)です。ただし、優れたプログラムは、データ構造を直接操作しません。かわりに、提供
される一連のメソッドを使用します。その結果、データは常に適切な状態に保たれます。
オブジェクト型の詳細は、
『Oracle Database アプリケーション開発者ガイド - オブジェクト・
リレーショナル機能』を参照してください。オブジェクト型での PL/SQL の使用方法の詳細
は、第 12 章「PL/SQL のオブジェクト型の使用」を参照してください。
使用上の注意
オブジェクト型をスキーマに作成すると、任意の PL/SQL ブロック、サブプログラムまたは
パッケージの中で、それを使用してオブジェクトを宣言できます。たとえば、そのオブジェク
ト型を使用すると、オブジェクト属性、表の列、PL/SQL 変数、バインド変数、レコード・
フィールド、コレクション要素、プロシージャの仮パラメータまたはファンクション結果の
データ型を指定できます。
パッケージと同様に、オブジェクト型は仕様部と本体の 2 つの部分から構成されます。仕様部
はアプリケーションへのインタフェースです。ここでは、データ構造(属性の集合)とデータ
操作に必要な演算(メソッド)を宣言します。本体ではメソッドを完全に定義し、それによっ
て仕様部を実装します。
メソッドを使用するためにクライアント・プログラムが必要とするすべての情報は、仕様部に
あります。仕様部は操作インタフェース、そして本体はブラック・ボックスと考えてください。
仕様部を変更しなくても、本体をデバッグ、拡張または置換できます。
オブジェクト型はデータと操作をカプセル化します。属性とメソッドはオブジェクト型仕様部
で宣言できますが、定数、例外、カーソル、型は宣言できません。少なくとも 1 つの属性が必
要です(最大で 1000)。メソッドはオプションです。
オブジェクト型の仕様部では、メソッドより前にすべての属性を宣言する必要があります。サ
ブプログラムのみが実装を必要とします。オブジェクト型の仕様部に属性およびコール仕様の
宣言のみがある場合、またはそのいずれかの宣言のみがある場合、オブジェクト型本体は不要
です。本体では属性を宣言できません。オブジェクト型の仕様部のすべての宣言は、パブリッ
ク(オブジェクト型の外側から参照可能)です。
属性は、オブジェクト型内の位置によってではなく、名前によってのみ参照できます。属性に
アクセスしたり、その値を変更するには、ドット表記法を使用します。属性名を連鎖させて、
ネストされたオブジェクト型の属性にアクセスできます。
オブジェクト型の中でメソッドは、修飾子なしで属性および他のメソッドを参照できます。
SQL 文からパラメータのないメソッドをコールするには、空のパラメータ・リストが必要で
す。プロシージャ文では、コールを連鎖しないかぎり空のパラメータ・リストはなくてもかま
いません。連鎖する場合は、最後のコール以外のすべてのコールで空のパラメータ・リストが
必要です。
PL/SQL の言語要素
13-77
オブジェクト型宣言
SQL 文からは、NULL インスタンス(SELF が NULL である状態)で MEMBER メソッドをコー
ルすると、メソッドは起動されず NULL が戻されます。プロシージャ文からは、NULL インス
タンスで MEMBER メソッドをコールすると、メソッドが起動される前に事前定義の例外
SELF_IS_NULL が呼び出されます。
マップ・メソッドかオーダー・メソッドを宣言できますが、その両方は宣言できません。どち
らかのメソッドを宣言すれば、オブジェクトを SQL 文およびプロシージャ文によって比較でき
ます。ただし、どちらのメソッドも宣言しなければ、オブジェクトは SQL 文でのみ比較し、し
かも比較できるのは等しいか等しくないかについてのみです。同じ型の 2 つのオブジェクトが
等しいとされるのは、それらの対応する属性の値が等しい場合のみです。
パッケージ化されたサブプログラムと同じく、同じ種類(ファンクションまたはプロシージャ)
のメソッドはオーバーロードできます。つまり、仮パラメータの数、順序、またはデータ型の
種類が違っていれば、同じ名前を複数の異なるメソッドで使用できます。
どのオブジェクト型にもデフォルト・コンストラクタ・メソッド(略してコンストラクタ)が
あります。このコンストラクタは、そのオブジェクト型と同じ名前のシステム定義のファンク
ションです。コンストラクタは、そのオブジェクト型のインスタンスを初期化したり、そのイ
ンスタンスを戻すために使用します。異なるパラメータのセットを受け入れる独自のコンスト
ラクタ・メソッドを定義することもできます。PL/SQL は、暗黙的にコンストラクタをコール
することはないため、明示的にコールする必要があります。コンストラクタは、ファンクショ
ン・コールが許可されているところでコールできます。
関連項目
「ファンクション宣言」(13-58 ページ)
「パッケージ宣言」(13-84 ページ)
「プロシージャ宣言」(13-89 ページ)
13-78
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
OPEN 文
OPEN 文
OPEN 文は、カーソルに関連付けられた問合せを実行します。また、問合せの処理に使用する
データベース・リソースを割り当て、結果セット(問合せの条件に一致する行)を識別します。
カーソルは、結果セットの最初の行の前に置かれます。詳細は、6-14 ページの「PL/SQL を使
用したデータの問合せ」を参照してください。
構文
open statement ::=
,
(
OPEN
cursor_name
cursor_parameter_name
)
;
キーワードとパラメータの説明
cursor_name
現行の有効範囲のうちそれより前に宣言されていて、現在オープンされていない明示カーソル
です。
cursor_parameter_name
カーソルの仮パラメータとして宣言された変数を識別します。
(cursor_parameter_declaration の構文は、13-32 ページの「カーソル宣言」を参照して
ください。
)カーソルのパラメータは、問合せの中で定数が使用できる場所であれば、どこでで
も使用できます。
使用上の注意
一般に、PL/SQL による明示カーソルは、それを最初にオープンするときにのみ解析されます。
また、SQL 文の解析(およびそれによる暗黙カーソルの作成)は、その文が初めて実行される
ときにのみ行われます。解析された SQL 文は、すべてキャッシュに入れられます。SQL 文は、
新しい SQL 文によってキャッシュからエージ・アウトされた場合にのみ再解析されます。した
がって、カーソルを再オープンするには、まずクローズする必要がありますが、PL/SQL は
カーソルに関連付けられた SELECT 文を再解析する必要はありません。カーソルをクローズし
てからただちに再オープンした場合、再解析は不要です。
結果セットの中の行は、OPEN 文の実行時には取り出されません。行の取出しには FETCH 文を
使用します。FOR UPDATE カーソルでは、カーソルがオープンされるときに、行はロックされ
ます。
仮パラメータが宣言されている場合は、カーソルに実パラメータを渡す必要があります。カー
ソルの仮パラメータは IN パラメータにする必要があるため、実パラメータに値を戻すことは
できません。実パラメータの値はカーソルをオープンする場合に使用されます。仮パラメータ
と実パラメータのデータ型には、互換性が必要です。問合せでは、有効範囲の中で宣言されて
いる他の PL/SQL 変数を参照することもできます。
デフォルト値を受け入れるのでなければ、カーソル宣言の中の仮パラメータは、すべて OPEN
文の中で対応する実パラメータを持つ必要があります。デフォルト値で宣言された仮パラメー
タの詳細は、対応する実パラメータがなくてもかまいません。このような仮パラメータは、
OPEN 文の実行時にデフォルト値を取ります。
位置表記法または名前表記法を使用して、OPEN 文の実パラメータを、カーソル宣言の仮パラ
メータに関連付けることができます。
カーソルがオープンされている場合は、そのカーソルの名前をカーソル FOR ループで使用でき
ません。
PL/SQL の言語要素
13-79
OPEN 文
例
次の例を参照してください。
例 6-10「カーソルを使用したフェッチ」(6-9 ページ)
例 6-13「カーソルを使用したバルク・データのフェッチ」(6-11 ページ)
例 13-1「宣言および変数への値の代入」(13-5 ページ)
関連項目
「CLOSE 文」(13-15 ページ)
「カーソル宣言」(13-32 ページ)
「FETCH 文」
(13-52 ページ)
「LOOP 文」
(13-71 ページ)
13-80
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
OPEN-FOR 文
OPEN-FOR 文
OPEN-FOR 文は、カーソル変数に関連付けられている問合せを実行します。また、問合せの処
理に使用するデータベース・リソースを割り当て、結果セット(問合せの条件を満たす行)を
識別します。カーソル変数は、結果セットの中の最初の行の前に配置します。詳細は、6-19
ページの「カーソル変数(REF CURSOR)の使用」を参照してください。
オプションの USING 句を使用して、カーソル変数を問合せに関連付けて、問合せを実行し、結
果セットを識別してカーソルを結果セットの最初の行の前に配置してから、%ROWCOUNT によっ
て保持される処理行カウントを 0(ゼロ)に設定します。詳細は、7-7 ページの「動的 SQL を
使用した動的問合せの構築」を参照してください。OPEN-FOR-USING 文は、バインド変数を使
用して SQL の処理効率を向上させることができるため、WHERE 句が事前に判明している問合せ
を構築する場合は、この文を使用します。WHERE 句の数が不明な動的問合せを処理するために
柔軟性が必要な場合は、OPEN-FOR 文を使用します。
構文
open for statement ::=
using_clause
cursor_variable_name
OPEN
FOR
:
select_statement
;
host_cursor_variable_name
using clause ::=
IN
OUT
IN_OUT
USING
,
bind_argument
キーワードとパラメータの説明
bind_argument
動的 SELECT 文に渡される値を持つ式です。
cursor_variable_name
現行の有効範囲のうちそれより前に宣言されているカーソル変数またはパラメータ(戻り型を
持たない)です。
host_cursor_variable_name
PL/SQL ホスト環境で事前に宣言され、バインド変数として PL/SQL に渡されるカーソル変数
を識別します。ホスト・カーソル変数のデータ型は、PL/SQL カーソル変数の戻り型と互換性
があります。ホスト変数には、接頭辞としてコロンを付けてください。
select_statement
cursor_variable に関連付けられた問合せです。一連の値を戻します。問合せでは、バイン
ド変数、PL/SQL 変数、パラメータ、ファンクションを参照できます。select_statement
の構文は、13-105 ページの「SELECT INTO 文」で定義されている select_into_statement
の構文に似ていますが、select_statement カーソルでは、INTO 句は使用できません。動的
文字列の長さは 32767K 以下にしてください。
PL/SQL の言語要素
13-81
OPEN-FOR 文
USING 句
バインド引数のリストを指定するオプションの句です。実行時に、USING 句のバインド引数は
動的 SELECT 文内の対応するプレースホルダを置き換えます。
使用上の注意
OCI や Pro*C プログラムなどの PL/SQL ホスト環境で、カーソル変数を宣言できます。ホス
ト・カーソル変数をオープンするには、バインド変数として無名 PL/SQL ブロックに渡しま
す。OPEN-FOR 文をグループにまとめることで、ネットワークの通信量を削減できます。たと
えば、次の PL/SQL ブロックは、1 回の往復で 5 つのカーソル変数をオープンしています。
/* anonymous PL/SQL block in host environment */
BEGIN
OPEN :emp_cv FOR SELECT * FROM employees;
OPEN :dept_cv FOR SELECT * FROM departments;
OPEN :grade_cv FOR SELECT * FROM salgrade;
OPEN :pay_cv FOR SELECT * FROM payroll;
OPEN :ins_cv FOR SELECT * FROM insurance;
END;
その他の OPEN-FOR 文は、異なる複数の問合せ用に同じカーソル変数をオープンできます。
カーソル変数を再オープンする場合、その前にクローズする必要はありません。別の問合せ用
にカーソル変数を再オープンすると、前の問合せは失われます。
カーソルとは異なり、カーソル変数はパラメータを取りません。かわりに、カーソル変数には
パラメータのみでなく問合せ全体を渡すことができます。カーソル変数は、PL/SQL ストア
ド・プロシージャまたはファンクションによってオープンして、コール元のサブプログラムに
戻すことができますが、コール元とコール先のサブプログラムは同じインスタンス上に存在す
る必要があります。データベース・リンクを介してコールされたプロシージャおよびファンク
ションに、カーソル変数を渡したり、戻すことはできません。カーソル変数を、そのカーソル
変数をオープンするサブプログラムの仮パラメータとして宣言する場合は、IN OUT モードを指
定する必要があります。この指定によって、サブプログラムはコール元にオープン・カーソル
を渡すことができます。
動的な複数行の問合せを処理するには、OPEN-FOR-USING 文、FETCH 文および CLOSE 文の 3
つの文を使用します。まず、OPEN-FOR 文でカーソル変数を複数行問合せ用にオープンします。
次に、FETCH 文で結果セットから行を取り出します。すべての行が処理された後に、CLOSE 文
でカーソル変数をクローズします。
動的文字列には、任意の複数行 SELECT 文(終了記号を持たない)を含むことができます。ま
た、バインド引数のプレースホルダも含めることができます。ただし、バインド引数を使用し
てスキーマ・オブジェクトの名前を動的 SQL 文に渡すことはできません。
動的文字列内のすべてのプレースホルダは、USING 句内のバインド引数に関連付ける必要があ
ります。USING 句内では数値リテラル、文字リテラル、および文字列リテラルは使用できます
が、ブール・リテラル(TRUE、FALSE、NULL)は使用できません。動的文字列に NULL を渡
すには、回避策を使用する必要があります。7-10 ページの「動的 SQL への NULL の引渡し」
を参照してください。
カーソル変数がオープンしている場合にのみ、問合せの中のバインド引数が評価されます。異
なるバインド値を使用してカーソルからフェッチするには、新しい値に設定されたバインド引
数でカーソル変数を再オープンする必要があります。
動的 SQL はすべての SQL データ型をサポートしています。たとえば、バインド引数をコレク
ション、LOB、オブジェクト型のインスタンスおよび ref とすることができます。通常、動的
SQL は PL/SQL 固有の型をサポートしていません。たとえばバインド引数をブールまたは索引
付き表にできません。
13-82
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
OPEN-FOR 文
例
次の例を参照してください。
例 6-27「REF CURSOR のパラメータとしての引渡し」
(6-21 ページ)
例 6-29「REF CURSOR をオープンするストアド・プロシージャ」
(6-22 ページ)
例 6-30「別の問合せで REF CURSOR をオープンするストアド・プロシージャ」(6-22 ページ)
例 6-31「異なる戻り型を持つカーソル変数」(6-23 ページ)
例 6-32「カーソル変数からレコードへのフェッチ」(6-24 ページ)
例 6-33「カーソル変数からコレクションへのフェッチ」(6-24 ページ)
例 7-9「レコードへの動的 SQL フェッチ」(7-12 ページ)
関連項目
「CLOSE 文」(13-15 ページ)
「カーソル変数」(13-29 ページ)
「EXECUTE IMMEDIATE 文」
(13-40 ページ)
「FETCH 文」
(13-52 ページ)
「LOOP 文」
(13-71 ページ)
PL/SQL の言語要素
13-83
パッケージ宣言
パッケージ宣言
パッケージとは、論理的に関連する PL/SQL の型、項目およびサブプログラムをグループにま
とめたスキーマ・オブジェクトのことです。再利用の可能性がある Application Program
Interface(API)を構成する一連の関連サブプログラムを作成する場合にパッケージを使用しま
す。パッケージには、仕様部と本体の 2 つの部分があります。詳細は、第 9 章「PL/SQL パッ
ケージの使用」を参照してください。パッケージ宣言の例は、9-6 ページの例 9-3 を参照してく
ださい。
この項では、PL/SQL のパッケージ仕様部とパッケージ本体のオプションについて説明します。
SQL の CREATE PACKAGE 文の詳細は、
『Oracle Database SQL リファレンス』を参照してくだ
さい。SQL の CREATE PACKAGE BODY 文の詳細は、『Oracle Database SQL リファレンス』を参
照してください。
構文
package specification ::=
PRAGMA
SERIALLY_REUSABLE
;
collection_type_definition
record_type_definition
subtype_definition
collection_declaration
constant_declaration
exception_declaration
package_name
object_declaration
END
record_declaration
variable_declaration
cursor_spec
function_spec
procedure_spec
call_spec
PRAGMA
13-84
RESTRICT_REFERENCES
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
;
パッケージ宣言
package body ::=
PRAGMA
SERIALLY_REUSABLE
;
collection_type_definition
record_type_definition
subtype_definition
collection_declaration
constant_declaration
exception_declaration
BEGIN
statement
object_declaration
package_name
END
;
record_declaration
variable_declaration
cursor_body
function_body
procedure_body
call_spec
キーワードとパラメータの説明
call_spec
Oracle データ・ディクショナリ内の外部 C ファンクションまたは Java メソッドを発行します。
これは、対応する SQL に名前、パラメータ型および戻り型をマップすることによって、ルーチ
ンを発行します。詳細は、
『Oracle Database Java 開発者ガイド』および『Oracle Database アプ
リケーション開発者ガイド - 基礎編』を参照してください。
collection_declaration
コレクション(ネストした表、索引付き表または VARRAY)を宣言します。
collection_declaration の構文は、13-16 ページの「コレクション定義」を参照してくだ
さい。
collection_type_definition
データ型指定子 TABLE または VARRAY を使用してコレクション型を定義します。
constant_declaration
定数を宣言します。constant_declaration の構文は、13-24 ページの「定数と変数の宣言」
を参照してください。
cursor_body
明示カーソルの基盤となる実装を定義します。cursor_body の構文は、13-32 ページの「カー
ソル宣言」を参照してください。
cursor_spec
明示カーソルへのインタフェースを宣言します。cursor_spec の構文は、13-32 ページの
「カーソル宣言」を参照してください。
PL/SQL の言語要素
13-85
パッケージ宣言
exception_declaration
例外を宣言します。exception_declaration の構文は、13-38 ページの「例外定義」を参照
してください。
function_body
ファンクションを実装します。function_body の構文は、13-58 ページの「ファンクション宣
言」を参照してください。
function_spec
ファンクションへのインタフェースを宣言します。function_spec の構文は、13-58 ページの
「ファンクション宣言」を参照してください。
object_declaration
オブジェクト(オブジェクト型のインスタンス)を宣言します。object_declaration の構
文は、13-77 ページの「オブジェクト型宣言」を参照してください。
package_name
データベースに格納されたパッケージを識別します。ネーミング規則は、2-3 ページの「識別
子」を参照してください。
pragma_restrict_refs
純正規則に違反していないか確認できるプラグマです。ファンクションは、副作用を制御する
規則に従っている場合にのみ、SQL 文からコールできます。ファンクション本体内の SQL 文が
規則に違反すると、実行時(文が解析されるとき)にエラーが発生します。プラグマの構文は、
13-96 ページの「RESTRICT_REFERENCES プラグマ」を参照してください。
プラグマは、ファンクションがデータベース表またはパッケージ変数(あるいはその両方)に
対する読込みや書込み、またはそのいずれも行っていないことを示します。純正規則と
RESTRICT_REFERENCES プラグマの詳細は、『Oracle Database アプリケーション開発者ガイド
- 基礎編』を参照してください。
PRAGMA SERIALLY_REUSABLE
サーバーへの 1 コール(サーバーへの OCI コール、サーバー間のリモート・プロシージャ・
コールなど)の間のみパッケージを逐次再使用可能な状態にする必要がある場合は、パッケー
ジに逐次再使用可能とマークします。詳細は、
『Oracle Database アプリケーション開発者ガイ
ド - 基礎編』を参照してください。
procedure_body
プロシージャを実装します。procedure_body の構文は、13-89 ページの「プロシージャ宣
言」を参照してください。
procedure_spec
プロシージャへのインタフェースを宣言します。procedure_spec の構文は、13-89 ページの
「プロシージャ宣言」を参照してください。
record_declaration
ユーザー定義のレコードを宣言します。record_declaration の構文は、13-93 ページの「レ
コード定義」を参照してください。
record_type_definition
データ型指定子 RECORD または属性 %ROWTYPE を使用してレコード型を定義します。
13-86
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
パッケージ宣言
schema_name
パッケージが含まれているスキーマを識別します。schema_name を省略すると、パッケージ
はユーザーのスキーマ内に存在するとみなされます。
variable_declaration
変数を宣言します。variable_declaration の構文は、13-24 ページの「定数と変数の宣言」
を参照してください。
使用上の注意
PL/SQL をサポートする Oracle のツール製品を使用すると、パッケージを作成し、それを
Oracle データベース内に格納できます。CREATE PACKAGE および CREATE PACKAGE BODY 文
は、Oracle プリコンパイラか OCI ホスト・プログラムから、または SQL*Plus から対話形式で
発行できます。ただし、パッケージは、PL/SQL ブロックまたはサブプログラムの中では定義
できません。
通常、パッケージには仕様部と本体があります。仕様部はアプリケーションへのインタフェー
スです。ここでは、使用できる型、変数、定数、例外、カーソル、サブプログラムなどを宣言
します。本体ではカーソルとサブプログラムを完全に定義し、仕様を実装します。
下位の実装を持つのは、サブプログラムとカーソルのみです。仕様部で宣言されているのが型、
定数、変数、例外およびコール仕様のみであれば、パッケージ本体は不要です。ただしその場
合でも、次のようにパッケージ本体を使用して、仕様部で宣言した項目を初期化できます。
CREATE OR REPLACE PACKAGE emp_actions AS
-additional code here ...
number_hired INTEGER;
END emp_actions;
/
CREATE OR REPLACE PACKAGE BODY emp_actions AS
BEGIN
number_hired := 0;
END emp_actions;
/
仕様部は本体がなくてもコーディングし、コンパイルできます。仕様部のコンパイルが終了す
ると、そのパッケージを参照するストアド・サブプログラムもコンパイルできます。アプリ
ケーション作成の最終段階になるまで、パッケージ本体を完全に定義する必要はありません。
パッケージ本体は、パッケージ仕様部を変更せずに、デバッグ、拡張または置換できます。そ
のため、パッケージをコールするサブプログラムを再コンパイルする必要はありません。
パッケージ仕様部で宣言したカーソルとサブプログラムは、パッケージ本体で定義する必要が
あります。パッケージ仕様部で宣言したその他のプログラム項目は、パッケージ本体で再宣言
できません。
サブプログラムの仕様部と本体を一致させるために、PL/SQL は、それらのヘッダーをトーク
ンごとに比較します。このため、空白を除いて、ヘッダーは一語一語が一致している必要があ
ります。一致していない場合は、PL/SQL によって例外が呼び出されます。
パッケージで宣言された変数は、セッションを通じてその値が保持されます。そのため、1 つ
のプロシージャでパッケージ変数の値を設定して、その値を別のプロシージャで取り出すこと
ができます。
例
次の例を参照してください。
例 1-13「パッケージおよびパッケージ本体の作成」(1-13 ページ)
例 6-43「パッケージでの自律型ファンクションの宣言」(6-36 ページ)
例 9-3「emp_admin パッケージの作成」
(9-6 ページ)
例 9-4「DBMS_OUTPUT パッケージでの PUT_LINE の使用」
(9-9 ページ)
例 12-18「オブジェクト型とコレクションの動的 SQL を使用した TEAMS パッケージ」
(12-11
ページ)
PL/SQL の言語要素
13-87
パッケージ宣言
関連項目
「コレクション定義」(13-16 ページ)
「カーソル宣言」(13-32 ページ)
「例外定義」(13-38 ページ)
「ファンクション宣言」(13-58 ページ)
「プロシージャ宣言」(13-89 ページ)
「レコード定義」(13-93 ページ)
13-88
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
プロシージャ宣言
プロシージャ宣言
プロシージャとは、パラメータを指定してコールできるサブプログラムのことです。一般に、
プロシージャはアクションを実行するために使用します。プロシージャには、仕様部と本体の
2 つの部分があります。仕様部は、キーワード PROCEDURE で始め、プロシージャ名またはパラ
メータ・リストで終わります。パラメータ宣言はオプションです。パラメータを取らないプロ
シージャではカッコを書きません。プロシージャの本体は、キーワード IS(または AS)で始
め、キーワード END で終わります。END の後には、オプションとしてプロシージャ名を続け
ることができます。
プロシージャ本体には、宣言部(オプション)
、実行部、例外処理部(オプション)の 3 つの部
分があります。宣言部には、型、カーソル、定数、変数、例外およびサブプログラムが含まれ
ます。これらの項目はローカルで、プロシージャを終了すると消去されます。実行部には、値
の代入、実行の制御および Oracle データの操作を実行する文があります。例外処理部には、実
行の途中で呼び出された例外を処理する例外ハンドラがあります。詳細は、8-3 ページの
「PL/SQL プロシージャ」を参照してください。プロシージャ宣言の例は、9-6 ページの例 9-3
を参照してください。
PL/SQL ブロックまたはパッケージでのプロシージャ宣言は、SQL でのプロシージャの作成と
は異なります。SQL の CREATE PROCEDURE 文の詳細は、
『Oracle Database SQL リファレンス』
を参照してください。
構文
procedure specification ::=
,
(
PROCEDURE
parameter_declaration
)
procedure_name
;
procedure declaration ::=
,
(
PROCEDURE
parameter_declaration
)
IS
procedure_name
AS
procedure body ::=
PRAGMA
AUTONOMOUS_TRANSACTION
;
type_definition
function_declaration
item_declaration
procedure_declaration
BEGIN
EXCEPTION
exception_handler
statement
procedure_name
END
;
PL/SQL の言語要素
13-89
プロシージャ宣言
parameter declaration ::=
IN
NOCOPY
OUT
IN
OUT
parameter_name
datatype
:=
expression
DEFAULT
キーワードとパラメータの説明
datatype
型指定子です。datatype の構文は、13-24 ページの「定数と変数の宣言」を参照してくださ
い。
exception_handler
例外ハンドラです。例外が呼び出されると、その例外に関連付けられた一連の文を実行します。
exception_handler の構文は、13-38 ページの「例外定義」を参照してください。
expression
変数、定数、リテラル、演算子、ファンクション・コールの組合せです。最も単純な式は、1
個の変数で構成されています。宣言が PL/SQL コンパイラによって処理されるときに、
expression の値がパラメータに代入されます。その値とパラメータのデータ型には互換性が
必要です。
function_declaration
ファンクションを宣言します。function_declaration の構文は、13-58 ページの「ファン
クション宣言」を参照してください。
IN、
、OUT、
、IN OUT
仮パラメータの動作を定義するパラメータ・モードです。IN パラメータは、コールされるサブ
プログラムに値を渡します。OUT パラメータは、サブプログラムのコール元に値を戻します。
IN OUT パラメータは、コール先のサブプログラムに初期値を渡して、更新された値をコール元
に戻します。
item_declaration
プログラム・オブジェクトを宣言します。item_declaration の構文は、13-8 ページの「ブ
ロック宣言」を参照してください。
NOCOPY
コンパイラ・ヒント(ディレクティブではなく)です。これによって、PL/SQL コンパイラは
OUT および IN OUT パラメータを、デフォルトの値方式ではなく、参照方式で渡すことができ
ます。詳細は、8-8 ページの「サブプログラムのパラメータのモードの指定」を参照してくださ
い。
parameter_name
仮パラメータを識別します。仮パラメータとは、プロシージャの仕様部で宣言され、プロシー
ジャ本体の中で参照される変数のことです。
13-90
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
プロシージャ宣言
AUTONOMOUS_TRANSACTION プラグマ
ファンクションを自律型としてマークします。自律型トランザクションは、メイン・トランザ
クションによって開始される独立したトランザクションです。自律型トランザクションを使用
すると、メイン・トランザクションを停止し、SQL 操作を実行してその操作をコミットまたは
ロールバックしてから、メイン・トランザクションを再開できます。詳細は、6-35 ページの
「自律型トランザクションによる独立した作業単位の実行」を参照してください。
procedure_name
ユーザー定義のプロシージャです。
type_definition
ユーザー定義のデータ型を指定します。type_definition の構文は、13-8 ページの「ブロッ
ク宣言」を参照してください。
:= | DEFAULT
プロシージャがコールされたときに IN パラメータに値が指定されていない場合、IN パラメー
タをデフォルト値に初期化します。
使用上の注意
プロシージャは PL/SQL 文としてコールされます。たとえば、次のようにプロシージャ
raise_salary をコールできます。
raise_salary(emp_num, amount);
プロシージャの中では、IN パラメータは定数のように取り扱われるため、値は代入できませ
ん。OUT パラメータはローカル変数のように取り扱われるため、値を変更して参照できます。
IN OUT パラメータは初期化された変数のように取り扱われるため、値を代入したり、その値を
他の変数に代入できます。パラメータ・モードの概要は、8-9 ページの表 8-1 を参照してくださ
い。
OUT パラメータおよび IN OUT パラメータとは異なり、IN パラメータはデフォルト値に初期化
できます。詳細は、8-9 ページの「サブプログラムのパラメータのデフォルト値の使用」を参照
してください。
プロシージャを終了する前に、すべての OUT 仮パラメータに明示的に値を代入してください。
OUT 実パラメータには、サブプログラムがコールされる前にも値を入れることができます。た
だし、サブプログラムをコールした時点で、値は失われます(コンパイラ・ヒント NOCOPY を
指定しない場合、またはサブプログラムを未処理例外で終了しない場合)
。
プロシージャの仕様部と本体を合わせて 1 つの単位として作成できます。また、プロシージャ
の仕様部と本体を別にすることもできます。このように、プロシージャをパッケージに入れる
と、実装上の細部を隠ぺいできます。パッケージ仕様部でプロシージャ仕様部を宣言せずに、
パッケージ本体でプロシージャを定義できます。ただし、このようなプロシージャはパッケー
ジの内側からのみコールできます。プロシージャの実行部には、少なくとも 1 つの文が存在し
ている必要があります。NULL 文はこの条件を満たします。
例
次の例を参照してください。
例 1-12「ストアド・サブプログラムの作成」(1-13 ページ)
例 1-13「パッケージおよびパッケージ本体の作成」(1-13 ページ)
例 1-14「パッケージのプロシージャのコール」(1-14 ページ)
例 9-3「emp_admin パッケージの作成」
(9-6 ページ)
関連項目
「コレクション・メソッド」(13-19 ページ)
「ファンクション宣言」(13-58 ページ)
「パッケージ宣言」(13-84 ページ)
PL/SQL の言語要素
13-91
RAISE 文
RAISE 文
RAISE 文は、PL/SQL ブロックまたはサブプログラムの通常の実行を停止させ、例外ハンドラ
に制御を移します。
ZERO_DIVIDE、NO_DATA_FOUND などの事前定義済の例外、またはユーザーが名前を付けた
ユーザー定義の例外を RAISE 文で呼び出すことができます。詳細は、10-6 ページの「独自の
PL/SQL 例外の定義」を参照してください。
構文
raise statement ::=
exception_name
RAISE
;
キーワードとパラメータの説明
exception_name
事前定義済の例外またはユーザー定義の例外を識別します。事前定義済の例外のリストは、
10-4 ページの「事前定義の PL/SQL 例外のまとめ」を参照してください。
使用上の注意
PL/SQL ブロックとサブプログラムから RAISE 文で例外を呼び出すのは、エラーのために処理
を続行できなくなった場合のみにしてください。指定した例外に対する RAISE 文は、その例外
の有効範囲内であれば任意の場所にコーディングできます。
例外が呼び出されたときに、PL/SQL がその例外のハンドラをカレント・ブロックで発見でき
ない場合は、ハンドラが見つかるまで、または検索するブロックがなくなるまで、例外が 1 つ
ずつ外側のブロックに伝播していきます。ハンドラが見つからなかった場合、PL/SQL はホス
ト環境に「未処理例外」エラーを戻します。
例外ハンドラの中の RAISE 文で例外名を省略すると、現行の例外を再度呼び出すことができま
す。これによって、初期の対処措置(問題のログを記録するなど)を行ってから、より広範囲
な対処を行う別のハンドラに制御を渡すことができます。例外が再度呼び出された場合、最初
に検索されるブロックは、カレント・ブロックではなく外側のブロックです。
例
次の例を参照してください。
例 1-12「ストアド・サブプログラムの作成」(1-13 ページ)
例 9-3「emp_admin パッケージの作成」
(9-6 ページ)
例 10-3「PL/SQL 例外の有効範囲」(10-6 ページ)
例 10-9「PL/SQL 例外の再呼出し」(10-12 ページ)
関連項目
「例外定義」(13-38 ページ)
13-92
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
レコード定義
レコード定義
レコードは、様々な型のデータ値を格納できるコンポジット変数で、C、C++ または Java の
struct 型に似ています。詳細は、5-5 ページの「PL/SQL レコード」を参照してください。
PL/SQL のレコードは、表の行から取り出したデータや特定の列を保持する場合に便利です。
新しいレコード型を作成するかわりに、変数を table%ROWTYPE または cursor%ROWTYPE と
して宣言して、メンテナンスを容易にできます。
構文
record type definition ::=
,
TYPE
type_name
IS_RECORD
field_declaration
;
record field declaration ::=
NOT_NULL
:=
expression
DEFAULT
field_name
datatype
record type declaration ::=
record_name
type_name
;
キーワードとパラメータの説明
datatype
データ型指定子です。datatype の構文は、13-24 ページの「定数と変数の宣言」を参照してく
ださい。
expression
変数、定数、リテラル、演算子、ファンクション・コールの組合せです。最も単純な式は、1
個の変数で構成されています。expression の構文は、13-44 ページの「式定義」を参照して
ください。宣言が PL/SQL コンパイラによって処理されるとき、expression の値がフィール
ドに代入されます。その値とフィールドのデータ型には互換性が必要です。
field_name
ユーザー定義のレコード内のフィールドを識別します。
NOT NULL
実行時に、NOT NULL として定義されたフィールドに NULL を代入しようとすると、事前定義
の例外 VALUE_ERROR が呼び出されます。NOT NULL 制約の後には初期化句が続く必要があり
ます。
record_name
ユーザー定義のレコードを識別します。
PL/SQL の言語要素
13-93
レコード定義
type_name
データ型指定子 RECORD を使用して定義されたユーザー定義のレコード型を識別します。
:= | DEFAULT
フィールドをデフォルト値に初期化します。
使用上の注意
RECORD 型定義とユーザー定義レコードの宣言は、任意のブロック、サブプログラムまたは
パッケージの宣言部でできます。
次に示すように、レコードを宣言の中で初期化できます。%TYPE 属性を使用して、フィールド
のデータ型を指定できます。また、フィールド宣言に NOT NULL 制約を加えて、フィールドに
NULL を代入できないようにすることもできます。NOT NULL と宣言されたフィールドは、初
期化されている必要があります。レコード中の個のフィールドを参照する場合は、ドット表記
法を使用します。たとえば、dept_rec レコードの dname フィールドを参照するには、
dept_rec.dname を使用します。
レコード中の個のフィールドに別に値を代入するかわりに、すべてのフィールドに値を一度に
代入できます。
■
■
2 つのユーザー定義レコードのデータ型が同じであれば、一方のレコードをもう一方のレ
コードに代入できます。
(正確に一致するフィールドが含まれているのみでは不十分です。)
フィールドの数と順序が同じで、対応するフィールドのデータ型に互換性があれば、
%ROWTYPE レコードをユーザー定義のレコードに代入できます。
SELECT 文または FETCH 文を使用して列の値をフェッチし、レコードに代入できます。選
択リストの列が、レコード中のフィールドと同じ順序で並ぶようにしてください。
ユーザー定義のレコードは、通常の有効範囲規則とインスタンス化の規則に従います。パッ
ケージの中では、そのパッケージが初めて参照された時点でインスタンスが生成され、データ
ベース・セッションが終わった時点で消滅します。ブロックまたはサブプログラムでは、ブ
ロックまたはサブプログラムに入るときにインスタンス化され、ブロックまたはサブプログラ
ムを終了すると消去されます。
スカラー変数と同様に、ユーザー定義のレコードもプロシージャやファンクションの仮パラ
メータとして宣言できます。スカラー・パラメータに適用されるのと同じ制限が、ユーザー定
義のレコードにも適用されます。
ファンクション仕様部の RETURN 句の中に RECORD 型を指定できます。こうすると、ファンク
ションは同じ型のユーザー定義のレコードを戻します。ユーザー定義のレコードを戻すファン
クションをコールする場合、次の構文を使用してレコード内のフィールドを参照します。
function_name(parameter_list).field_name
ネストしたフィールドを参照するには、次の構文を使用します。
function_name(parameter_list).field_name.nested_field_name
ファンクションがパラメータを取らない場合は、空のパラメータ・リストをコーディングしま
す。次に構文を示します。
function_name().field_name
例
次の例を参照してください。
例 1-16「レコード型の宣言」(1-16 ページ)
例 5-8「レコードとしての VARRAY」(5-9 ページ)
例 5-20「複雑なデータ型を使用した VARRAY への値の代入」
(5-14 ページ)
例 5-21「複雑なデータ型を使用した表への値の代入」(5-14 ページ)
例 5-41「単純なレコード型の宣言および初期化」(5-28 ページ)
例 5-42「レコード型の宣言および初期化」(5-28 ページ)
例 5-44「ファンクションからレコードを戻す」(5-30 ページ)
例 5-45「プロシージャへのパラメータとしてのレコードの使用」(5-30 ページ)
13-94
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
レコード定義
例 5-46「ネストされたレコードの宣言」(5-30 ページ)
例 5-47「レコードへのデフォルト値の代入」(5-31 ページ)
例 5-50「%ROWTYPE を使用した PL/SQL レコードの挿入」(5-33 ページ)
例 5-51「レコードを使用した行の更新」(5-33 ページ)
例 5-52「レコードを使用した RETURNING 句の使用」(5-34 ページ)
例 5-53「SELECT INTO 文での BULK COLLECT の使用」
(5-34 ページ)
例 6-26「レコード型を戻すカーソル変数」(6-20 ページ)
例 9-3「emp_admin パッケージの作成」
(9-6 ページ)
関連項目
「コレクション定義」(13-16 ページ)
「ファンクション宣言」(13-58 ページ)
「パッケージ宣言」(13-84 ページ)
「プロシージャ宣言」(13-89 ページ)
PL/SQL の言語要素
13-95
RESTRICT_REFERENCES プラグマ
RESTRICT_REFERENCES プラグマ
ストアド・ファンクションは、副作用を制御する特定の純正規則に従っている場合にのみ、
SQL 文からコールできます。8-23 ページの「PL/SQL サブプログラムの副作用の制御」を参照
してください。副作用が少なければ、特に PARALLEL_ENABLE ヒントまたは DETERMINISTIC
ヒントを使用している場合に、問合せ内でファンクションをより効率化できます。ファンク
ション自体に適用される規則が、そのファンクションがコールするファンクションまたはプロ
シージャにも適用されます。
ファンクション本体内の SQL 文が規則に違反すると、実行時(文が解析されるとき)にエラー
が発生します。コンパイル時にこの規則に違反していないかどうかを確認するには、コンパイ
ラ・ディレクティブである RESTRICT_REFERENCES プラグマを使用します。このプラグマは、
ファンクションがデータベース表またはパッケージ変数(あるいはその両方)に対する読込み
や書込み、またはそのいずれも行っていないことを示します。このような読込みや書込み操作
を行っているファンクションは、コールによって結果が異なったり、エラーが発生する場合が
あるため、最適化は困難です。
詳細は、
『Oracle Database アプリケーション開発者ガイド - 基礎編』を参照してください。
構文
restrict_references pragma ::=
RNDS
WNDS
function_name
PRAGMA
RESTRICT_REFERENCES
(
,
,
RNPS
DEFAULT
WNPS
TRUST
キーワードとパラメータの説明
DEFAULT
プラグマがパッケージ仕様部またはオブジェクト型の仕様部の中のすべてのサブプログラムに
適用されるように指定します。その場合でも、サブプログラムごとにプラグマを宣言できます。
これらのプラグマは、デフォルトのプラグマをオーバーライドします。
function_name
ユーザー定義のファンクションまたはプロシージャを識別します。
PRAGMA
文がコンパイラ・ディレクティブであることを表します。プラグマは、実行時ではなくコンパ
イル時に処理されます。プログラムの機能に影響を与えず、コンパイラに情報を提供します。
RNDS
サブプログラムがデータベースに読込み禁止状態である(データベース表を問合せできない)
ことを示します。
RNPS
サブプログラムがパッケージに読込み禁止状態である(パッケージ変数の値を参照できない)
ことを示します。
13-96
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
RESTRICT_REFERENCES プラグマ
TRUST
サブプログラムが 1 つ以上の規則に違反しないと信頼されていることを示します。C または
Java で記述されたファンクションを PL/SQL でコールする場合は、実行時にこれらのファンク
ションを検証できないため、この値が必要です。
WNDS
サブプログラムがデータベースへの書込み禁止状態である(表を変更できない)ことを示しま
す。
WNPS
サブプログラムがパッケージへの書込み禁止状態である(パッケージ変数の値を変更できない)
ことを示します。
使用上の注意
RESTRICT_REFERENCES プラグマは、パッケージ仕様部またはオブジェクト型仕様部でのみ宣
言できます。制約は 4 つまで(RNDS、RNPS、WNDS、WNPS)任意の順序で指定できます。パラ
レル問合せからファンクションをコールするには、4 つの制約をすべて指定します。他の制約
を暗黙的に指定する制約はありません。通常、このプラグマはファンクションに対して指定し
ます。ファンクションがプロシージャをコールする場合は、それらのプロシージャにも同様に
プラグマを指定します。
TRUST を指定すると、ファンクション本体はプラグマにリストされた制約に違反しているかど
うかチェックされません。ファンクションは制約に違反していないことを承認されます。これ
らのチェックをスキップすると、パフォーマンスが向上します。
サブプログラム名ではなく DEFAULT を指定した場合、このプラグマはパッケージ仕様部また
はオブジェクト型の仕様部(オブジェクト型のシステム定義のコンストラクタも含む)の中の
すべてのサブプログラムに適用されます。その場合でも、サブプログラムごとにプラグマを宣
言し、デフォルトのプラグマをオーバーライドできます。
RESTRICT_REFERENCES プラグマは、1 つのサブプログラム宣言にのみ適用できます。オー
バーロードされたサブプログラムの名前を参照するプラグマは、直前のサブプログラム宣言に
必ず適用されます。
例
次の例を参照してください。
例 6-48「自律型ファンクションのコール」(6-40 ページ)
関連項目
「AUTONOMOUS_TRANSACTION プラグマ」(13-6 ページ)
「EXCEPTION_INIT プラグマ」
(13-37 ページ)
「SERIALLY_REUSABLE プラグマ」
(13-109 ページ)
PL/SQL の言語要素
13-97
RETURN 文
RETURN 文
RETURN 文は、サブプログラムの実行を即座に完了させ、コール元に制御を戻します。その後
は、サブプログラム・コールの直後の文から、実行が再開されます。ファンクションの中の
RETURN 文は、ファンクション識別子を戻り値に代入します。8-5 ページの「RETURN 文の使
用」を参照してください。
構文
return statement ::=
(
)
expression
RETURN
;
キーワードとパラメータの説明
expression
変数、定数、リテラル、演算子、ファンクション・コールの組合せです。最も単純な式は、1
個の変数で構成されています。RETURN 文を実行すると、expression の値がファンクション
識別子に代入されます。
使用上の注意
RETURN 文は、ファンクションの仕様部の中で戻り値のデータ型を指定する RETURN 句とは異
なります。
サブプログラムでは、複数の RETURN 文を使用できます。どの RETURN 文を実行しても、サ
ブプログラムは即座に終了します。RETURN 文をサブプログラムの最後の文として配置する必
要はありません。RETURN 文を無名ブロックで使用して、そのブロックおよびすべての外側の
ブロックを終了させることができますが、RETURN 文は式を含むことはできません。
プロシージャでは、RETURN 文に式を含めることはできません。RETURN 文には、プロシー
ジャ本来の終了地点に達する前に、コール元に制御を戻す役割のみがあります。ファンクショ
ンでは、RETURN 文に、RETURN 文の実行時に評価される式が含まれている必要があります。
結果として得られる値がファンクション識別子に代入されます。ファンクションには、RETURN
文へ導く少なくとも 1 つの実行パスが必要です。そうではない場合、PL/SQL によって実行時
に例外が呼び出されます。
例
次の例を参照してください。
例 1-13「パッケージおよびパッケージ本体の作成」(1-13 ページ)
例 2-15「名前解決でのサブプログラムの使用」(2-14 ページ)
例 5-44「ファンクションからレコードを戻す」(5-30 ページ)
例 6-43「パッケージでの自律型ファンクションの宣言」(6-36 ページ)
例 6-48「自律型ファンクションのコール」(6-40 ページ)
例 9-3「emp_admin パッケージの作成」
(9-6 ページ)
関連項目
「ファンクション宣言」(13-58 ページ)
13-98
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
RETURNING INTO 句
RETURNING INTO 句
RETURNING 句では、DELETE、EXECUTE IMMEDIATE、INSERT および UPDATE の各文の戻
り値を指定します。取り出した列値は、個の変数またはコレクションに代入できます。
RETURNING 句はリモートまたはパラレルでの削除には使用できません。文を実行しても行に影
響がない場合、RETURNING 句で指定した変数の値は未定義になります。
構文
returning clause ::=
,
,
variable_name
single_row_expression
INTO
:
host_variable_name
RETURNING
,
RETURN
,
multiple_row_expression
BULK
COLLECT
collection_name
INTO
:
host_array_name
キーワードとパラメータの説明
BULK COLLECT
1 つ以上のコレクションに結果の値を格納します。FETCH 文を使用したループよりも高速な問
合せが可能です。詳細は、11-8 ページの「バルク SQL による、DML 文および問合せのルー
プ・オーバーヘッドの削減」を参照してください。
collection_name
フェッチした select_item 値を格納するための、宣言されたコレクションを識別します。
select_item ごとに、リストの中に、対応する型互換のコレクションが存在している必要が
あります。
host_array_name
フェッチした select_item 値を格納するための配列を識別します。この配列は、PL/SQL ホ
スト環境で宣言され、バインド変数として PL/SQL に渡されます。select_item ごとに、リ
ストの中に、対応する型互換の配列が存在している必要があります。ホスト配列には、接頭辞
としてコロンが必要です。
host_variable_name
PL/SQL ホスト環境で宣言され、バインド変数として PL/SQL に渡されるカーソル変数を識別
します。ホスト・カーソル変数のデータ型は、PL/SQL カーソル変数の戻り型と互換性があり
ます。ホスト変数には、接頭辞としてコロンを付けてください。
INTO ...
単一行の問合せの場合に使用され、取り出された列値を入れる変数またはレコードを指定しま
す。問合せによって取り出された値それぞれに対して、INTO 句の中に、対応する型互換性変数
が存在している必要があります。
multiple_row_expression
表の複数行を戻す式です。
PL/SQL の言語要素
13-99
RETURNING INTO 句
RETURNING | RETURN
RETURNING 句のある(BULK COLLECT 句のない)DML 文の場合に使用され、列の値が戻
されるバインド変数を指定します。DML 文によって戻された値それぞれに対して、
RETURNING INTO 句の中に、対応する型互換性変数が存在している必要があります。
single_row_expression
表の単一行を戻す式です。
variable_name
選択された列の値を格納する変数を識別します。
使用
RETURNING 句を持つ DML 文の場合は、パラメータ・モード OUT を定義して指定しなくても、
OUT 引数を RETURNING INTO 句に入れることができます。USING 句と RETURNING INTO 句の
両方を使用する場合、USING 句には IN 引数のみを含めることができます。
実行時に、バインド引数は動的文字列内の対応するプレースホルダを置き換えます。すべての
プレースホルダを USING 句内または RETURNING INTO 句内(あるいはその両方)のバインド
引数に関連付ける必要があります。数値リテラル、文字リテラルおよび文字列リテラルはバイ
ンド引数として使用できますが、ブール・リテラル(TRUE、FALSE および NULL)は使用でき
ません。動的文字列に NULL を渡すには、回避策を使用する必要があります。7-10 ページの
「動的 SQL への NULL の引渡し」を参照してください。
動的 SQL はすべての SQL データ型をサポートしています。たとえば、定義変数やバインド引
数をコレクション、LOB、オブジェクト型のインスタンスおよび ref とすることができます。動
的 SQL は PL/SQL 固有の型をサポートしていません。たとえば、定義変数やバインド引数を
ブールまたは索引付き表にすることはできません。例外として、PL/SQL レコードを INTO 句
に入れることができます。
例
次の例を参照してください。
例 5-52「レコードを使用した RETURNING 句の使用」(5-34 ページ)
例 6-1「PL/SQL を使用したデータ操作」
(6-2 ページ)
例 7-5「RETURNING BULK COLLECT INTO 句を使用した動的 SQL」(7-6 ページ)
例 7-6「FORALL 文中の動的 SQL」(7-7 ページ)
例 11-15「RETURNING INTO 句での BULK COLLECT の使用」(11-18 ページ)
例 11-16「BULK COLLECT での FORALL の使用」(11-18 ページ)
関連項目
「DELETE 文」(13-35 ページ)
「SELECT INTO 文」(13-105 ページ)
「UPDATE 文」(13-119 ページ)
13-100
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
ROLLBACK 文
ROLLBACK 文
ROLLBACK 文は COMMIT 文の逆です。これは、カレント・トランザクションでデータベースに
加えられたすべての変更または一部の変更を取り消します。詳細は、6-28 ページの「PL/SQL
におけるトランザクション処理の概要」を参照してください。
SQL の ROLLBACK 文は、静的 SQL として PL/SQL に埋め込むことができます。SQL の
ROLLBACK 文の構文の詳細は、『Oracle Database SQL リファレンス』を参照してください。
使用上の注意
ロールバック先のセーブポイント以降にマークされているセーブポイントはすべて消去されま
す。ロールバック先のセーブポイントは消去されません。たとえば、セーブポイントを A、B、
C、D の順でマークしている場合、セーブポイント B までロールバックすると、セーブポイン
ト C と D のみが消去されます。
INSERT 文、UPDATE 文または DELETE 文を実行する前に、暗黙的なセーブポイントがマーク
されます。文の実行が失敗すると、その暗黙的なセーブポイントまでロールバックされます。
通常は、トランザクション全体ではなく、失敗した SQL 文のみがロールバックされます。その
文が原因で未処理例外が呼び出された場合は、ホスト環境によってロールバックの対象が決ま
ります。
例
次の例を参照してください。
例 2-14「名前解決でのブロック・ラベルの使用」(2-14 ページ)
例 6-37「ROLLBACK の使用」
(6-30 ページ)
例 6-38「ROLLBACK と SAVEPOINT の併用」
(6-30 ページ)
例 6-39「ROLLBACK による SAVEPOINT の再使用」
(6-31 ページ)
関連項目
「COMMIT 文」(13-23 ページ)
「SAVEPOINT 文」
(13-104 ページ)
PL/SQL の言語要素
13-101
%ROWTYPE 属性
%ROWTYPE 属性
%ROWTYPE 属性は、データベース表の中の行を表すレコード型を提供します。レコードには、
表から選択された行全体、あるいはカーソルまたはカーソル変数でフェッチされた行全体の
データを格納できます。%ROWTYPE 属性を使用して宣言された変数は、データ型名を使用して
宣言された変数と同じように扱われます。%ROWTYPE 属性は、変数宣言の中でデータ型指定子
として使用できます。
レコード中のフィールドと、それに対応する行の中の列は、同じ名前とデータ型を持ちます。
ただし、%ROWTYPE レコードのフィールドは、NOT NULL 列、チェック制約、デフォルト値な
どの制約を継承しません。詳細は、2-11 ページの「%ROWTYPE 属性の使用」を参照してくだ
さい。
構文
%rowtype attribute ::=
cursor_name
cursor_variable_name
%
ROWTYPE
table_name
キーワードとパラメータの説明
cursor_name
現行の有効範囲の中で、事前に宣言されている明示カーソルを識別します。
cursor_variable_name
現行の有効範囲の中で事前に宣言されている、強い型指定を持つ PL/SQL カーソル変数を識別
します。
table_name
宣言が PL/SQL コンパイラによって処理されるときにアクセスできる必要があるデータベース
の表(またはビュー)を識別します。
使用上の注意
変数を table_name%ROWTYPE 型として宣言すると、データベース表と PL/SQL 間でデータを送
信する場合に便利です。列ごとに個別の変数を作成するのではなく、単一の変数を作成します。
ユーザーはすべての列の名前を知る必要がありません。作成した変数名ではなく、列の実名を
使用して、列を参照します。後で列が表に追加されたり、表から削除された場合も、変更なし
でコードは正常に機能します。
レコード中のフィールドを参照するには、ドット表記法(record_name.field_name)を使
用します。この方法では、一度に 1 つのフィールドに対して読取りまたは書込みを行うことが
できます。
レコードのすべてのフィールドに一度に値を代入するには、次の 2 つの方法があります。
■
■
13-102
1 番目の方法として、PL/SQL では、レコード全体の宣言が同じ表またはカーソルを参照し
ている場合には、そのレコード全体の間で集計代入できます。
2 番目の方法では、SELECT 文か FETCH 文を使用して、レコードに列値のリストを代入しま
す。列名の順番は宣言された順番です。%ROWTYPE に関連付けられたカーソルからフェッ
チされた選択項目は、単純名を持つ必要があります。また、選択項目が式の場合は別名を
持つ必要があります。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
%ROWTYPE 属性
例
次の例を参照してください。
例 1-6「明示カーソルでの %ROWTYPE の使用」
(1-9 ページ)
例 2-8「表の行での %ROWTYPE の使用」
(2-11 ページ)
例 2-9「%ROWTYPE 属性の使用」
(2-11 ページ)
例 2-10「%ROWTYPE 宣言を使用したレコードへの値の代入」(2-12 ページ)
例 3-11「%TYPE および %ROWTYPE での SUBTYPE の使用」(3-19 ページ)
例 5-7「%TYPE および %ROWTYPE を使用したコレクション要素型の指定」(5-8 ページ)
例 5-20「複雑なデータ型を使用した VARRAY への値の代入」
(5-14 ページ)
例 5-42「レコード型の宣言および初期化」(5-28 ページ)
例 6-24「%ROWTYPE 変数を戻すカーソル変数」(6-20 ページ)
例 6-25「%ROWTYPE 属性を使用したデータ型の指定」(6-20 ページ)
例 13-1「宣言および変数への値の代入」(13-5 ページ)
関連項目
「定数と変数の宣言」(13-24 ページ)
「カーソル宣言」(13-32 ページ)
「カーソル変数」(13-29 ページ)
「FETCH 文」
(13-52 ページ)
PL/SQL の言語要素
13-103
SAVEPOINT 文
SAVEPOINT 文
SAVEPOINT 文は、トランザクション処理の過程で、現行の位置に名前を付けてマークします。
セーブポイントを ROLLBACK TO 文と組み合せると、トランザクション全体ではなく、トラン
ザクションの一部を取り消すことができます。詳細は、6-28 ページの「PL/SQL におけるトラ
ンザクション処理の概要」を参照してください。
SQL の SAVEPOINT 文は、静的 SQL として PL/SQL に埋め込むことができます。SQL の
SAVEPOINT 文の構文の詳細は、『Oracle Database SQL リファレンス』を参照してください。
使用上の注意
単純なロールバックまたはコミットではすべてのセーブポイントが消去されます。あるセーブ
ポイントまでロールバックすると、そのセーブポイント以降にマークされたセーブポイントは
すべて消去されます。ロールバック先のセーブポイントは消去されません。
セーブポイント名は、トランザクション内で再利用できます。再利用すると、セーブポイント
はトランザクションの中の古い位置から現在の位置に移動します。
再帰的サブプログラムの中でセーブポイントをマークすると、再帰しながら進む過程で、各レ
ベルで SAVEPOINT 文の新しいインスタンスが実行されます。ロールバックできるのは直前に
マークされたセーブポイントまでのみです。
INSERT 文、UPDATE 文または DELETE 文を実行する前に、暗黙的なセーブポイントがマーク
されます。文の実行が失敗すると、その暗黙的なセーブポイントまでロールバックされます。
通常は、トランザクション全体ではなく、失敗した SQL 文のみがロールバックされます。その
文が原因で未処理例外が呼び出された場合は、ホスト環境(SQL*Plus など)によってロール
バックの対象が決まります。
例
次の例を参照してください。
例 6-38「ROLLBACK と SAVEPOINT の併用」
(6-30 ページ)
例 6-39「ROLLBACK による SAVEPOINT の再使用」
(6-31 ページ)
関連項目
「COMMIT 文」(13-23 ページ)
「ROLLBACK 文」(13-101 ページ)
13-104
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
SELECT INTO 文
SELECT INTO 文
SELECT INTO 文は、データベースの 1 つ以上の表からデータを取り出して、選択した値を変数
またはコレクションに代入します。SELECT SQL 文の詳細は、
『Oracle Database SQL リファレ
ンス』を参照してください。
デフォルトの使用方法(SELECT ... INTO)では、この文は単一の行から 1 つ以上の列を取
り出します。バルクでの使用方法(SELECT ... BULK COLLECT INTO)では、この文は結
果セット全体を一度に取り出します。
構文
select into statement ::=
DISTINCT
UNIQUE
*
ALL
SELECT
,
select_item
,
variable_name
INTO
record_name
table_reference
FROM
alias
rest_of_statement
THE
(
subquery
;
)
PL/SQL の言語要素
13-105
SELECT INTO 文
select item ::=
,
(
parameter_name
)
function_name
NULL
numeric_literal
schema_name
.
table_name
.
*
view_name
schema_name
AS
alias
.
table_name
.
view_name
column_name
CURRVAL
sequence_name
.
NEXTVAL
subquery
’
text
’
キーワードとパラメータの説明
alias
参照される列、表またはビューの別名(通常は短縮名)です。
BULK COLLECT
1 つ以上のコレクションに結果の値を格納します。FETCH 文を使用したループよりも高速な問
合せが可能です。詳細は、11-8 ページの「バルク SQL による、DML 文および問合せのルー
プ・オーバーヘッドの削減」を参照してください。
collection_name
フェッチした select_item 値を格納するための、宣言されたコレクションを識別します。
select_item ごとに、リストの中に、対応する型互換のコレクションが存在している必要が
あります。
function_name
ユーザー定義のファンクションを識別します。
host_array_name
フェッチした select_item 値を格納するための配列を識別します。この配列は、PL/SQL ホ
スト環境で宣言され、バインド変数として PL/SQL に渡されます。select_item ごとに、リ
ストの中に、対応する型互換の配列が存在している必要があります。ホスト配列には、接頭辞
としてコロンが必要です。
numeric_literal
数値または暗黙的に数値に変換可能な値を表すリテラルです。
parameter_name
ユーザー定義ファンクションの仮パラメータを識別します。
13-106
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
SELECT INTO 文
record_name
フェッチした行の値を格納する、ユーザー定義のレコードまたは %ROWTYPE レコードを識別し
ます。問合せが戻す select_item 値に対して、レコードの中に、対応する型互換のフィール
ドが存在している必要があります。
rest_of_statement
SAMPLE 句を除く、SQL の SELECT 文の FROM 句に続けることができる任意の構造体です。
schema_name
表またはビューが含まれているスキーマを識別します。schema_name を省略すると、表また
はビューはユーザーのスキーマ内に存在するとみなされます。
subquery
処理する行セットを提供する SELECT 文です。構文は select_into_statement の構文と似
ていますが、INTO 句は使用できません。
table_reference
表またはビューを指定します。指定された表またはビューは、SELECT 文の実行時にアクセス
できる必要があり、ユーザーは SELECT 権限を持っている必要があります。
table_reference の構文は、13-35 ページの「DELETE 文」を参照してください。
TABLE (subquery2)
TABLE のオペランドは、1 つの列値を戻す SELECT 文です。これはネストした表または
VARRAY である必要があります。演算子 TABLE は、値がスカラー値ではなくコレクションで
あることを Oracle に通知します。
variable_name
フェッチした select_item 値を格納するための、事前に宣言された変数を識別します。問合
せが戻す select_item 値に対して、リストの中に、対応する型互換の変数が存在している必
要があります。
使用上の注意
デフォルトでは、SELECT INTO 文は 1 行のみを戻す必要があります。それ以外の場合、
PL/SQL は事前定義の例外 TOO_MANY_ROWS を呼び出して、INTO 句内の変数の値は未定義に
なります。WHERE 句が 1 行とのみ一致するように指定してください。
行が戻されなかった場合は、PL/SQL によって NO_DATA_FOUND が呼び出されます。可能な場
合、COUNT(*)、AVG() などの集計関数の結果を選択すると、この例外を回避できます。これ
らの集計関数は、条件に一致する行がない場合でも、必ず単一の値を戻します。
SELECT ... BULK COLLECT INTO 文を使用すると、複数行を戻すことができます。結果を
保持するようにコレクション変数を設定する必要があります。必要に応じて、拡張される結合
配列またはネストした表を宣言して、結果セット全体を保持することもできます。
暗黙カーソル SQL とカーソル属性 %NOTFOUND、%FOUND、%ROWCOUNT および %ISOPEN を使
用すると、SELECT INTO 文の実行についての情報が得られます。
例
例 13-4 に、SELECT INTO 文を使用する様々な方法を示します。
例 13-4 SELECT INTO 文の使用
DECLARE
deptid
jobid
emp_rec
employees.department_id%TYPE;
employees.job_id%TYPE;
employees%ROWTYPE;
PL/SQL の言語要素
13-107
SELECT INTO 文
TYPE emp_tab IS TABLE OF employees%ROWTYPE INDEX BY PLS_INTEGER;
all_emps
emp_tab;
BEGIN
SELECT department_id, job_id INTO deptid, jobid
FROM employees WHERE employee_id = 140;
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('Dept Id: ' || deptid || ', Job Id: ' || jobid);
END IF;
SELECT * INTO emp_rec FROM employees WHERE employee_id = 105;
SELECT * BULK COLLECT INTO all_emps FROM employees;
DBMS_OUTPUT.PUT_LINE('Number of rows: ' || SQL%ROWCOUNT);
END;
/
次の例を参照してください。
例 1-3「SELECT INTO を使用した変数への値の代入」
(1-6 ページ)
例 1-4「サブプログラムのパラメータとしての変数への値の代入」
(1-7 ページ)
例 1-9「WHILE-LOOP を使用した制御」
(1-11 ページ)
例 5-51「レコードを使用した行の更新」(5-33 ページ)
例 5-52「レコードを使用した RETURNING 句の使用」(5-34 ページ)
例 6-5「CURRVAL と NEXTVAL の使用」
(6-4 ページ)
例 6-37「ROLLBACK の使用」
(6-30 ページ)
例 6-38「ROLLBACK と SAVEPOINT の併用」
(6-30 ページ)
例 6-43「パッケージでの自律型ファンクションの宣言」(6-36 ページ)
例 7-1「動的 SQL の例」(7-3 ページ)
例 7-2「表名および WHERE 句を受け入れる動的 SQL プロシージャ」(7-4 ページ)
関連項目
「代入文」(13-3 ページ)
「FETCH 文」
(13-52 ページ)
「%ROWTYPE 属性」
(13-102 ページ)
13-108
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
SERIALLY_REUSABLE プラグマ
SERIALLY_REUSABLE プラグマ
SERIALLY_REUSABLE プラグマは、サーバーへの 1 コールの間のみ、そのパッケージ状態が必
要であることを示します。例としては、データベースへの OCI コール、データベース・リンク
を介したストアド・プロシージャ・コールなどがあります。このコールの後、パッケージ変数
の記憶域の再利用が可能になり、長時間実行セッションのメモリー・オーバーヘッドが削減さ
れます。詳細は、
『Oracle Database アプリケーション開発者ガイド - 基礎編』を参照してくだ
さい。
構文
pragma serially_resuable ::=
PRAGMA
SERIALLY_REUSABLE
;
キーワードとパラメータの説明
PRAGMA
文がプラグマ(コンパイラ・ディレクティブ)であることを表します。プラグマは、実行時で
はなくコンパイル時に処理されます。プログラムの機能に影響を与えず、コンパイラに情報を
提供する役割のみです。
使用上の注意
このプラグマは、同じセッションのそれ以降のデータベース・コール中には必要ない、1 回の
み使用される大規模な一時作業領域を宣言するパッケージに適しています。
本体部のないパッケージを逐次再使用可能としてマークできます。パッケージに仕様部と本体
がある場合は、両方ともマークする必要があります。本体のみをマークすることはできません。
逐次再使用可能なパッケージのグローバル・メモリーは、ユーザー・グローバル領域(UGA)
で個のユーザーに割り当てられるのではなく、システム・グローバル領域(SGA)にプールさ
れます。それによって、パッケージ作業領域の再使用が可能になります。サーバーへのコール
が終わると、メモリーはプールに戻されます。パッケージが再使用されるたびに、そのパッ
ケージのパブリック変数はデフォルト値か NULL に初期設定されます。
逐次再使用可能パッケージには、データベース・トリガー、または SQL 文からコールされる他
の PL/SQL サブプログラムからアクセスすることはできません。これを試行すると、Oracle は
エラーを生成します。
例
例 13-5 では、逐次再使用可能パッケージを作成します。
例 13-5 逐次再使用パッケージの使用
CREATE PACKAGE pkg1 IS
PRAGMA SERIALLY_REUSABLE;
num NUMBER := 0;
PROCEDURE init_pkg_state(n NUMBER);
PROCEDURE print_pkg_state;
END pkg1;
/
CREATE PACKAGE BODY pkg1 IS
PRAGMA SERIALLY_REUSABLE;
PROCEDURE init_pkg_state (n NUMBER) IS
BEGIN
pkg1.num := n;
PL/SQL の言語要素
13-109
SERIALLY_REUSABLE プラグマ
END;
PROCEDURE print_pkg_state IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Num: ' || pkg1.num);
END;
END pkg1;
/
関連項目
「AUTONOMOUS_TRANSACTION プラグマ」(13-6 ページ)
「EXCEPTION_INIT プラグマ」
(13-37 ページ)
「RESTRICT_REFERENCES プラグマ」(13-96 ページ)
13-110
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
SET TRANSACTION 文
SET TRANSACTION 文
SET TRANSACTION 文は、読取り専用または読取り / 書込みのトランザクションを開始するか、
分離レベルを設定するか、指定したロールバック・セグメントにカレント・トランザクション
を代入します。読取り専用トランザクションは、他のユーザーが更新中である 1 つ以上の表に
対して、複数の問合せを実行する場合に便利です。詳細は、6-32 ページの「SET
TRANSACTION を使用したトランザクション・プロパティの設定」を参照してください。
SQL の SET TRANSACTION 文の詳細は、
『Oracle Database SQL リファレンス』を参照してくだ
さい。
構文
set transaction ::=
ONLY
READ
WRITE
SET
TRANSACTION
SERIALIZABLE
ISOLATION
’
text
’
;
LEVEL
READ
USE
NAME
ROLLBACK
SEGMENT
COMMITTED
rollback_segment_name
キーワードとパラメータの説明
READ ONLY
カレント・トランザクションを読取り専用に設定する句です。これによって、それ以降の問合
せからはトランザクションの開始前にコミットされた変更内容のみが参照されます。READ
ONLY を使用しても、他のユーザーや他のトランザクションには影響がありません。
READ WRITE
カレント・トランザクションを読取り / 書込みに設定する句です。READ WRITE を使用しても、
他のユーザーや他のトランザクションには影響がありません。トランザクションで DML 文が
実行されると、Oracle はトランザクションをロールバック・セグメントに代入します。
ISOLATION LEVEL
データベースを変更するトランザクションがどのように処理されるかを指定します。
SERIALIZABLE: 直列可能トランザクションが、コミットされていない別のトランザクション
ですでに変更された表を変更する SQL DML 文を実行しようとした場合、その文は失敗します。
SERIALIZABLE モードを使用可能にするには、DBA が、Oracle 初期化パラメータ
COMPATIBLE を 7.3.0 以上に設定します。
READ COMMITTED: トランザクションに含まれる SQL DML 文が、別のトランザクションによっ
て保持されている行ロックを必要とする場合に、その文は行ロックが解放されるまで待機しま
す。
USE ROLLBACK SEGMENT
カレント・トランザクションを指定したロールバック・セグメントに代入し、トランザクショ
ンを読取り / 書込みに設定する句です。このパラメータは、同じトランザクションの中で
READ ONLY パラメータとともには使用できません。読取り専用トランザクションは、ロール
バック情報を生成しないためです。
PL/SQL の言語要素
13-111
SET TRANSACTION 文
NAME
トランザクションの名前またはコメント・テキストを指定します。この指定した名前やコメン
ト・テキストはトランザクションの実行中に使用可能で、長時間実行のインダウト・トランザ
クションをモニターしやすくなるため、COMMIT COMMENT 機能を使用するより適切です。
使用上の注意
SET TRANSACTION 文は、トランザクションの最初の SQL 文にする必要があり、そのトランザ
クションで 1 回しか使用できません。
例
次の例を参照してください。
例 6-40「SET TRANSACTION を使用した読取り専用トランザクションの開始」
(6-32 ページ)
関連項目
「COMMIT 文」(13-23 ページ)
「ROLLBACK 文」(13-101 ページ)
「SAVEPOINT 文」
(13-104 ページ)
13-112
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
SQL カーソル
SQL カーソル
明示カーソルに関連付けられていない SQL 文を処理するために、Oracle は暗黙的にカーソルを
オープンします。PL/SQL では直前の暗黙カーソルを SQL カーソルとして参照できます。SQL
カーソルには、%FOUND、%ISOPEN、%NOTFOUND および %ROWCOUNT の 4 つの属性がありま
す。これらの属性を使用すると、DML 文の実行についての情報が得られます。SQL カーソルに
は、FORALL 文で使用できるように設計された追加の属性 %BULK_ROWCOUNT および
%BULK_EXCEPTIONS もあります。詳細は、6-14 ページの「PL/SQL を使用したデータの問合
せ」を参照してください。
構文
sql cursor ::=
FOUND
ISOPEN
NOTFOUND
SQL
%
ROWCOUNT
BULK_ROWCOUNT
(
index
)
ERROR_INDEX
BULK_EXCEPTIONS
(
index
)
.
ERROR_CODE
キーワードとパラメータの説明
%BULK_ROWCOUNT
FORALL 文で使用するために設計された複合属性です。この属性は索引付き表のように取り扱
われます。i 番目の要素には、UPDATE 文または DELETE 文の i 番目の実行によって処理された
行の数が格納されます。i 番目の実行によって影響を受ける行がない場合、
%BULK_ROWCOUNT(i) は 0(ゼロ)を戻します。
%BULK_EXCEPTIONS
SAVE EXCEPTIONS 句を使用する FORALL 文によって発生した例外についての情報を格納する
結合配列です。この要素をループして、例外の発生した箇所と内容を判断する必要があります。
SQL%BULK_EXCEPTIONS(i).ERROR_INDEX は、1 から SQL%BULK_EXCEPTIONS.COUNT ま
での各索引値 i において、例外の原因となった FORALL ループの反復を指定します。
SQL%BULK_EXCEPTIONS(i).ERROR_CODE は、例外に対応する Oracle エラー・コードを指定
します。
%FOUND
INSERT 文、UPDATE 文または DELETE 文が 1 つ以上の行に影響を与える場合または SELECT
INTO 文が 1 つ以上の行を戻す場合、この属性は TRUE を戻します。それ以外の場合は、FALSE
を戻します。
%ISOPEN
Oracle は、SQL カーソルに関連付けられた SQL 文の実行を終了すると、このカーソルを自動的
にクローズするため、この属性は常に FALSE を戻します。
PL/SQL の言語要素
13-113
SQL カーソル
%NOTFOUND
%FOUND とは論理的に反対の意味を持ちます。INSERT 文、UPDATE 文または DELETE 文がどの
行にも影響を与えない場合または SELECT INTO 文がどの行も戻さない場合、この属性は TRUE
を戻します。それ以外の場合は、FALSE を戻します。
%ROWCOUNT
INSERT 文、UPDATE 文または DELETE 文に影響を受けた行、または SELECT INTO 文に戻され
た行の数を戻します。
SQL
Oracle 暗黙カーソルの名前です。
使用上の注意
カーソル属性は、プロシージャ文では使用できますが、SQL 文では使用できません。Oracle が
SQL カーソルを自動的にオープンするまでは、暗黙カーソルの属性は NULL を戻します。カー
ソル属性の値は、常に直前に実行された SQL 文を参照します(その文の場所とは無関係です)。
文が別の有効範囲に存在する場合もあります。したがって、属性の値を保存して後で使用する
場合は、値を変数に直接代入してください。
SELECT INTO 文が行を戻せなかった場合は、次の行で SQL%NOTFOUND をチェックしているか
どうかにかかわらず、PL/SQL によって事前定義済の例外 NO_DATA_FOUND が呼び出されま
す。SQL 集計関数をコールする SELECT INTO 文が、NO_DATA_FOUND を呼び出すことはあり
ません。SQL 集計関数は、必ず値または NULL を戻します。このような場合、SQL%NOTFOUND
は FALSE を戻します。典型的な挿入は 1 行にのみ影響するため、%BULK_ROWCOUNT は、冗長
になるのを防ぐためバルク挿入用に保持されません。11-12 ページの「%BULK_ROWCOUNT
属性を持つ FORALL による影響を受ける行カウント」を参照してください。
バルク・バインドには、スカラー属性の %FOUND、%NOTFOUND および %ROWCOUNT を使用でき
ます。たとえば、%ROWCOUNT は、SQL 文のすべての実行によって処理された行の総数を戻し
ます。%FOUND と %NOTFOUND は、SQL 文の最後の実行のみを参照しますが、
%BULK_ROWCOUNT を使用すると、個の実行に対する値を推論できます。たとえば、
%BULK_ROWCOUNT(i) がゼロの場合、%FOUND と %NOTFOUND はそれぞれ、FALSE および
TRUE になります。
例
次の例を参照してください。
例 6-7「SQL%FOUND の使用」(6-7 ページ)
例 6-8「SQL%ROWCOUNT の使用」(6-7 ページ)
例 6-10「カーソルを使用したフェッチ」(6-9 ページ)
例 6-14「%FOUND の使用」
(6-12 ページ)
例 6-15「%ISOPEN の使用」(6-12 ページ)
例 6-16「%NOTFOUND の使用」
(6-12 ページ)
例 6-17「%ROWCOUNT の使用」
(6-13 ページ)
例 11-7「FORALL 文での %BULK_ROWCOUNT の使用」(11-12 ページ)
例 13-4「SELECT INTO 文の使用」(13-107 ページ)
関連項目
「カーソル宣言」(13-32 ページ)
「カーソル属性」(13-27 ページ)
「FORALL 文」
(13-55 ページ)
13-114
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
SQLCODE ファンクション
SQLCODE ファンクション
SQLCODE ファンクションは、直前の例外の番号コードを戻します。
内部例外の場合、SQLCODE は関連付けられている Oracle エラーの番号を戻します。SQLCODE
が戻す番号は負の値ですが、Oracle エラー「データが見つかりません。」の場合は例外です。こ
の場合、SQLCODE は +100 を戻します。ユーザー定義の例外の場合、SQLCODE は +1 を戻しま
す。ただし、EXCEPTION_INIT プラグマを使用して例外を Oracle エラー番号に関連付けてい
る場合は、代入した値を戻します。
構文
sqlcode function ::=
SQLCODE
使用上の注意
SQLCODE は例外ハンドラの中でのみ有効です。ハンドラの外側では、SQLCODE は常に 0 を戻
します。SQLCODE は呼び出された内部例外の識別に使用できるため、OTHERS 例外ハンドラの
中で使用すると特に便利です。SQLCODE は、SQL 文の中で直接使用することができません。ま
ず、SQLCODE の値をローカル変数に代入します。
RESTRICT_REFERENCES プラグマを使用してストアド・ファンクションの純正度を示すときに
ファンクションが SQLCODE をコールする場合は、WNPS および RNPS 制約は指定できません。
例
例 13-6 に、SQLCODE および SQLERRM の使用を示します。
例 13-6 SQLCODE および SQLERRM の使用
DECLARE
name employees.last_name%TYPE;
v_code NUMBER;
v_errm VARCHAR2(64);
BEGIN
SELECT last_name INTO name FROM employees WHERE employee_id = 1000;
EXCEPTION
WHEN OTHERS THEN
v_code := SQLCODE;
v_errm := SUBSTR(SQLERRM, 1 , 64);
DBMS_OUTPUT.PUT_LINE('The error code is ' || v_code || '- ' || v_errm);
END;
/
次の例を参照してください。
例 10-11「SQLCODE および SQLERRM の表示」
(10-14 ページ)
関連項目
「例外定義」(13-38 ページ)
「SQLERRM ファンクション」
(13-116 ページ)
「エラー・コードとエラー・メッセージの取得 : SQLCODE および SQLERRM」
(10-13 ページ)
PL/SQL の言語要素
13-115
SQLERRM ファンクション
SQLERRM ファンクション
SQLERRM ファンクションは、エラー番号の引数に関連付けられているエラー・メッセージを戻
します。引数が省略されている場合は、SQLCODE のカレント値に関連付けられているエラー・
メッセージを戻します。引数なしの SQLERRM は、例外ハンドラの中でのみ有効です。ハンド
ラの外側では、引数なしの SQLERRM は常にメッセージ「正常に完了しました。
」を戻します。
内部例外の場合、SQLERRM は、発生した Oracle エラーに関連付けられているメッセージを戻
します。メッセージの先頭には Oracle エラー・コードが示されています。
ユーザー定義の例外の場合、SQLERRM はメッセージ「ユーザー定義の例外」を戻します。ただ
し、EXCEPTION_INIT プラグマを使用して例外を Oracle エラー番号に関連付けている場合は
例外です。この場合、SQLERRM は対応するエラー・メッセージを戻します。詳細は、10-13
ページの「エラー・コードとエラー・メッセージの取得 : SQLCODE および SQLERRM」を参
照してください。
構文
sqlerrm function ::=
(
error_number
)
SQLERRM
キーワードとパラメータの説明
error_number
有効な Oracle エラー番号です。Oracle エラー(接頭辞として ORA- が付くエラー)のリスト
は、
『Oracle Database エラー・メッセージ』を参照してください。
使用上の注意
SQLERRM は呼び出された内部例外の識別に使用できるため、OTHERS 例外ハンドラの中で使用
すると特に便利です。SQLERRM に渡されるエラー番号は、負の値です。SQLERRM に 0(ゼロ)
を渡すと、常にメッセージ「ORA-0000: 正常に完了しました。」を戻します。SQLERRM に正数
を渡すと、必ず「ユーザー定義の例外」というメッセージが戻されます。ただし、+100 を渡す
と、SQLERRM によって「ORA-01403: データが見つかりません。
」というメッセージが戻されま
す。
SQLERRM は、SQL 文の中で直接使用することができません。13-115 ページの例 13-6 に示すよ
うに、まず、SQLERRM の値をローカル変数に代入します。
RESTRICT_REFERENCES プラグマを使用してストアド・ファンクションの純正度を示すとき
に、ファンクションが SQLERRM をコールする場合は WNPS および RNPS 制約を指定できませ
ん。
例
次の例を参照してください。
例 10-11「SQLCODE および SQLERRM の表示」
(10-14 ページ)
例 13-6「SQLCODE および SQLERRM の使用」
(13-115 ページ)
関連項目
「例外定義」(13-38 ページ)
「SQLCODE ファンクション」
(13-115 ページ)
13-116
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
%TYPE 属性
%TYPE 属性
%TYPE 属性を使用すると、型名をハードコードするかわりに、宣言内のフィールド、レコー
ド、ネストした表、データベース列または変数のデータ型を使用できます。%TYPE 属性は、定
数、変数、フィールドまたはパラメータを宣言するときにデータ型指定子として使用できます。
参照する型が変更されると、宣言は自動的に更新されます。これによって、たとえば、
VARCHAR2 列を長くする場合にコードを変更する必要がなくなります。%TYPE を使用して宣言
した項目には、NOT NULL、チェック制約、デフォルト値などの列制約は継承されません。詳細
は、2-10 ページの「%TYPE 属性の使用」を参照してください。
構文
%type attribute ::=
collection_name
cursor_variable_name
object name
.
field_name
%
TYPE
record_name
db_table_name
.
column_name
variable_name
キーワードとパラメータの説明
collection_name
現行の有効範囲のうち、これより前の部分で宣言されているネストした表、索引付き表または
VARRAY を指定します。
cursor_variable_name
現行の有効範囲の中で事前に宣言されている PL/SQL カーソル変数を識別します。カーソル変
数に代入できるのは、別のカーソル変数の値のみです。
db_table_name.column_name
宣言が PL/SQL コンパイラによって処理されるときにアクセスできる必要がある表および列を
識別します。
object_name
現行の有効範囲のうち、これより前の部分で宣言されているオブジェクト型のインスタンスを
識別します。
record_name
現行の有効範囲のうち、これより前の部分で宣言されているユーザー定義のレコードまたは
%ROWTYPE レコードです。
PL/SQL の言語要素
13-117
%TYPE 属性
record_name.field_name
現行の有効範囲のうち、これより前の部分で宣言されているユーザー定義のレコードまたは
%ROWTYPE レコードのフィールドを識別します。
variable_name
同じ有効範囲の中で事前に宣言されている変数を識別します。
使用上の注意
%TYPE 属性は、データベース列を参照する変数、フィールドおよびパラメータを宣言する場合
に特に便利です。列の長さや型が変更されても、コードは正常に機能します。
例
次の例を参照してください。
例 1-15「PL/SQL のコレクション型の使用」(1-16 ページ)
例 2-6「変数のデータ型を持つ %TYPE の使用」
(2-10 ページ)
例 2-7「表の列での %TYPE の使用」
(2-11 ページ)
例 2-15「名前解決でのサブプログラムの使用」(2-14 ページ)
例 2-10「%ROWTYPE 宣言を使用したレコードへの値の代入」(2-12 ページ)
例 3-11「%TYPE および %ROWTYPE での SUBTYPE の使用」(3-19 ページ)
例 5-5「ネストした表としてのプロシージャのパラメータの宣言」
(5-8 ページ)
例 5-7「%TYPE および %ROWTYPE を使用したコレクション要素型の指定」(5-8 ページ)
例 5-42「レコード型の宣言および初期化」(5-28 ページ)
例 6-1「PL/SQL を使用したデータ操作」
(6-2 ページ)
例 6-13「カーソルを使用したバルク・データのフェッチ」(6-11 ページ)
例 13-1「宣言および変数への値の代入」(13-5 ページ)
関連項目
「定数と変数の宣言」(13-24 ページ)
「%ROWTYPE 属性」
(13-102 ページ)
13-118
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
UPDATE 文
UPDATE 文
UPDATE 文は、表またはビューの中の 1 行以上の行にある指定された列の値を変更します。
UPDATE 文の詳細は、『Oracle Database SQL リファレンス』を参照してください。
構文
update statement ::=
table_reference
UPDATE
(
alias
subquery1
)
TABLE
(
subquery2
sql_expression
column_name
=
(
subquery3
)
,
SET
,
(
column_name
)
=
(
subquery4
)
search_condition
WHERE
CURRENT_OF
cursor_name
returning_clause
キーワードとパラメータの説明
alias
参照される表またはビューの別名(通常は短縮名)で、WHERE 句の中で頻繁に使用されます。
column_name
更新する列(または更新する複数の列の中の 1 つ)です。これは参照される表またはビューの
列の名前にしてください。column_name リストでは同じ列名を繰り返して使用できません。
UPDATE 文の列名は、表またはビューの中と同じ順序で指定する必要はありません。
returning_clause
更新された行から値を戻します。そのため、後で行を SELECT で選択する必要がありません。
取り出した列値は、変数かホスト変数、またはコレクションかホスト配列に代入できます。
RETURNING 句はリモートまたはパラレルでの更新には使用できません。文を実行しても行に影
響がない場合、RETURNING 句で指定した変数の値は未定義になります。returning_clause
の構文は、13-99 ページの「RETURNING INTO 句」を参照してください。
SET column_name = sql_expression
この句は sql_expression の値を、column_name によって識別される列に代入します。
sql_expression の中で、更新される表の列が参照されている場合、参照は現在行の列が対象
になります。古い列の値は、等号の右辺で使用されます。
SET column_name = (subquery3)
subquery3 でデータベースから取り出した値を、column_name によって識別される列に代入
します。この副問合せは、正確に 1 つの行と 1 つの列を戻す必要があります。
PL/SQL の言語要素
13-119
UPDATE 文
SET (column_name, column_name, ...)= (subquery4)
subquery4 でデータベースから取り出した値を、column_name リストにある列に代入しま
す。副問合せは、リストされている列すべてを含む 1 つの行のみを戻す必要があります。副問
合せによって戻された列値は、列リストの列に順番に代入されます。1 番目の値はリストの 1
番目の列に、2 番目の値はリストの 2 番目の列に、というように代入されます。
sql_expression
任意の有効な SQL の式です。詳細は、『Oracle Database SQL リファレンス』を参照してくださ
い。
subquery
処理する行セットを提供する SELECT 文です。構文は select_into_statement の構文と似
ていますが、INTO 句は使用できません。13-105 ページの「SELECT INTO 文」を参照してくだ
さい。
table_reference
表またはビューを指定します。指定された表またはビューは、UPDATE 文の実行時にアクセス
できる必要があり、ユーザーが UPDATE 権限を持つ必要があります。table_reference の構
文は、13-35 ページの「DELETE 文」を参照してください。
TABLE (subquery2)
TABLE のオペランドは、1 つの列値を戻す SELECT 文です。これはネストした表または
VARRAY である必要があります。演算子 TABLE は、値がスカラー値ではなくコレクションで
あることを Oracle に通知します。
WHERE CURRENT OF cursor_name
指定したカーソルに関連付けられている FETCH 文によって処理された最後の行を参照します。
カーソルは、FOR UPDATE であること、さらにオープンされていて行に置かれていることが必
要です。カーソルがオープンされていないと、CURRENT OF 句でエラーが発生します。カーソ
ルがオープンされていても、フェッチされた行がないか、最後のフェッチで行が戻されなかっ
た場合は、PL/SQL によって事前定義の例外 NO_DATA_FOUND が呼び出されます。
WHERE search_condition
データベース表の中の更新対象行を選択します。検索条件を満たす行のみが更新されます。こ
の句を省略すると、表の中のすべての行が更新されます。
使用上の注意
UPDATE WHERE CURRENT OF 文は、オープンされているカーソルからのフェッチ(カーソル
FOR ループで実行されるフェッチを含む)の後で使用できます。ただしそのためには、関連付
けられた問合せが FOR UPDATE である必要があります。この文は直前にフェッチされた行を更
新します。
暗黙的な SQL カーソルとカーソル属性 %NOTFOUND、%FOUND、%ROWCOUNT および %ISOPEN
を使用すると、UPDATE 文の実行に関する有用な情報にアクセスできます。
例
例 13-7 では、従業員 ID は正しく、名前は間違っている表を作成します。次に、相関問合せを
含む UPDATE 文を実行して、EMPLOYEES 表から正しい名前を取り出し、新しい表で名前を修
正します。
例 13-7 副問合せでの UPDATE の使用
-- Create a table with all the right IDs, but messed-up names
CREATE TABLE employee_temp AS
SELECT employee_id, UPPER(first_name) first_name,
13-120
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
UPDATE 文
TRANSLATE(last_name,'aeiou','12345') last_name
FROM employees;
BEGIN
-- Display the first 5 names to show they're messed up
FOR person IN (SELECT * FROM employee_temp WHERE ROWNUM < 6)
LOOP
DBMS_OUTPUT.PUT_LINE(person.first_name || ' ' || person.last_name);
END LOOP;
UPDATE employee_temp SET (first_name, last_name) =
(SELECT first_name, last_name FROM employees
WHERE employee_id = employee_temp.employee_id);
DBMS_OUTPUT.PUT_LINE('*** Updated ' || SQL%ROWCOUNT || ' rows. ***');
-- Display the first 5 names to show they've been fixed up
FOR person IN (SELECT * FROM employee_temp WHERE ROWNUM < 6)
LOOP
DBMS_OUTPUT.PUT_LINE(person.first_name || ' ' || person.last_name);
END LOOP;
END;
/
次の例を参照してください。
例 1-12「ストアド・サブプログラムの作成」(1-13 ページ)
例 4-1「単純な IF-THEN 文の使用」(4-2 ページ)
例 5-51「レコードを使用した行の更新」(5-33 ページ)
例 5-52「レコードを使用した RETURNING 句の使用」(5-34 ページ)
例 6-1「PL/SQL を使用したデータ操作」
(6-2 ページ)
例 6-5「CURRVAL と NEXTVAL の使用」
(6-4 ページ)
例 6-6「ROWNUM の使用」(6-5 ページ)
例 6-38「ROLLBACK と SAVEPOINT の併用」
(6-30 ページ)
例 6-41「CURRENT OF を使用した、カーソルからフェッチされた最新行の更新」(6-33 ペー
ジ)
例 7-1「動的 SQL の例」(7-3 ページ)
例 7-5「RETURNING BULK COLLECT INTO 句を使用した動的 SQL」(7-6 ページ)
例 7-6「FORALL 文中の動的 SQL」(7-7 ページ)
例 11-6「FORALL でのロールバックの使用」(11-11 ページ)
例 11-9「例外が発生しても継続するバルク操作」
(11-14 ページ)
関連項目
「データ操作」(6-2 ページ)
「DELETE 文」(13-35 ページ)
「FETCH 文」
(13-52 ページ)
「INSERT 文」
(13-65 ページ)
PL/SQL の言語要素
13-121
UPDATE 文
13-122
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
A
PL/SQL のソース・コードの不明瞭化
この付録では、スタンドアロンの wrap ユーティリティおよび DBMS_DDL パッケージのサブプ
ログラムを使用して、PL/SQL のソース・コードを不明瞭化(ラップ)する方法について説明
します。PL/SQL ユニットを不明瞭化(隠ぺい)すると、ソース・コードおよび実装の詳細を
隠したまま PL/SQL アプリケーションを配布できます。
この付録の項目は、次のとおりです。
■
不明瞭化
■
wrap ユーティリティを使用した PL/SQL コードの不明瞭化
■
DBMS_DDL サブプログラムを使用した PL/SQL コードの不明瞭化
参照 : DBMS_DDL パッケージの詳細は、
『Oracle Database PL/SQL パッ
ケージ・プロシージャおよびタイプ・リファレンス』を参照してくださ
い。
PL/SQL のソース・コードの不明瞭化
A-1
不明瞭化
不明瞭化
PL/SQL ユニットの不明瞭化(ラップ)とは、PL/SQL のソース・コードを隠す処理のことで
す。ラップを行うには、wrap ユーティリティおよび DBMS_DDL サブプログラムを使用します。
コマンドラインから実行する wrap ユーティリティによって、SQL*Plus のインストール・スク
リプトなどの入力 SQL ファイルが処理されます。DBMS_DDL サブプログラムでは、単一の
CREATE PROCEDURE コマンドなど、動的に生成された単一の PL/SQL ユニットがラップされ
ます。
wrap ユーティリティまたは DBMS_DDL パッケージのラップ・サブプログラムを使用して
PL/SQL ユニットのソース・コードを不明瞭化(隠ぺい)すると、次の利点があります。
■
■
■
■
他の開発者によるアプリケーションの間違った使用や、アルゴリズムの競合他社への公開
を防ぐことができます。
ソース・コードが USER_SOURCE、ALL_SOURCE または DBA_SOURCE データ・ディクショ
ナリ・ビューから参照されません。
不明瞭化されたソース・ファイルを SQL*Plus で処理できます。
インポート / エクスポート・ユーティリティで、ラップされたファイルを扱えます。ラッ
プされたプロシージャのバックアップまたは移動を実行できます。
PL/SQL ユニットの不明瞭化のヒント
PL/SQL ユニットを不明瞭化(ラップ)する場合は、次のことに注意してください。
■
■
■
パッケージまたはオブジェクト型をラップする場合は、仕様部ではなく、本体のみをラッ
プします。こうすると、他の開発者は、パッケージまたは型を使用するのに必要な情報を
見ることができますが、その実装は見えません。
ラップされたファイル内の PL/SQL ソースは編集できません。ラップされた PL/SQL コー
ドを変更するには、元のソース・ファイルを編集し、再度ラップします。エンド・ユー
ザーに出荷する用意ができるまでコードをラップしないようにするか、または構築環境で
ラッピング操作を行うことができます。
ソース・コードのすべての重要な部分が不明瞭化されていることを確認するために、配布
前に、ラップされたファイルをテキスト・エディタで表示してください。
不明瞭化の制限
PL/SQL のソース・コードを不明瞭化する場合には、次の制限があります。
■
■
■
■
A-2
コンパイル・ユニットをラップすると、アルゴリズムが隠ぺいされ、リバース・エンジニ
アリングの防止に役立ちますが、パスワードまたは表名を隠ぺいするための保護方法とし
てこの方法を使用しないことをお薦めします。PL/SQL ユニットを不明瞭化すると、ほと
んどのユーザーはソース・コードを確認できなくなりますが、すべてのユーザーに対して
隠ぺいできるとはかぎりません。
ラップでは、トリガー用のソース・コードは不明瞭化されません。ラップされたプロシー
ジャをコールする 1 行トリガーを記述すると、トリガーの動作を隠すことができます。
ラップでは、PL/SQL コードを不明瞭化すると、runaway string などのトークン化エラー
のみが検出されます。ラップでは、表またはビューが存在しないなどのセマンティック・
エラーは検出されません。これらのエラーは、PL/SQL コンパイル時または SQL*Plus で
出力ファイルを実行したときに検出されます。
不明瞭化された PL/SQL プログラム・ユニットは、以前のリリースのデータベースにイン
ポートできません。ラップされたコンパイル・ユニットは、Oracle リリース間での上位互
換性はありますが、下位互換性はありません。たとえば、リリース 8.1.5 の wrap ユーティ
リティで処理されたファイルは、リリース 8.1.6 の Oracle データベースにロードできます
が、リリース 8.1.6 の wrap ユーティリティで処理されたファイルは、リリース 8.1.5 の
Oracle データベースにロードできません。
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
wrap ユーティリティを使用した PL/SQL コードの不明瞭化
wrap ユーティリティの制限
■
■
ソース・コードは SQL*Plus ではなく PL/SQL コンパイラで解析されるため、PL/SQL コー
ドに SQL*Plus の DEFINE 表記法を使用して置換変数を含めることはできません。他の不
明瞭化しない SQL 文では、置換変数を使用できます。
ラップされたファイルでは、ほとんどのコメントが削除されます。A-3 ページの「PL/SQL
の wrap ユーティリティの入力ファイルと出力ファイル」を参照してください。
DBMS_DDL の wrap ファンクションの制限
■
DBMS_DDL.WRAP の出力で DBMS_SQL.PARSE を起動する場合(32767 バイトを超えるテキス
トに対する文の仮パラメータのデータ型が VARCHAR2A または VARCHAR2S であるオー
バーロードを使用するとき)は、LFFLG パラメータに FALSE を設定する必要があります。
設定しないと、DBMS_SQL.PARSE によって、ラップされたユニットに改行が追加されるた
め、ユニットが破損します。
wrap ユーティリティを使用した PL/SQL コードの不明瞭化
wrap ユーティリティでは、入力 SQL ファイルが処理されて、パッケージ仕様部、パッケージ
本体、ファンクション、プロシージャ、型仕様部、型本体など、ファイル内の PL/SQL ユニッ
トのみが不明瞭化されます。無名ブロックの PL/SQL コンテンツ、トリガーまたは PL/SQL 以
外のコードは不明瞭化されません。
wrap ユーティリティを実行するには、次の構文を使用して、オペレーティング・システム・プ
ロンプトで wrap コマンドを入力します。
wrap iname=input_file [oname=output_file]
等号の前後には空白を使用しないでください。
input_file は、通常、SQL*Plus を使用して実行する、SQL 文を含むファイルの名前です。
ファイル拡張子を省略すると、拡張子は .sql であるとみなされます。たとえば、次のコマン
ドは同じ意味を持ちます。
wrap iname=/mydir/myfile
wrap iname=/mydir/myfile.sql
次のように、異なるファイル拡張子を指定することもできます。
wrap iname=/mydir/myfile.src
output_file は、作成するファイル(不明瞭化されたファイル)の名前です。oname は任意
に指定します。出力ファイル名はデフォルトで入力ファイルの名前となり、拡張子はデフォル
トで .plb となります。たとえば、次のコマンドは同じ意味を持ちます。
wrap iname=/mydir/myfile
wrap iname=/mydir/myfile.sql oname=/mydir/myfile.plb
次に示すように、oname オプションを使用して、異なるファイル名と拡張子を指定できます。
wrap iname=/mydir/myfile oname=/yourdir/yourfile.out
PL/SQL の wrap ユーティリティの入力ファイルと出力ファイル
入力ファイルでは、SQL 文を任意に組み合せることができます。ほとんどの文はそのままの形
で渡されます。サブプログラム、パッケージまたはオブジェクト型を定義する CREATE 文は、
不明瞭化されます。これらの文の本体は、隠ぺいされた(ただし PL/SQL コンパイラが理解可
能な)形式に置き換えられます。
PL/SQL のソース・コードの不明瞭化
A-3
wrap ユーティリティを使用した PL/SQL コードの不明瞭化
次の CREATE 文は不明瞭化されます。
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
[OR
[OR
[OR
[OR
[OR
[OR
[OR
REPLACE]
REPLACE]
REPLACE]
REPLACE]
REPLACE]
REPLACE]
REPLACE]
FUNCTION function_name
PROCEDURE procedure_name
PACKAGE package_name
PACKAGE BODY package_name
TYPE type_name AS OBJECT
TYPE type_name UNDER type_name
TYPE BODY type_name
CREATE [OR REPLACE] TRIGGER 文および [DECLARE] BEGIN..END 無名ブロックは不明
瞭化されません。その他の SQL 文はすべて、そのままの形で出力ファイルに渡されます。
CREATE OR REPLACE ヘッダー内のコメント行および C 形式のコメント(/* */ で区切られ
る)を除いて、ラップされるユニットのすべてのコメント行が削除されます。
出力ファイルはテキスト・ファイルです。このファイルを SQL*Plus でスクリプトとして実行
し、PL/SQL プロシージャ、ファンクションおよびパッケージを設定できます。ラップされた
ファイルは、次のように実行します。
SQL> @wrapped_file_name.plb;
wrap ユーティリティの実行
たとえば、wrap_test.sql ファイルの内容が次のとおりであるとします。
CREATE PROCEDURE wraptest IS
TYPE emp_tab IS TABLE OF employees%ROWTYPE INDEX BY PLS_INTEGER;
all_emps
emp_tab;
BEGIN
SELECT * BULK COLLECT INTO all_emps FROM employees;
FOR i IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE('Emp Id: ' || all_emps(i).employee_id);
END LOOP;
END;
/
ファイルをラップするには、オペレーティング・システム・プロンプトで次のように実行しま
す。
wrap iname=wrap_test.sql
wrap ユーティリティの出力は、次のようになります。
PL/SQL Wrapper: Release 10.2.0.0.0 on Tue Apr 26 16:47:39 2005
Copyright (c) 1993, 2005, Oracle.All rights reserved.
Processing wrap_test.sql to wrap_test.plb
wrap_test.plb テキスト・ファイルの内容を確認すると、1 行目に CREATE PROCEDURE
wraptest wrapped が表示され、ファイルの残りの内容は表示されません。
SQL*Plus で wrap_test.plb を実行し、ファイルの SQL 文を実行するには、次のように入力
します。
SQL> @wrap_test.plb
wrap_test.plb を実行した後、作成されたプロシージャを実行できます。
SQL> CALL wraptest();
A-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
DBMS_DDL サブプログラムを使用した PL/SQL コードの不明瞭化
DBMS_DDL サブプログラムを使用した PL/SQL コードの不明瞭化
DBMS_DDL パッケージには、パッケージ仕様部、パッケージ本体、ファンクション、プロシー
ジャ、型仕様部、型本体など、単一の PL/SQL ユニットを不明瞭化するプロシージャが含まれ
ます。オーバーロードされるこれらのサブプログラムには、データベースに作成される動的生
成 PL/SQL プログラム・ユニットを不明瞭化するメカニズムが備えられています。
DBMS_DDL パッケージには、WRAP ファンクションおよび CREATE_WRAPPED プロシージャが含
まれます。CREATE_WRAPPED では、テキストのラップおよび PL/SQL ユニットの作成の両方
が行われます。名前の競合および他のユーザが DBMS_DDL というローカル・パッケージを作成
していたり、DBMS_DDL パブリック・シノニムを定義している場合の危険性を回避するために、
ラップ・プロシージャをコールする場合は、パッケージの完全修飾名 SYS.DBMS_DDL を使用
してください。入力 CREATE OR REPLACE 文は、DBMS_DDL.WRAP() または
DBMS_DDL.CREATE_WRAPPED() を起動するユーザーの権限で実行されます。
また、DBMS_DDL パッケージには、ラップ・プロシージャへの入力が有効な PL/SQL ユニット
でない場合に発生する MALFORMED_WRAP_INPUT 例外(ORA-24230)も含まれます。
DBMS_DDL の create_wrapped プロシージャの使用
例 A-1 に、CREATE_WRAPPED を使用して、データベースにパッケージ仕様部およびパッケー
ジ本体を動的に作成およびラップする方法を示します。
例 A-1 CREATE_WRAPPED プロシージャを使用したパッケージのラップ
DECLARE
-- the package_text variable contains the text to create the package spec and body
package_text VARCHAR2(32767);
FUNCTION generate_spec (pkgname VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN 'CREATE PACKAGE ' || pkgname || ' AS
PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER);
PROCEDURE fire_employee (emp_id NUMBER);
END ' || pkgname || ';';
END generate_spec;
FUNCTION generate_body (pkgname VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN 'CREATE PACKAGE BODY ' || pkgname || ' AS
PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) IS
BEGIN
UPDATE employees SET salary = salary + amount WHERE employee_id = emp_id;
END raise_salary;
PROCEDURE fire_employee (emp_id NUMBER) IS
BEGIN
DELETE FROM employees WHERE employee_id = emp_id;
END fire_employee;
END ' || pkgname || ';';
END generate_body;
BEGIN
package_text := generate_spec('emp_actions'); -- generate package spec
SYS.DBMS_DDL.CREATE_WRAPPED(package_text); -- create and wrap the package spec
package_text := generate_body('emp_actions'); -- generate package body
SYS.DBMS_DDL.CREATE_WRAPPED(package_text); -- create and wrap the package body
END;
/
-- call a procedure from the wrapped package
CALL emp_actions.raise_salary(120, 100);
PL/SQL のソース・コードの不明瞭化
A-5
DBMS_DDL サブプログラムを使用した PL/SQL コードの不明瞭化
*_SOURCE ビューを表示しても、ソースがラップされている(表示されない)ため、他のユー
ザーはコードの詳細を見ることができません。次に例を示します。
SELECT text FROM USER_SOURCE WHERE name = 'EMP_ACTIONS';
出力結果は、次のようになります。
TEXT
--------------------------------------------------------------PACKAGE emp_actions wrapped
a000000
1f
abcd
...
A-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
B
PL/SQL での識別子名の解決
この付録では、潜在的に意味の曖昧なプロシージャ文および SQL 文で、名前への参照を
PL/SQL がどのように解決するかについて説明します。
この付録の項目は、次のとおりです。
■
名前解決
■
修飾名およびドット表記法の例
■
PL/SQL と SQL の名前解決の相違点
■
取得の理解
■
DML 文の内部取得の回避
■
オブジェクト属性およびメソッドへの参照の修飾
PL/SQL での識別子名の解決
B-1
名前解決
名前解決
コンパイルの際に、PL/SQL コンパイラは、PL/SQL サブプログラムの各名前と関連付けるオ
ブジェクトを判別します。名前は、ローカル変数、表、パッケージ、プロシージャ、スキーマ
などを参照する場合があります。オブジェクトが作成または削除されている場合、サブプログ
ラムが再コンパイルされると、その関連付けが変更されることがあります。
内部有効範囲における宣言または定義で、外部有効範囲における別の宣言または定義が隠され
る可能性があります。PL/SQL の名前では大 / 小文字が区別されないため、例 B-1 では、
client 変数の宣言によって Client データ型の定義が隠されています。
例 B-1 グローバル変数名およびローカル変数名の解決
BEGIN
<<block1>>
DECLARE
TYPE Client IS RECORD ( first_name VARCHAR2(20), last_name VARCHAR2(25) );
TYPE Customer IS RECORD ( first_name VARCHAR2(20), last_name VARCHAR2(25) );
BEGIN
DECLARE
client Customer; -- hides definition of type Client in outer scope
-- lead1 Client; -- not allowed; Client resolves to the variable client
lead2 block1.Client; -- OK; refers to type Client
BEGIN
NULL; -- no processing, just an example of name resolution
END;
END;
END;
/
ブロック・ラベル block1 で参照を修飾すると、Client データ型を参照できます。
次の CREATE TYPE 文では、2 つ目の文によって警告が生成されます。manager という名前の
属性を作成すると、manager という名前の型が隠されるため、2 つ目の属性の宣言は適切に実
行されません。
CREATE TYPE manager AS OBJECT (dept NUMBER);
/
CREATE TYPE person AS OBJECT (manager NUMBER, mgr manager) -- raises a warning;
/
修飾名およびドット表記法の例
名前解決の際、コンパイラは、単なる未修飾の名前、ドットで区切られて連鎖した識別子、コ
レクションの索引付きのコンポーネントなど、様々な種類の参照に遭遇する可能性があります。
例 B-2 を参照してください。
例 B-2 ドット表記法を使用した名前の修飾
CREATE OR REPLACE PACKAGE pkg1 AS
m NUMBER;
TYPE t1 IS RECORD (a NUMBER);
v1 t1;
TYPE t2 IS TABLE OF t1 INDEX BY PLS_INTEGER;
v2 t2;
FUNCTION f1 (p1 NUMBER) RETURN t1;
FUNCTION f2 (q1 NUMBER) RETURN t2;
END pkg1;
/
CREATE OR REPLACE PACKAGE BODY pkg1 AS
FUNCTION f1 (p1 NUMBER) RETURN t1 IS
B-2
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
修飾名およびドット表記法の例
--------------------
n NUMBER;
BEGIN
(1) unqualified name
n := m;
(2) dot-separated chain of identifiers (package name used as scope
qualifier followed by variable name)
n := pkg1.m;
(3) dot-separated chain of identifiers (package name used as scope
qualifier followed by function name also used as scope qualifier
followed by parameter name)
n := pkg1.f1.p1;
(4) dot-separated chain of identifiers (variable name followed by
component selector)
n := v1.a;
(5) dot-separated chain of identifiers (package name used as scope
qualifier followed by variable name followed by component selector)
n := pkg1.v1.a;
(6) indexed name followed by component selector
n := v2(10).a;
(7) function call followed by component selector
n := f1(10).a;
(8) function call followed by indexing followed by component selector
n := f2(10)(10).a;
(9) function call (which is a dot-separated chain of identifiers,
including schema name used as scope qualifier followed by package
name used as scope qualifier followed by function name)
followed by component selector of the returned result followed
by indexing followed by component selector
n := hr.pkg1.f2(10)(10).a;
(10) variable name followed by component selector
v1.a := p1;
RETURN v1;
END f1;
FUNCTION f2 (q1 NUMBER) RETURN t2 IS
v_t1 t1;
v_t2 t2;
BEGIN
v_t1.a := q1;
v_t2(1) := v_t1;
RETURN v_t2;
END f2;
END pkg1;
/
ファンクション本体で宣言されているプライベート変数への外部参照は、無効です。たとえば、
ファンクション f2 の hr.pkg1.f1.n など、ファンクション f1 で宣言されている変数 n への
外部参照によってエラーが発生します。9-8 ページの「パッケージのプライベート項目とパブ
リック項目」を参照してください。
ドット表記法を使用して名前を指定する方法の追加例
ドット表記法は、レコード・フィールド、オブジェクト属性、およびパッケージや他のスキー
マ内の項目を識別するために使用します。これらの項目を組み合せる際、複数レベルのドット
を含む式を使用する必要がある場合がありますが、その場合は各ドットが示すものがわかりに
くくなることもあります。組合せの例を次に示します。
ファンクションの戻り値のフィールドまたは属性
func_name().field_name
func_name().attribute_name
PL/SQL での識別子名の解決
B-3
PL/SQL と SQL の名前解決の相違点
別のスキーマが所有するスキーマ・オブジェクト
schema_name.table_name
schema_name.procedure_name()
schema_name.type_name.member_name()
別のユーザーが所有するパッケージ・オブジェクト
schema_name.package_name.procedure_name()
schema_name.package_name.record_name.field_name
オブジェクト型を含むレコード
record_name.field_name.attribute_name
record_name.field_name.member_name()
PL/SQL と SQL の名前解決の相違点
PL/SQL と SQL の名前解決ルールはよく似ています。取得回避規則に従っている場合は、いく
つかの違いは回避できます。互換性のため、SQL ルールは PL/SQL と比較して、より許容性が
高くなっています。そのほとんどが状況依存な SQL ルールでは、PL/SQL ルールで認識される
よりも多くの状況と DML 文が、有効なものと認識されます。
■
■
PL/SQL コンパイラが DML 文などの SQL 文を処理する場合、PL/SQL では、SQL と同じ名
前解決ルールが使用されます。たとえば、HR.JOBS という名前の場合、SQL では、まず
HR スキーマでオブジェクトが検索され、次に現行スキーマでパッケージ、型、表および
ビューが検索されます。
PL/SQL では、代入やプロシージャのコールなどの PL/SQL 文の名前は、異なる順序で解
決されます。HR.JOBS という名前の場合、PL/SQL では、まず現行スキーマで HR という
名前のパッケージ、型、表およびビューが検索され、次に HR スキーマでオブジェクトが
検索されます。
SQL ネーミング規則については、
『Oracle Database SQL リファレンス』を参照してください。
取得の理解
別の有効範囲における宣言または型の定義が参照の正常な解決の妨げになる場合、その宣言ま
たは定義が参照を「取得する」と呼びます。通常、これは移行またはスキーマのアップグレー
ドの結果として生じます。取得には、内部、同一有効範囲および外部の 3 種類があります。内
部および同一有効範囲の取得は SQL スコープにのみ適用されます。
内部取得
内部取得が発生するのは、内部有効範囲に含まれる名前が外部有効範囲のエンティティを参照
しておらず、次のような状態が発生した場合です。
■
■
内部有効範囲に含まれるエンティティに名前が解決される場合。
識別子の一部が内部有効範囲に取得され、参照を完全に解決することができず、プログラ
ムでエラーが発生する場合。
参照が別の有効な名前を指す場合、プログラムが目的と異なる動作を行う理由を認識できない
可能性があります。
次の例では、内側の SELECT 文における col2 への参照は、表 tab2 が col2 という名前の列
を持たないため、表 tab1 の列 col2 にバインドされます。
CREATE
INSERT
CREATE
INSERT
TABLE tab1 (col1
INTO tab1 VALUES
TABLE tab2 (col1
INTO tab2 VALUES
NUMBER, col2 NUMBER);
(100, 10);
NUMBER);
(100);
CREATE OR REPLACE PROCEDURE proc AS
B-4
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
取得の理解
CURSOR c1 IS SELECT * FROM tab1
WHERE EXISTS (SELECT * FROM tab2 WHERE col2 = 10);
BEGIN
NULL;
END;
/
この例で、次に示すように、表 tab2 に列 col2 を追加した場合を考えます。
ALTER TABLE tab2 ADD (col2 NUMBER);
この場合には、プロシージャ proc は無効となり、次に使用する際に、自動的に再コンパイル
されます。ただし、再コンパイルの際に、tab2 は内部有効範囲にあるため、内側の SELECT
文の col2 は tab2 の列 col2 にバインドされます。したがって、表 tab2 への列 col2 の追加
によって、col2 への参照は取得されます。
コレクションやオブジェクト型を使用することによって、さらに多くの内部取得が発生する可
能性があります。次の例では、hr.tab2.a への参照は、問合せの外部有効範囲で参照すること
のできる表の別名 hr を経由して、表 tab1 の列 tab2 の属性 a に解決されます。
CREATE
/
CREATE
INSERT
CREATE
INSERT
TYPE type1 AS OBJECT (a NUMBER);
TABLE tab1 (tab2 type1);
INTO tab1 VALUES ( type1(10) );
TABLE tab2 (x NUMBER);
INTO tab2 VALUES ( 10 );
-- in the following, alias tab1 with same name as schema name, which
-- is not a good practice but is used here for illustration purpose
-- note lack of alias in second SELECT
SELECT * FROM tab1 hr
WHERE EXISTS (SELECT * FROM hr.tab2 WHERE x = hr.tab2.a);
この例で、内側の副問合せに現れる表 hr.tab2 に列名 a を追加することを考えます。問合せ
が処理されると、hr.tab2.a への参照がスキーマ hr 内の表 tab2 の列 a に解決されるため、
内部取得が発生します。内部取得を防止するには、B-6 ページの「DML 文の内部取得の回避」
で説明するルールに従います。これらのルールに従えば、この問合せは、次のように書き換わ
ります。
SELECT * FROM hr.tab1 p1
WHERE EXISTS (SELECT * FROM hr.tab2 p2 WHERE p2.x = p1.tab2.a);
同一有効範囲の取得
SQL スコープで、同一有効範囲の取得が発生するのは、結合に使用される 2 つの表のどちらか
に列が追加され、どちらの表にも同じ列名が存在する場合です。結合問合せのその列名を事前
に参照できます。エラーを回避するには、列名を表名で修飾する必要があります。
外部取得
外部取得が発生するのは、過去に内部有効範囲内のエンティティに解決されていた内部有効範
囲内の名前が、外部有効範囲に解決された場合です。SQL と PL/SQL は、外部取得を防止する
設計になっています。この状態を回避するためのアクションは必要ありません。
PL/SQL での識別子名の解決
B-5
DML 文の内部取得の回避
DML 文の内部取得の回避
次のルールを遵守することによって、DML 文における内部取得を防止できます。
■
DML 文内の各表に対して別名を指定します。
■
DML 文の全体を通じて、表の別名を一意に保ちます。
■
問合せ内で使用されているスキーマ名と一致する表の別名の使用を避けます。
■
列の参照を表の別名で修飾します。
文がユーザー定義のオブジェクト型の列を持つ表を参照している場合には、
schema_name.table_name で参照を修飾しても内部取得は防止できません。
オブジェクト属性およびメソッドへの参照の修飾
ユーザー定義のオブジェクト型の列によって、より多くの内部取得が発生する可能性がありま
す。問題を最小限に抑えるため、表の別名の使用に関する次のルールが名前解決アルゴリズム
に含まれています。
属性およびメソッドへの参照
属性およびメソッドへのすべての参照が、表の別名によって修飾されている必要があります。
表を参照する場合、その表に格納されているオブジェクトの属性やメソッドを参照するときに
は、表名に別名を添付する必要があります。次の例に示すとおり、属性またはメソッドへの列
修飾された参照は、その参照に接頭辞として表名が使用されている場合は使用できません。
CREATE TYPE t1 AS OBJECT (x NUMBER);
/
CREATE TABLE tb1 (col1 t1);
BEGIN
-- following inserts are allowed without an alias
-- because there is no column list
INSERT INTO tb1 VALUES ( t1(10) );
INSERT INTO tb1 VALUES ( t1(20) );
INSERT INTO tb1 VALUES ( t1(30) );
END;
/
BEGIN
UPDATE tb1 SET col1.x = 10 WHERE col1.x = 20; -- error, not allowed
END;
/
BEGIN
UPDATE tb1 SET tb1.col1.x = 10 WHERE tb1.col1.x = 20; -- not allowed
END;
/
BEGIN
UPDATE hr.tb1 SET hr.tb1.col1.x = 10 WHERE hr.tb1.col1.x = 20; -- not allowed
END;
/
BEGIN -- following allowed with table alias
UPDATE hr.tb1 t set t.col1.x = 10 WHERE t.col1.x = 20;
END;
/
DECLARE
y NUMBER;
BEGIN -- following allowed with table alias
SELECT t.col1.x INTO y FROM tb1 t WHERE t.col1.x = 30;
END;
/
BEGIN
DELETE FROM tb1 WHERE tb1.col1.x = 10; -- not allowed
B-6
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
オブジェクト属性およびメソッドへの参照の修飾
END;
/
BEGIN -- following allowed with table alias
DELETE FROM tb1 t WHERE t.col1.x = 10;
END;
/
行の式への参照
行の式は、表の別名への参照として解決する必要があります。行の式を REF および VALUE に
渡したり、UPDATE 文の SET 句に行の式を使用できます。次に例を示します。
CREATE TYPE t1 AS OBJECT (x number);
/
CREATE TABLE ot1 OF t1;
BEGIN
-- following inserts are allowed without an alias
-- because there is no column list
INSERT INTO ot1 VALUES ( t1(10) );
INSERT INTO ot1 VALUES ( 20 );
INSERT INTO ot1 VALUES ( 30 );
END;
/
BEGIN
UPDATE ot1 SET VALUE(ot1.x) = t1(20) WHERE VALUE(ot1.x) = t1(10); -- not allowed
END;
/
BEGIN -- following allowed with table alias
UPDATE ot1 o SET o = (t1(20)) WHERE o.x = 10;
END;
/
DECLARE
n_ref REF t1;
BEGIN -- following allowed with table alias
SELECT REF(o) INTO n_ref FROM ot1 o WHERE VALUE(o) = t1(30);
END;
/
DECLARE
n t1;
BEGIN -- following allowed with table alias
SELECT VALUE(o) INTO n FROM ot1 o WHERE VALUE(o) = t1(30);
END;
/
DECLARE
n NUMBER;
BEGIN -- following allowed with table alias
SELECT o.x INTO n FROM ot1 o WHERE o.x = 30;
END;
/
BEGIN
DELETE FROM ot1 WHERE VALUE(ot1) = (t1(10)); -- not allowed
END;
/
BEGIN -- folowing allowed with table alias
DELETE FROM ot1 o WHERE VALUE(o) = (t1(20));
END;
/
PL/SQL での識別子名の解決
B-7
オブジェクト属性およびメソッドへの参照の修飾
B-8
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
C
PL/SQL のプログラム上の制限
この付録では、PL/SQL 言語によって課されるプログラム上の制限について説明します。
PL/SQL はプログラミング言語 Ada をベースにしています。したがって PL/SQL では、ツリー
構造の中間言語、DIANA(Descriptive Intermediate Attributed Notation for Ada)を使用して
います。この中間言語は、インタフェース定義言語(IDL)と呼ばれるメタ表記を使用して定
義されます。DIANA は、コンパイラなどのツールによって内部的に使用されます。
PL/SQL のソース・コードはコンパイル時に機械可読の m コードに変換されます。1 つのプロ
シージャまたはパッケージに対応する DIANA および m コードの両方がデータベースに格納さ
れます。実行時に DIANA と m コードは共有メモリー・プール内にロードされます。DIANA
は依存プロシージャのコンパイルに使用され、m コードはそのまま実行されます。
共有メモリー・プールの場合、パッケージ仕様部、オブジェクト型仕様部、スタンドアロン・
サブプログラムまたは無名ブロックは、67108864(2**26)個の DIANA ノードに制限されてい
ます。ノードは、識別子、キーワード、演算子などのトークンに対応します。PL/SQL コンパ
イラによる制限を超えないかぎり、6,000,000 行以下のコードが許されます。PL/SQL コンパイ
ラによる一部の制限を表 C-1 に示します。
表 C-1 PL/SQL コンパイラの制限
項目
制限
プログラム・ユニットに渡されるバインド変数
32768
プログラム・ユニット内の例外ハンドラ
65536
レコード内のフィールド
65536
ブロック・ネストのレベル
255
レコード・ネストのレベル
32
副問合せネストのレベル
254
ラベル・ネストのレベル
98
ネストしたコレクションのレベル
事前定義された制限なし
BINARY_INTEGER 値の絶対値
-2147483648..2147483647
PLS_INTEGER 値の絶対値
-2147483648..2147483647
明示カーソル、ファンクション、プロシージャでの
仮パラメータの数
65536
プログラム・ユニットから参照されるオブジェクト
65536
FLOAT 値(2 進数)の精度
126
NUMBER 値(10 進数)の精度
38
REAL 値(2 進数)の精度
63
識別子のサイズ(文字)
30
文字列リテラルのサイズ(バイト)
32767
PL/SQL のプログラム上の制限
C-1
表 C-1 PL/SQL コンパイラの制限(続き)
項目
制限
CHAR 値(バイト)のサイズ
32767
LONG 値(バイト)のサイズ
32760
LONG RAW 値(バイト)のサイズ
32760
RAW 値(バイト)のサイズ
32767
VARCHAR2 値(バイト)のサイズ
32767
NCHAR 値(バイト)のサイズ
32767
NVARCHAR2 値(バイト)のサイズ
32767
BFILE 値(バイト)のサイズ
4G × DB_BLOCK_SIZE パラメータの値
BLOB 値(バイト)のサイズ
4G × DB_BLOCK_SIZE パラメータの値
CLOB 値(バイト)のサイズ
4G × DB_BLOCK_SIZE パラメータの値
NCLOB 値(バイト)のサイズ
4G × DB_BLOCK_SIZE パラメータの値
プログラム・ユニットに必要なメモリー量を見積もるときには、データ・ディクショナリ・
ビュー user_object_size を使用して問い合せることができます。parsed_size という列
に、フラット化された DIANA のバイト・サイズが戻ります。次に例を示します。
SQL> SELECT * FROM user_object_size WHERE name = 'PKG1';
NAME TYPE
SOURCE_SIZE PARSED_SIZE CODE_SIZE ERROR_SIZE
---------------------------------------------------------------PKG1 PACKAGE
46
165
119
0
PKG1 PACKAGE BODY
82
0
139
0
ただし、サイズの解析結果から DIANA ノードの数を見積もることはできません。解析後のサ
イズが同じプログラム・ユニットが 2 つあり、一方に必要な DIANA ノードの数が 1500 に対し
て、他方に必要なのが 2000 である(2 番目のユニットに含まれる SQL 文が複雑であるなどの理
由で)場合もあるためです。
PL/SQL ブロック、サブプログラム、パッケージまたはオブジェクト型のいずれかのサイズが
上限を超えると、
「PLS-00123: プログラムが大きすぎます。
」などのエラーとなります。多く
の場合、この問題はパッケージまたは無名ブロックで発生します。パッケージの場合、最良の
方法は複数個のより小さなパッケージに分けることです。無名ブロックの場合、最良の方法は
サブプログラムのグループとして再定義し、データベースに格納できるようにすることです。
データ型の制限の詳細は、第 3 章「PL/SQL のデータ型」を参照してください。コレクション
の添字の制限については、5-11 ページの「コレクション要素の参照」を参照してください。
C-2
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
D
PL/SQL の予約語およびキーワード
この付録では、PL/SQL で使用するために予約されている予約語のリストを示します。定数、
変数、カーソルなどのプログラム・オブジェクト、および列、表、索引などのスキーマ・オブ
ジェクトの名前には使用しないでください。
PL/SQL で予約されているこれらの語は、キーワードまたは予約語として分類されています。
表 D-1 および表 D-2 を参照してください。予約語は、識別子として使用できません。キーワー
ドは識別子として使用できますが、お薦めしません。
これらの単語には、SQL の予約語もあります。Oracle データベースの予約語のリストは、
『Oracle Database SQL リファレンス』を参照してください。すべてのキーワードおよび予約語
のリストは、
『Oracle Database リファレンス』で説明されているように、V$RESERVED_WORDS
ビューを使用して生成できます。
表 D-1 に、PL/SQL の予約語を示します。
表 D-1 PL/SQL の予約語
頭文字 :
予約語
A
ALL、ALTER、AND、ANY、ARRAY、ARROW、AS、ASC、AT
B
BEGIN、BETWEEN、BY
C
CASE、CHECK、CLUSTERS、CLUSTER、COLAUTH、COLUMNS、COMPRESS、CONNECT、CRASH、
CREATE、CURRENT
D
DECIMAL、DECLARE、DEFAULT、DELETE、DESC、DISTINCT、DROP
E
ELSE、END、EXCEPTION、EXCLUSIVE、EXISTS
F
FETCH、FORM、FOR、FROM
G
GOTO、GRANT、GROUP
H
HAVING
I
IDENTIFIED、IF、IN、INDEXES、INDEX、INSERT、INTERSECT、INTO、IS
L
LIKE、LOCK
M
MINUS、MODE
N
NOCOMPRESS、NOT、NOWAIT、NULL
O
OF、ON、OPTION、OR、ORDER,OVERLAPS
P
PRIOR、PROCEDURE、PUBLIC
R
RANGE、RECORD、RESOURCE、REVOKE
S
SELECT、SHARE、SIZE、SQL、START、SUBTYPE
T
TABAUTH、TABLE、THEN、TO、TYPE
U
UNION、UNIQUE、UPDATE、USE
V
VALUES、VIEW、VIEWS
W
WHEN、WHERE、WITH
PL/SQL の予約語およびキーワード
D-1
表 D-2 に、PL/SQL のキーワードを示します。
表 D-2 PL/SQL のキーワード
頭文字 :
キーワード
A
A、ADD、AGENT、AGGREGATE、ARRAY、ATTRIBUTE、AUTHID、AVG
B
BFILE_BASE、BINARY、BLOB_BASE、BLOCK、BODY、BOTH、BOUND、BULK、BYTE
C
C、CALL、CALLING、CASCADE、CHAR、CHAR_BASE、CHARACTER、CHARSETFORM、
CHARSETID、CHARSET、CLOB_BASE、CLOSE、COLLECT、COMMENT、COMMIT、COMMITTED、
COMPILED、CONSTANT、CONSTRUCTOR、CONTEXT、CONVERT、COUNT、CURSOR、
CUSTOMDATUM
D
DANGLING、DATA、DATE、DATE_BASE、DAY、DEFINE、DETERMINISTIC、DOUBLE、DURATION
E
ELEMENT、ELSIF、EMPTY、ESCAPE、EXCEPT、EXCEPTIONS、EXECUTE、EXIT、EXTERNAL
F
FINAL、FIXED、FLOAT、FORALL、FORCE、FUNCTION
G
GENERAL
H
HASH、HEAP、HIDDEN、HOUR
I
IMMEDIATE、INCLUDING、INDICATOR、INDICES、INFINITE、INSTANTIABLE、INT、INTERFACE、
INTERVAL、INVALIDATE、ISOLATION
J
JAVA
L
LANGUAGE、LARGE、LEADING、LENGTH、LEVEL、LIBRARY、LIKE2、LIKE4、LIKEC、LIMIT、
LIMITED、LOCAL、LONG、LOOP
M
MAP、MAX、MAXLEN、MEMBER、MERGE、MIN、MINUTE、MOD、MODIFY、MONTH、
MULTISET
N
NAME、NAN、NATIONAL、NATIVE、NCHAR、NEW、NOCOPY、NUMBER_BASE
O
OBJECT、OCICOLL、OCIDATETIME、OCIDATE、OCIDURATION、OCIINTERVAL、
OCILOBLOCATOR、OCINUMBER、OCIRAW、OCIREFCURSOR、OCIREF、OCIROWID、OCISTRING、
OCITYPE、ONLY、OPAQUE、OPEN、OPERATOR、ORACLE、ORADATA、ORGANIZATION、
ORLANY、ORLVARY、OTHERS、OUT、OVERRIDING
P
PACKAGE、PARALLEL_ENABLE、PARAMETER、PARAMETERS、PARTITION、PASCAL、PIPE、
PIPELINED、PRAGMA、PRECISION、PRIVATE
R
RAISE、RANGE、RAW、READ、RECORD、REF、REFERENCE、REM、REMAINDER、RENAME、
RESULT、RETURN、RETURNING、REVERSE、ROLLBACK、ROW
S
SAMPLE、SAVE、SAVEPOINT、SB1、SB2、SB4、SECOND、SEGMENT、SELF、SEPARATE、
SEQUENCE、SERIALIZABLE、SET、SHORT、SIZE_T、SOME、SPARSE、SQLCODE、SQLDATA、
SQLNAME、SQLSTATE、STANDARD、STATIC、STDDEV、STORED、STRING、STRUCT、STYLE、
SUBMULTISET、SUBPARTITION、SUBSTITUTABLE、SUBTYPE、SUM、SYNONYM
T
TDO、THE、TIME、TIMESTAMP、TIMEZONE_ABBR、TIMEZONE_HOUR、TIMEZONE_MINUTE、
TIMEZONE_REGION、TRAILING、TRANSAC、TRANSACTIONAL、TRUSTED、TYPE
U
UB1、UB2、UB4、UNDER、UNSIGNED、UNTRUSTED、USE、USING
V
VALIST、VALUE、VARIABLE、VARIANCE、VARRAY、VARYING、VOID
W
WHILE、WORK、WRAPPED、WRITE
Y
YEAR
Z
ZONE
D-2
Oracle Database PL/SQL ユーザーズ・ガイドおよびリファレンス
索引
記号
%BULK_EXCEPTIONS,「BULK_EXCEPTIONS カーソル
属性」を参照
%BULK_ROWCOUNT,「BULK_ROWCOUNT カーソル
属性」を参照
%FOUND,「FOUND カーソル属性」を参照
%ISOPEN,「ISOPEN カーソル属性」を参照
%NOTFOUND,「NOTFOUND カーソル属性」を参照
%ROWCOUNT,「ROWCOUNT カーソル属性」を参照
%ROWTYPE, 「ROWTYPE 属性」を参照
%TYPE, 「TYPE 属性」を参照
:= 代入演算子,1-6
|| 連結演算子,2-23
. 項目のセパレータ,2-2
\,2-2
.. 範囲演算子,2-2,4-9
=, !=, \ および~ = 関係演算子,2-22
\、\= 関係演算子,2-22
@ リモート・アクセスのインジケータ,2-2,2-13
--1 行コメントのデリミタ,2-2
; 文の終了記号,2-2,13-12
- 減算 / 否定演算子,2-2
数字
3 項演算子,2-19
A
ACCESS_INTO_NULL 例外,10-4
AL16UTF16 文字コード化体系,3-9
ALL_PLSQL_OBJECT_SETTINGS ビュー
PL/SQL コンパイラ・パラメータの設定,11-2,
11-27
ALL 行演算子,6-3,6-6
ALTER ..COMPILE 文,10-18
ALTER PROCEDURE
プロシージャの再コンパイルで使用,10-19
ARRAY
VARYING,5-6
AS
プロシージャの定義,8-4
プロシージャ本体の定義,8-4
AUTHID 句
サブプログラムの権限の指定,8-16
実行者権限の指定に使用,8-15
ファンクションで使用,8-4
AUTONOMOUS_TRANSACTION プラグマ
構文,13-6
定義,6-36
例へのリンク,13-7
AVG
SQL 集計関数,2-37
B
BEGIN
構文,13-10
実行可能 PL/SQL ブロックの開始,13-10
実行可能部分の開始,8-4
ブロック構造,1-5
Best Practice
Oracle Technology Network,1-1,11-1
BETWEEN 句
FORALL,13-55
BETWEEN 比較演算子,2-22
式,13-47
BFILE データ型,3-11
BINARY_DOUBLE データ型,3-3
BINARY_FLOAT_INFINITY
定数,3-3
BINARY_FLOAT_MAX_NORMAL
定数,3-3
BINARY_FLOAT_MAX_SUBNORMAL
定数,3-3
BINARY_FLOAT_MIN_NORMAL
定数,3-3
BINARY_FLOAT_MIN_SUBNORMAL
定数,3-3
BINARY_FLOAT_NAN
定数,3-3
BINARY_FLOAT および BINARY_DOUBLE データ型
計算集中型プログラム,11-19
BINARY_FLOAT データ型,3-3
BINARY_INTEGER, 「PLS_INTEGER」を参照
BINARY_INTEGER データ型,3-2
BLOB データ型,3-11
BODY
CREATE PACKAGE SQL 文,1-13,9-2,13-84
CREATE TYPE SQL 文,13-77
SQL CREATE PACKAGE 文,9-2
SQL 文の CREATE PACKAGE で,1-13
BOOLEAN データ型,3-12
BULK COLLECT 句,11-15
DELETE 文,13-35
索引 -1
DML 結果の取得,11-18
EXECUTE IMMEDIATE,13-40
FETCH,13-52
FORALL 文での使用,11-18
LIMIT 句の使用,11-16,11-17
RETURNING 句,13-99
ROWNUM 疑似列の使用,11-16
SAMPLE 句の使用,11-16
SELECT INTO,13-106
結果が返されないかどうかの確認,11-15
問合せ結果の取得,11-15
複数行の戻し,6-14
BULK_EXCEPTIONS カーソル属性
ERROR_CODE フィールド,11-13
ERROR_INDEX フィールド,11-13
FORALL 例外処理,11-13
SQLERRM での ERROR_CODE フィールドの使用,
11-14
例,11-14
BULK_ROWCOUNT カーソル属性
FORALL の影響,11-12
BULK 句
COLLECT,11-15
C
CALL
SQL 文,1-14
CARDINALITY 演算子
ネストした表,5-15
CASE_NOT_FOUND 例外,10-4
CASE 式,2-25
概要,1-10
CASE 文
検索,4-5
構文,13-13
使用,4-4
例へのリンク,13-14
CHARACTER サブタイプ,3-5
CHAR データ型,3-5
VARCHAR2 との違い,3-22
CLOB データ型,3-11
CLOSE 文
カーソルの使用禁止,6-11
カーソル変数の使用禁止
クローズ,6-25
構文,13-15
例へのリンク,13-15
COLLECTION_IS_NULL 例外,10-4
COLLECT 句
BULK,11-15
COMMENT 句
トランザクションの使用,6-29
COMMIT 文,6-29,13-23
例へのリンク,13-23
CONSTANT
宣言,13-25
定数の宣言,2-9
CORR
SQL 分析関数,2-37
COUNT
SQL 集計関数,2-37
索引 -2
COUNT メソッド
コレクション,5-19,13-19
CREATE
PROCEDURE 文,1-12,1-18,8-3
CREATE FUNCTION 文,1-12,1-18,8-3
CREATE PROCEDURE 文,1-12,1-18,8-3
CREATE_WRAPPED ファンクション
使用,A-5
不明瞭化,A-5
CREATE 文
FUNCTION,8-3
FUNCTION で,1-12,1-18
パッケージ,1-13,9-2
CURRENT OF 句
UPDATE の使用,6-33
CURRVAL
疑似列,6-4
CURSOR_ALREADY_OPEN 例外,10-4
D
DATE データ型,3-13
DAY
データ型フィールド,3-12
DBMS_TRACE パッケージ
チューニングのためのコードのトレース,11-7
DBMS_ALERT パッケージ,9-9
DBMS_DB_VERSION パッケージ
条件付きコンパイルでの使用,2-33
DBMS_DDL パッケージ
PL/SQL コードの不明瞭化,A-1
PL/SQL コードのラップ,A-1
PL/SQL のソース・コードを隠すためのファンクショ
ン,A-1
wrap ファンクション,A-5
使用,A-5
制限,A-2
DBMS_OUTPUT パッケージ
PL/SQL からの出力の表示,9-9
PUT_LINE を使用して出力を表示,1-7
出力の表示,1-15
DBMS_PIPE パッケージ,9-10
DBMS_PREPROCESSOR パッケージ
条件付きコンパイルでの使用,2-35
DBMS_PROFILE パッケージ
チューニングのための統計情報の収集,11-7
DBMS_SQL パッケージ,7-2
PARSE プロシージャ,8-17
問合せでの使用,7-2
動的 SQL での置き換え,7-2
動的 SQL へのアップグレード,11-20
DBMS_WARNING パッケージ
PL/SQL の警告メッセージの制御,10-18
dbmsupbin.sql スクリプト
解釈コンパイル,11-29
dbmsupgnv.sql スクリプト
PL/SQL ネイティブ・コンパイル用,11-30
DEC
NUMBER サブタイプ,3-4
DECIMAL
NUMBER サブタイプ,3-4
DECLARE
PL/SQL ブロックの宣言部の開始,13-11
構文,13-11
ブロック構造,1-5
ローカル宣言,8-4
DECODE ファンクション
NULL の扱い,2-28
DEFAULT オプション
FUNCTION,13-61
RESTRICT_REFERENCES,13-96
DEFAULT キーワード
代入,2-9
DEFINE
wrap ユーティリティの使用の制限,A-3
DELETE 文
構文,13-35
例へのリンク,13-36
DELETE メソッド
コレクション,5-24,13-20
DETERMINISTIC ヒント
ファンクション構文,13-59
ファンクションで使用,8-4
DISTINCT 行演算子,6-3,6-6
DOUBLE PRECISION
NUMBER サブタイプ,3-4
DUP_VAL_ON_INDEX 例外,10-4
E
ELSE 句
使用,4-3
ELSIF 句
使用,4-3
END
PL/SQL ブロックの終わり,13-11
構文,13-11
実行可能部分の終了,8-4
ブロック構造,1-5
END IF
IF 文の終了,4-2
END LOOP
LOOP 文の終了,4-9
ERROR_CODE
BULK_EXCEPTIONS カーソル属性フィールド,
11-13
SQLERRM での使用,11-14
ERROR_INDEX
BULK_EXCEPTIONS カーソル属性フィールド,
11-13
EXCEPTION
PL/SQL ブロックの構文,13-11
ブロック構造,1-5
ブロックの例外処理部,13-11
例外処理部,8-4
EXCEPTION_INIT プラグマ
RAISE_APPLICATION_ERROR での使用,10-8
構文,13-37
例外,10-7
例へのリンク,13-37
EXECUTE IMMEDIATE 文,7-2
構文,13-40
例へのリンク,13-42
EXECUTE 権限
サブプログラム,8-18
EXISTS メソッド
コレクション,5-19,13-20
EXIT-WHEN 文
概要,1-11
使用,4-8
EXIT 文
構文,13-43
使用,4-7
使用できる場所,4-7
ループの停止,4-7
ループの途中での終了,4-12
例へのリンク,13-43
EXTEND メソッド
コレクション,5-22,13-20
F
FALSE 値,2-7
FETCH 文
カーソル変数,6-24
構文,13-52
明示カーソルの使用,6-9
例へのリンク,13-54
FIRST メソッド
コレクション,5-20,13-20
FLOAT
NUMBER サブタイプ,3-4
FOR UPDATE 句,6-9
使用する場合,6-33
FORALL 文
BULK COLLECT 句で使用,11-18
構文,13-55
使用,11-8
パフォーマンスの向上,11-8
例へのリンク,13-57
ロールバック,11-11
FOR-LOOP 文
構文,13-72
使用,4-9
FOR ループ
ネスト,4-12
明示カーソル,6-16
FOUND カーソル属性
暗黙的,6-7
明示的,6-11
FUNCTION
CREATE 文,8-3
G
GOTO 文
概要,1-12
構文,13-62
使用,4-13
制限,4-14
ラベル,4-13
例外ハンドラ内外への分岐,10-13
例へのリンク,13-62
GROUP BY 句,6-3
索引 -3
H
HOUR
データ型フィールド,3-12
HTF パッケージ,9-10
HTML(Hypertext Markup Language)
,9-10
HTP パッケージ,9-10
HTTP(Hypertext Transfer Protocol),1-4
UTL_HTTP パッケージ,9-10
I
IF-THEN-ELSEIF 文
使用,4-3
IF-THEN-ELSE 文
概要,1-9
使用,4-3
IF-THEN 文
使用,4-2
IF 文,4-2
ELSE 句,4-3
構文,13-63
使用,4-2
例へのリンク,13-64
IMMEDIATE
EXECUTE 文,7-2
IN OUT パラメータ・モード
サブプログラム,8-9
INDEX BY
コレクション定義,13-17
INDICES OF 句
FORALL,11-8,13-55
INSERT 文
構文,13-65
例へのリンク,13-66
レコード変数,5-32
INT
NUMBER サブタイプ,3-4
INTEGER
NUMBER サブタイプ,3-4
INTERSECT 集合演算子,6-6
INTERVAL DAY TO SECOND データ型,3-16
INTERVAL YEAR TO MONTH データ型,3-15
INTO
SELECT INTO 文,13-105
INTO 句
FETCH 文,6-25
INTO リスト
明示カーソルとの併用,6-9
INVALID_CURSOR 例外,10-4
INVALID_NUMBER 例外,10-4
IN パラメータ・モード
サブプログラム,8-8
IN 比較演算子,2-22
IS
プロシージャの定義,8-4
プロシージャ本体の定義,8-4
IS A SET 演算子,5-15
IS EMPTY 演算子,5-15
IS NULL 比較演算子,2-22
式,13-49
ISOLATION LEVEL パラメータ
READ COMMITTED,13-111
索引 -4
SERIALIZABLE,13-111
トランザクションの設定,13-111
ISOPEN カーソル属性
暗黙的,6-7
明示的,6-12
J
Java
外部サブプログラムのコールに使用,8-22
コール仕様部,8-22
Java ストアド・プロシージャ
PL/SQL からのコール,8-21
L
LAG
SQL 分析関数,2-37
LANGUAGE
外部サブプログラムのコールに使用,8-22
LAST メソッド
コレクション,5-20,13-20
LEVEL
疑似列,6-5
LEVEL パラメータ
ISOLATION でのトランザクション設定,13-111
LIKE 比較演算子,2-22
式,13-49
LIMIT 句
FETCH,13-53
バルク・フェッチ操作での行数の制限,11-17
LIMIT メソッド
コレクション,5-20,13-20
LOB(ラージ・オブジェクト)データ型,3-10
LOB ロケータ,3-11
LOCK TABLE 文
構文,13-70
表のロック,6-34
例,13-70
LOGIN_DENIED 例外,10-5
LONG RAW データ型,3-6
下位互換性のみサポート,3-6
最大長,3-6
変換,3-22
LONG データ型,3-6
下位互換性のみサポート,3-6
最大長,3-6
制限,3-6
LOOP 文
概要,1-10
構文,13-71
使用,4-7
例へのリンク,13-74
M
MEMBER OF 演算子,5-15
MERGE 文
構文,13-75
MINUS 集合演算子,6-6
MINUTE
データ型フィールド,3-12
MONTH
データ型フィールド,3-12
MULTISET EXCEPT 演算子,5-12
MULTISET INTERSECT 演算子,5-12
MULTISET UNION 演算子,5-12
N
NAME
外部サブプログラムのコールに使用,8-22
NAME パラメータ
トランザクション,6-32
トランザクションの設定,13-112
National Language Support(NLS)
,3-9
NATURAL
BINARY_INTEGER サブタイプ,3-3
NATURALN
BINARY_INTEGER サブタイプ,3-3
NATURAL と NATURALN サブタイプ,3-3
NCHAR データ型,3-9
NCLOB データ型,3-12
NEXTVAL
疑似列,6-4
NEXT メソッド
コレクション,5-21,13-20
NLS(National Language Support)
,3-9
NLS_LENGTH_SEMANTICS 初期化パラメータ
条件付きコンパイルでの使用,2-31
NO COPY ヒント
FUNCTION,13-60
NO_DATA_FOUND 例外,10-5
NOCOPY コンパイラ・ヒント
制限,11-21
チューニング,11-20
NOT NULL
宣言,13-25
NOT NULL オプション
レコード定義,13-93
NOT NULL 制約
%ROWTYPE 宣言の効果,2-11
%TYPE 宣言の効果,2-10
コレクション宣言での使用,5-9
変数宣言で使用,2-10
明示カーソルの制限,6-9
NOT_LOGGED_ON 例外,10-5
NOTFOUND カーソル属性
暗黙的,6-7
明示的,6-12
NOT 論理演算子
NULL の扱い,2-27
NOWAIT オプション
LOCK TABLE,13-70
NOWAIT パラメータ
FOR UPDATE での使用,6-33
NULL の扱い,2-26
動的 SQL,7-10
NULL 文
構文,13-76
使用,4-15
プロシージャで使用,8-4
例へのリンク,13-76
NUMBER サブタイプ,3-4
NUMBER データ型,3-3
値の範囲,3-3
リテラルの範囲,2-5
NUMERIC
NUMBER サブタイプ,3-4
NVARCHAR2 データ型,3-10
NVL ファンクション
NULL の扱い,2-28
O
ONLY パラメータ
READ でのトランザクション設定,13-111
OPEN FOR 文
動的文字列の長さ,13-81
OPEN-FOR-USING 文
構文,13-81
OPEN-FOR 文,6-21
構文,13-81
例へのリンク,13-83
OPEN 文
構文,13-79
明示カーソル,6-9
例へのリンク,13-80
Oracle Metalink
spnc_commands,11-24
ネイティブ・コンパイル,11-22
Oracle Technology Network
Best Practice,1-1
best practices,11-1
SQL インジェクション,7-7,13-42
サンプル・コード,1-1
チューニング情報,11-1
テーブル・ファンクション,11-31
テーブル・ファンクションの例,11-31
ネイティブ・コンパイル,11-22
OR キーワード
EXCEPTION での使用,10-12
OTHERS 句
例外処理,13-38
OTHERS 例外ハンドラ,10-2,10-12
OUT パラメータ・モード
サブプログラム,8-8
P
PACKAGE
SQL CREATE 文,9-2
SQL CREATE 文で,1-13
PACKAGE BODY
SQL CREATE 文,9-2
SQL CREATE 文で,1-13
PARALLE_ENABLE オプション
FUNCTION,13-60
PARALLEL_ENABLE オプション
ファンクションで使用,8-4
PIPE ROW 文
段階的に行を戻す場合,11-33
PIPELINED
ファンクション・オプション,13-60
ファンクションのオプション,11-32
PLS_INTEGER データ型,3-4
オーバーフロー条件,3-5
索引 -5
PL/SQL
CASE 式,2-25
NOCOPY を使用したチューニング,11-20
Server Pages(PSP)
,2-37
SQL サポート,6-2
Web アプリケーション,2-36
Web アプリケーションおよび Web ページの作成,
2-36
アーキテクチャ,1-18
移植性,1-4
エラー,10-1
エラー処理
概要,1-17
エンジン,1-18
環境,9-8
キーワード,D-1
キャラクタ・セット,2-2
警告メッセージ,10-17
計算集中型プログラムのチューニング,11-19
言語要素の構文,13-1
コードのチューニング,11-2
コメント,2-7
コレクション
概要,1-15
コレクション型,5-1
コンパイラの制限,C-1
コンパイラ・パラメータ,11-2
コンパイラ・パラメータの設定,11-2,11-27
コンパイル時の警告,10-17
再コンパイル,10-18
再利用可能なコードを書く,1-12
サブプログラム,8-1
コール,1-19
式,2-19
識別子の有効範囲,2-15
字句単位,2-2
システム固有の実行のための PL/SQL コードのコン
パイル,11-22
出力データ,1-15
出力の表示,1-7,9-9
条件付きコンパイル,1-12,2-29
制御構造,1-9,4-2
宣言
定数,2-9
ソース・コードの隠ぺいまたは不明瞭化,A-1
定数,1-5
データ型,3-1
データの抽象化,1-15
データの問合せ,6-14
動的 SQL の使用,7-2
動的 SQL プログラムのチューニング,11-20
トランザクション処理,6-28
名前解決,B-2
入力データ,1-15
ネーミング規則,2-13
パフォーマンス
メリット,1-3
パフォーマンス問題,11-3
比較,2-19
ファンクション,2-37,8-1
ブール値の代入,2-18
プログラムでの制限,C-1
プログラムの制限,C-1
索引 -6
プログラムのプロファイルおよびトレース,11-7
プロシージャ,8-1
プロシージャ的な面,1-5
ブロック,13-8
構造,1-5
文,13-1
変換パイプラインの使用,11-31
変数,1-5
変数への値の代入,2-18
変数への問合せ結果の代入,2-18
無名ブロック,1-5
メリット,1-2
予約語,D-1
リテラル,2-5
例外,10-1
レコード
概要,1-16
論理演算子,2-20
PLSQL_CCFLAGS 初期化パラメータ
条件付きコンパイル,2-33
条件付きコンパイルでの使用,2-31
PLSQL_CODE_TYPE 初期化パラメータ
PL/SQL ネイティブ・コンパイルの設定,11-25
条件付きコンパイルでの使用,2-31
plsql_code_type 列
ネイティブ・コンパイル,11-27
PLSQL_DEBUG 初期化パラメータ
条件付きコンパイルでの使用,2-31
PLSQL_LINE フラグ
条件付きコンパイルでの使用,2-31
PLSQL_NATIVE_LIBRARY_DIR 初期化パラメータ
ネイティブ・コンパイルの Real Application
Clusters,11-24
ネイティブ・コンパイル用,11-25
PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT 初期化パ
ラメータ
ネイティブ・コンパイル用,11-25
PLSQL_OPTIMIZE_LEVEL 初期化パラメータ
PL/SQL プログラムの最適化,11-2
条件付きコンパイルでの使用,2-31
PLSQL_UNIT フラグ
条件付きコンパイルでの使用,2-31
PLSQL_WARNINGS 初期化パラメータ,10-17
条件付きコンパイルでの使用,2-31
PL/SQL コードの隠ぺい,A-1
PLSQL データ型
数値リテラル,2-5
POSITIVE
BINARY_INTEGER サブタイプ,3-3
POSITIVEL と POSITIVEN サブタイプ,3-3
POSITIVEN
BINARY_INTEGER サブタイプ,3-3
PRAGMA
AUTONOMOUS_TRANSACTION でのコンパイラ・
ディレクティブ,13-6,13-60
EXCEPTION_INIT でのコンパイラ・ディレクティ
ブ,13-37
RESTRICT_REFERENCES でのコンパイラ・ディレク
ティブ,13-96
SERIALLY_REUSABLE でのコンパイラ・ディレク
ティブ,13-86,13-109
プロシージャの AUTONOMOUS_TRANSACTION
でのコンパイラ・ディレクティブ,13-91
PRIOR 行演算子,6-5
PRIOR メソッド
コレクション,5-21,13-20
PROCEDURE
CREATE 文,8-3
CREATE 文で,1-12,1-18
PROGRAM_ERROR 例外,10-5
PUT_LINE
出力の表示,1-7
R
raise_application_error プロシージャ
PL/SQL 例外の呼出し,10-7
RAISE 文
PL/SQL の例外,10-9
構文,13-92
例外ハンドラでの使用,10-11,10-12
例へのリンク,13-92
RAW データ型,3-6
最大長,3-6
変換,3-22
READ ONLY パラメータ
トランザクション,6-32
トランザクション設定,13-111
READ WRITE パラメータ
トランザクションの設定,13-111
REAL
NUMBER サブタイプ,3-4
Real Application Clusters
PL/SQL ネイティブ・コンパイル,11-24
ネイティブ・コンパイル,11-24
RECORD データ型,5-2
REF CURSOR データ型,6-19
カーソル副問合せの使用,6-28
カーソル変数,6-19
定義,6-20
REF CURSOR 変数
事前定義の SYS_REFCURSOR 型,11-35
テーブル・ファンクションへのパラメータ,11-35
REF ファンクション
PL/SQL を使用したオブジェクトの操作,12-6
REPEAT UNTIL 構造
PL/SQL での等価,4-9
REPLACE ファンクション
NULL の扱い,2-28
RESTRICT_REFERENCES プラグマ,8-23
構文,13-96
自律型ファンクションでの使用,6-40
動的 SQL での使用,7-11
例へのリンク,13-97
RETURNING 句
構文,13-99
動的 SQL,7-3
例へのリンク,13-100
レコード変数,5-34
RETURN 句
FUNCTION,13-61
カーソル,9-11
カーソル宣言,13-30
ファンクション,8-5
RETURN 文
構文,13-98
ファンクション,8-5
例へのリンク,13-98
REUSE SETTINGS 句
コンパイラ・パラメータ,11-2
REVERSE
ループ・カウンタを使用,4-9
REVERSE オプション
LOOP,13-73
RNDS オプション
RESTRICT_REFERENCES,13-96
RNPS オプション
RESTRICT_REFERENCES,13-96
ROLLBACK 文,6-29
構文,13-101
セーブポイントへの影響,6-31
例へのリンク,13-101
ROWCOUNT カーソル属性
暗黙的,6-7
明示的,6-13
ROWID,3-7
疑似列,6-5
ROWIDTOCHAR ファンクション,6-5
ROWID データ型,3-7
ROWNUM
疑似列,6-5
ROWTYPE_MISMATCH 例外,10-5
ROWTYPE 属性
NOT NULL 制約の効果,2-11
SUBTYPE を使用,3-17
構文,13-102
使用,2-11
宣言,1-9
デフォルト値の効果,2-11
例へのリンク,13-103
レコード,5-28
列から継承されたプロパティ,13-102
RPC(リモート・プロシージャ・コール)
例外,10-9
S
SAVE EXCEPTIONS 句
FORALL,13-56
SAVEPOINT 文,6-30
構文,13-104
例へのリンク,13-104
SECOND
データ型フィールド,3-12
SELECT INTO 文
1 行の戻し,6-14
構文,13-105
例へのリンク,13-107
SELF_IS_NULL 例外,10-5
SERIALLY_REUSABLE プラグマ
構文,13-109
パッケージでの使用,13-86
例,13-109
Server Pages(PSP)
PL/SQL,2-37
SERVEROUTPUT
ON を設定して出力を表示,9-9
PL/SQL からの出力の表示,1-15
索引 -7
SET TRANSACTION 文,6-32
構文,13-111
例へのリンク,13-112
SET 句
UPDATE,13-119
SIGNTYPE
BINARY_INTEGER サブタイプ,3-3
SIGNTYPE サブタイプ,3-3
SMALLINT
NUMBER サブタイプ,3-4
spnc_commands
Oracle Metalink,11-24
SQL
DML 操作,6-2
DML 文で行が戻されない,6-3
DML 文によって呼び出される例外,6-3
PL/SQL での発行,6-2
インジェクション,7-7,13-42
疑似列,6-4
静的,1-2
動的,1-2,7-2
比較演算子,6-6
変数および DML 文の定義,6-3
SQLCODE ファンクション
構文,13-115
例外ハンドラでの使用,10-13
例へのリンク,13-115
SQLERRM ファンクション
BULK_EXCEPTIONS ERROR_CODE フィールドでの
使用,11-14
構文,13-116
例外ハンドラでの使用,10-13
例へのリンク,13-116
SQL インジェクション,7-7,13-42
Oracle Technology Network,7-7,13-42
SQL カーソル
構文,13-113
例へのリンク,13-114
STANDARD パッケージ
PL/SQL 環境の定義,9-8
START WITH 句,6-5
STEP 句
PL/SQL での等価,4-10
STORAGE_ERROR 例外,10-5
再起による発生,8-21
STRING サブタイプ,3-9
SUBSCRIPT_BEYOND_COUNT 例外,10-5
SUBSCRIPT_OUTSIDE_LIMIT 例外,10-5
SUBSTR ファンクション
SQLERRM での使用,10-14
SYS_INVALID_ROWID 例外,10-5
SYS_REFCURSOR 型,11-35
T
TABLE 演算子
PL/SQL を使用したオブジェクトの操作,12-8
TABLE データ型,5-6
THEN 句
IF 文と,4-2
使用,4-2
TIMEOUT_ON_RESOURCE 例外,10-5
索引 -8
TIMESTAMP WITH LOCAL TIME ZONE データ型,
3-15
TIMESTAMP WITH TIME ZONE データ型,3-14
TIMESTAMP データ型,3-13
TIMEZONE_ABBR
データ型フィールド,3-12
TIMEZONE_HOUR
データ型フィールド,3-12
TIMEZONE_MINUTE
データ型フィールド,3-12
TIMEZONE_REGION
データ型フィールド,3-12
TOO_MANY_ROWS 例外,10-5
TRIM メソッド
コレクション,5-23,13-20
TRUE 値,2-7
TRUST オプション
RESTRICT_REFERENCES,13-97
TYPE 属性
NOT NULL 制約の効果,2-10
SUBTYPE を使用,3-17
構文,13-117
使用,2-10
宣言,1-8
デフォルト値の効果,2-10
例へのリンク,13-118
列から継承されたプロパティ,13-117
TYPE 定義
RECORD,5-28
REF CURSOR,6-20
VARRAY,5-6
結合配列,5-6
コレクション,5-6
コレクション型,5-6
ネストした表,5-6
U
UNION ALL 集合演算子,6-6
UNION 集合演算子,6-6
UPDATE 文
構文,13-119
例へのリンク,13-120
レコード変数,5-33
URL(Uniform Resource Locator),9-10
UROWID
疑似列,6-5
UROWID データ型,3-7
USE ROLLBACK SEGMENT パラメータ
トランザクションの設定,13-111
USING 句
EXECUTE IMMEDIATE,13-41
OPEN FOR 文,13-82
動的 SQL,7-3
UTF8 文字コード化体系,3-9
UTL_FILE パッケージ,9-10
UTL_HTTP パッケージ,9-10
UTL_SMTP パッケージ,9-10
utlirp.sql スクリプト
PL/SQL ネイティブ・コンパイル用,11-27
utlrp.sql スクリプト
PL/SQL ネイティブ・コンパイル用,11-30
V
あ
V$RESERVED_WORDS ビュー
予約語およびキーワードのリスト,D-1
VALUE_ERROR 例外,10-5
VALUES OF 句,11-8
FORALL,13-55
VALUES 句
INSERT,13-66
VALUE ファンクション,12-5
VARCHAR2 データ型,3-8
CHAR との違い,3-22
VARCHAR サブタイプ,3-9
VARRAY
TYPE 定義,5-6
構文,13-16
サイズの制限,5-6
ネストした表との比較,5-5
理解,5-2
VARRAY データ型,5-3,5-6
アーキテクチャ
PL/SQL,1-18
値方式によるパラメータの引渡し,8-23
アドレス
REF CURSOR,6-19
アポストロフィ,2-6
アンダースコア,2-4
暗黙カーソル
ガイドライン,6-8
属性,6-6
暗黙的な宣言
FOR ループ・カウンタ,4-11
暗黙的なデータ型変換,3-20
パフォーマンス,11-5
W
え
Web Server Pages
PL/SQL を使用した作成,2-36
Web アプリケーション
PL/SQL を使用した作成,2-36
WHEN 句
使用,4-8
例外,10-12
例外処理,13-38
WHERE CURRENT OF 句
DELETE 文,13-36
UPDATE,13-120
WHILE-LOOP 文
概要,1-11
構文,13-74
使用,4-9
WNDS オプション
RESTRICT_REFERENCES,13-97
WNPS オプション
RESTRICT_REFERENCES,13-97
WRAP ファンクション
不明瞭化,A-5
wrap ユーティリティ
PL/SQL コードの不明瞭化,A-1,A-3
実行,A-4
制限,A-2
WRITE パラメータ
READ でのトランザクション設定,13-111
エイリアシング
カーソル FOR ループ内の式の値,6-16
パラメータ,8-23
エラー処理
PL/SQL,10-1
概要,1-17
エラーの処理
PL/SQL,10-1
エラー・メッセージ
最大長,10-14
演算子
関係,2-22
比較,2-21
優先順位,2-19
論理,2-20
Y
YEAR
データ型フィールド,3-12
Z
ZERO_DIVIDE 例外,10-5
ZONE
TIMESTAMP データ型部,3-14
い
移植性,1-4
お
オーバーロード
ガイドライン,8-10
継承,8-14
サブプログラム名,8-10
制限,8-11
パッケージ・サブプログラム,9-8
オブジェクト型
PL/SQL コレクションでの使用,12-9
PL/SQL での使用,12-1
PL/SQL での初期化,12-2,12-3
PL/SQL での定義,12-2
PL/SQL ブロックでの宣言,12-3
概要,1-16
実行者権限サブプログラムでの使用,8-19
オブジェクト型宣言
構文,13-77
オブジェクト型の代替性
オーバーロード,8-14
オブジェクト・コンストラクタ
PL/SQL でのコール,12-5
PL/SQL へのパラメータの引渡し,12-5
索引 -9
オブジェクト指向プログラミング
PL/SQL,12-1
オブジェクト・メソッド
PL/SQL でのコール,12-5
オンザフライ・ラップ
DBMS_DDL パッケージ,A-1
か
カーソル
REF CURSOR 変数,6-19
RETURN 句,9-11
SYS_REFCURSOR 型,11-35
暗黙的,1-15
オープン、明示,6-9
カーソル変数を使用する利点,6-19
ガイドライン、暗黙,6-8
クローズ、明示,6-11
式,6-27
宣言、明示,6-8
属性、暗黙,6-6
属性、明示,6-11
定義,1-15
パッケージ,9-11
パラメータ付き,6-18
フェッチ,6-9
変数,6-19
明示的,1-15,6-8
明示的な FOR ループ,6-16
有効範囲ルール、明示,6-8
カーソル FOR ループ
パラメータの受渡し,6-18
カーソル式
REF CURSOR,6-28
使用,6-27
制限,6-27
例,6-28
カーソル宣言
構文,13-32
例へのリンク,13-34
カーソル属性
%BULK_EXCEPTIONS,11-13
%BULK_ROWCOUNT,11-12
%FOUND,6-7,6-11
%ISOPEN,6-7,6-12
%NOTFOUND,6-7,6-12
%ROWCOUNT,6-7,6-13
OPEN、FETCH および CLOSE 後の値,6-13
暗黙的,6-6
構文,13-27
明示的,6-11
例へのリンク,13-28
カーソル副問合せ
使用,6-27
カーソル変数,6-19
エラーの回避,6-26
オープン,6-21
クローズ,6-25
構文,13-29
制限,6-26
宣言,6-20
定義,6-20
テーブル・ファンクションへのパラメータ,11-35
索引 -10
ネットワーク・トラフィックの削減,6-25
パラメータとしての引渡し,6-21
フェッチ,6-24
ホスト変数として使用,6-23
利点,6-19
例へのリンク,13-31
改行,2-2
解決
名前,2-14
名前への参照,B-2
解釈コンパイル
dbmsupbin.sql スクリプト,11-29
すべての PL/SQL モジュールの再コンパイル,11-29
外部
サブプログラム,8-21
参照,8-16
ルーチン,8-21
科学表記法,2-5
拡張 ROWID,3-7
可視性
トランザクション,6-38
パッケージの内容,9-2
有効範囲,2-15
カッコ,2-19
各国語キャラクタ・セット,3-9
各国語キャラクタ・データ型,3-9
可読性,2-2
NULL 文,4-15
可変サイズの配列(VARRAY)
理解,5-2
仮パラメータ,6-19
関係演算子,2-22
き
キーワード
PL/SQL,D-1
PL/SQL での使用,2-4
PL/SQL のリスト,D-2
記憶域表,5-6
疑似列
CURRVAL,6-4
LEVEL,6-5
NEXTVAL,6-4
PL/SQL での使用,6-4
ROWID,6-5
ROWNUM,6-5
SQL,6-4
UROWID,6-5
規則
PL/SQL のネーミング,2-13
純正,8-23
基本構造的に NULL
PL/SQL でのオブジェクト型,12-3
基本ループ,4-7
キャラクタ・セット
PL/SQL,2-2
行演算子,6-6
行ロック
FOR UPDATE の使用,6-33
く
句
AUTHID,8-4,8-15,8-16
BULK COLLECT,11-15
LIMIT,11-17
空白
使用できる場所,2-2
空白埋めの方法,3-23
組込みファンクション,2-37
位取り
指定,3-4
け
警告メッセージ
PL/SQL の制御,10-17
継承
オーバーロード,8-14
桁数精度,3-4
結果セット,6-9
結合配列
VARCHAR2 キーとグローバリゼーション設定,5-4
キーと値のペアのセット,5-3
構文,13-16
ネストした表との比較,5-5
理解,5-2
言語間のコール,8-21
言語要素
PL/SQL,13-1
検索 CASE 式,2-26
検索 CASE 文,4-5
こ
語
PL/SQL で予約,D-1
後続する空白,3-24
構文
AUTONOMOUS_TRANSACTION プラグマ,13-6
BEGIN,13-10
CASE 文,13-13
CLOSE 文,13-15
DECLARE,13-11
DELETE 文,13-35
END,13-11
EXCEPTION,13-11
EXCEPTION_INIT プラグマ,13-37
EXECUTE IMMEDIATE 文,13-40
EXIT 文,13-43
FETCH 文,13-52
FORALL 文,13-55
FOR-LOOP 文,13-72
GOTO 文,13-62
IF 文,13-63
INSERT 文,13-65
LOCK TABLE 文,13-70
LOOP 文,13-71
NULL 文,13-76
OPEN-FOR-USING 文,13-81
OPEN-FOR 文,13-81
OPEN 文,13-79
PL/SQL の言語要素,13-1
RAISE 文,13-92
RESTRICT_REFERENCES プラグマ,13-96
RETURNING 句,13-99
RETURN 文,13-98
ROLLBACK 文,13-101
ROWTYPE 属性,13-102
SAVEPOINT 文,13-104
SELECT INTO 文,13-105
SERIALLY_REUSABLE プラグマ,13-109
SET TRANSACTION 文,13-111
SQLCODE ファンクション,13-115
SQLERRM ファンクション,13-116
SQL カーソル,13-113
TYPE 属性,13-117
UPDATE 文,13-119
WHILE-LOOP 文,13-74
オブジェクト型宣言,13-77
カーソル宣言,13-32
カーソル属性,13-27
カーソル変数,13-29
コメント,13-22
コレクション定義,13-16
コレクション・メソッド,13-19
式,13-44
図の読み方,13-1
代入文,13-3
定数,13-24
パッケージ宣言,13-84
ファンクション宣言,13-58
プロシージャ宣言,13-89
ブロック宣言,13-8
変数,13-24
ラベル,13-11
リテラル宣言,13-67
例外定義,13-38
レコード定義,13-93
コール
Java ストアド・プロシージャ,8-21
言語間,8-21
サブプログラム,8-7
サブプログラムの解決,8-12
ストアド・サブプログラム,1-19
プロシージャ,1-14
コール仕様部,9-2
コメント
PL/SQL,2-7
構文,13-22
制限,2-8
例へのリンク,13-22
コレクション
COUNT メソッド,5-19
DELETE メソッド,5-24
EXISTS メソッド,5-19
EXTEND メソッド,5-22
FIRST メソッド,5-20
LAST メソッド,5-20
LIMIT メソッド,5-20
NEXT メソッド,5-21
NULL かどうかのテスト,5-15
PL/SQL での型,5-1
PRIOR メソッド,5-21
TRIM メソッド,5-23
VARRAY とネストした表との相違点,5-5
索引 -11
オブジェクト型の使用,12-9
概要,1-15
型の定義,5-6
結合配列とネストした表との相違点,5-5
構文,13-16
コンストラクタ,5-9
参照,5-9
使用する型の選択,5-5
使用できる添字範囲,5-11
初期化,5-9
代入,5-12
ネストした表を変換する演算子,5-12
パラメータへのメソッドの適用,5-25
バルク・バインド,5-34,11-8
比較,5-15
変数の宣言,5-6,5-7
マルチレベル,5-17
メソッド,5-18
有効範囲,5-6
要素型,5-6
要素の参照,5-11
要素の順序付きグループ,5-2
理解,5-2
例外の回避,5-26
例へのリンク,13-18,13-21
コレクションの例外
呼び出される場合,5-27
コレクション・メソッド
構文,13-19
使用,5-18
コンストラクタ
コレクション,5-9
コンテキスト
トランザクション,6-38
コンパイラ・パラメータ
PL/SQL,11-2
REUSE SETTINGS 句,11-2
コンパイラ・パラメータの設定
ALL_PLSQL_OBJECT_SETTINGS ビュー,11-2,
11-27
コンパイル
システム固有の実行のための PL/SQL プロシージャ,
11-22
条件,2-29,1-12
コンポジット型
概要,3-2
コレクションおよびレコード,5-2
さ
再帰
PL/SQL のサブプログラムでの使用,8-21
再コンパイル
ファンクション、パッケージおよびプロシージャ,
10-18
サイズの制限
VARRAY,5-6
最大サイズ
CHAR 値,3-5
LOB,3-10
LONG RAW 値,3-6
LONG 値,3-6
NCHAR 値,3-9
索引 -12
NVARCHAR2 値,3-10
Oracle エラー・メッセージ,10-14
RAW 値,3-6
VARCHAR2 値,3-8
識別子,2-4
最大精度,3-4
最適化
PL/SQL プログラム,11-2
先送り
サブプログラムの宣言,8-5
参照,2-13
作業領域
問合せ,6-19
索引付き表
「結合配列」を参照
作成
パッケージ,1-13,9-2
ファンクション,1-12,1-18,8-3
プロシージャ,1-12,1-18,8-3
サブタイプ
BINARY_INTEGER,3-3
CHARACTER,3-5
NATURAL と NATURALN,3-3
NUMBER,3-4
PL/SQL,3-17
POSITIVE と POSITIVEN,3-3
SIGNTYPE,3-3
STRING,3-9
VARCHAR,3-9
互換性,3-18
使用,3-18
制約と無制約,3-17
定義,3-17
サブプログラム
AUTHID 句,8-15,8-16
EXECUTE 権限,8-18
IN OUT パラメータ・モード,8-9
IN パラメータ・モード,8-8
OUT パラメータ・モード,8-8
PL/SQL,8-1
PL/SQL でのメリット,8-3
PL/SQL の概要,8-2
PL/SQL の宣言,1-8
SQL*Plus からのコール,1-19
値方式によるパラメータの引渡し,8-23
位置表記法のパラメータ,8-7
オーバーロードおよび継承,8-14
オーバーロードのガイドライン,8-10
オーバーロードの制限,8-11
外部サブプログラムのコール,8-21
外部参照,8-16
外部参照の解決,8-17
コールの解決方法,8-12
混合表記法のパラメータ,8-7
再帰,8-21
再帰の使用,8-21
参照方式によるパラメータの引渡し,8-23
実行者権限,8-15
実行者権限サブプログラムでのデータベース・リンク
の使用,8-19
実行者権限サブプログラムでのトリガーの使用,8-19
実行者権限サブプログラムでのビューの使用,8-19
実行者権限サブプログラムのロール,8-19
実行者権限に対する権限の付与,8-18
実行中の現行ユーザー,8-16
実パラメータと仮パラメータの対比,8-6
スタンドアロン,1-19
ストアド,1-18
宣言、ネスト,8-5
定義者権限,8-15
デフォルトのパラメータ・モード,8-9
名前解決のオーバーライド,8-17
名前のオーバーロード,8-10
名前表記法のパラメータ,8-7
パッケージ,1-19
パラメータによるコール,8-7
パラメータのエイリアシング,8-23
パラメータの引渡し,8-6
パラメータ・モード,8-8,8-9
副作用の制御,8-23
プロシージャとファンクションの比較,8-4
ローカル,1-19
参照
解決、外部,8-17
外部,8-16
コレクション,5-9
参照型,3-2
参照方式によるパラメータの引渡し,8-23
サンプル・コード
Oracle Technology Network,1-1
し
時間隔
算術,3-16
データ型,3-12
式
CASE,2-25
PL/SQL,2-19
構文,13-44
静的,2-31
ブール,2-23
例,13-51
識別子
構成,2-4
最大長,2-4
二重引用符で囲んだ,2-5
有効範囲規則,2-15
字句単位
PL/SQL,2-2
システム固有の実行
PL/SQL プロシージャのコンパイル,11-22
システム固有の動的 SQL, 「動的 SQL」を参照,1-3,
7-1
事前定義の例外
再宣言,10-8
明示的な呼出し,10-9
実行者権限
サブプログラムの権限,8-15
メリット,8-16
実行部
PL/SQL ブロック,1-5
ファンクション,8-5
プロシージャ,8-4
実パラメータ,6-19
シノニム
名前解決,8-17
集計関数
AVG,2-37
COUNT,2-37
PL/SQL,6-3
集計代入,2-12
集合演算子,6-6
修飾子
サブプログラム名を使用,2-14
必要な場合,2-13,2-16
終了記号、文,2-2
述語,6-6
出力の表示
DBMS_OUTPUT.PUT_LINE の使用,1-7
DBMS_OUTPUT で,1-15
PL/SQL から,1-7
SERVEROUTPUT の設定,1-15,9-9
順序
CURRVAL と NEXTVAL,6-4
純正規則,8-23
条件制御,4-2
条件付きコンパイル,1-12,2-29
DBMS_DB_VERSION での使用,2-33
DBMS_PREPROCESSOR での使用,2-35
NLS_LENGTH_SEMANTICS 初期化パラメータ,
2-31
PLSQL_CCFLAGS 初期化パラメータ,2-31
PLSQL_CCFLAGS 初期化パラメータの使用,2-33
PLSQL_CODE_TYPE 初期化パラメータ,2-31
PLSQL_DEBUG 初期化パラメータ,2-31
PLSQL_LINE フラグ,2-31
PLSQL_OPTIMIZE_LEVEL 初期化パラメータ,2-31
PLSQL_UNIT フラグ,2-31
PLSQL_WARNINGS 初期化パラメータ,2-31
以前の Oracle データベース・リリースに対する可用
性,2-29
制御トークン,2-30
制限,2-35
静的定数,2-32
静的な式の使用,2-31
問合せディレクティブ,2-30
例,2-34
条件文
指針,4-6
照合順番,2-23
詳細
Oracle Technology Network,1-1
仕様部
カーソル,9-11
コール,9-2
パッケージ,9-4,13-87
ファンクション,8-5
プロシージャ,8-4
初期化
DEFAULT の使用,2-9
NOT NULL 制約,2-10
PL/SQL でのオブジェクト,12-3
コレクション,5-9
パッケージ,9-6
変数,2-18
初期化パラメータ
PL/SQL コンパイル,11-2
索引 -13
書式
マスク,3-22
自律型トランザクション
PL/SQL,6-35
SQL%ROWCOUNT 属性,6-7
SQL のコール,6-40
エラーの回避,6-39
制御,6-38
ネストしたトランザクションとの比較,6-37
メリット,6-36
自律型ファンクション
RESTRICT_REFERENCES プラグマ,6-40
自律型トリガー
使用,6-39
す
数値リテラル,2-5
PL/SQL データ型,2-5
スカラー・データ型,3-2
スタンドアロン・サブプログラム,1-19
ストアド・サブプログラム
Oracle データベースで,1-18
せ
正規表現ファンクション
REGEXP_LIKE,6-9
制御構造
PL/SQL の概要,4-2
順次,4-13
条件,4-2
反復,4-7
理解,1-9
制限
DBMS_DDL パッケージ,A-2
PL/SQL コンパイラ,C-1
PL/SQL プログラム,C-1
wrap ユーティリティ,A-2
カーソル式,6-27
カーソル変数,6-26
サブプログラムのオーバーロード,8-11
ネイティブ・コンパイル,11-24
制限 ROWID,3-7
生産性,1-3
整数
BINARY,3-2
PLS データ型,3-4
静的 SQL,1-2
静的定数
条件付きコンパイル,2-32
静的な式
PLS_INTEGER,2-31
VARCHAR2,2-31
条件付きコンパイルでの使用,2-31
ブール,2-31
精度桁数
指定,3-4
制約
NOT NULL,2-10
セーブポイント
名前の再使用,6-31
索引 -14
セキュリティ
SQL インジェクション,7-7,13-42
セパレータ,2-2
宣言
%ROWTYPE の使用,2-11
%TYPE 属性の使用,2-10
DEFAULT の使用,2-9
NOT NULL 制約の使用,2-10
PL/SQL のサブプログラム,1-8
PL/SQL のプロシージャ,1-8
PL/SQL のファンクション,1-8
PL/SQL の変数,1-8
PL/SQL の例外,10-6
PL/SQL ブロックでのオブジェクト,12-3
カーソル変数,6-20
コレクション,5-7
サブプログラム,8-5
制限,2-13
定数,1-7,2-9
変数,1-5,2-9
明示カーソル,6-8
宣言部
PL/SQL ブロック,1-5
ファンクション,8-5
プロシージャ,8-4
選択子,2-25
そ
相関副問合せ,6-17
属性
%ROWTYPE,1-9,2-11
%TYPE,1-8,2-10
明示カーソル,6-11
疎コレクション
ネストした表と配列との相違点,5-3
た
大 / 小文字の区別
識別子,2-4
文字列リテラル,2-6
代入
IN OUT パラメータ,1-7
コレクション,5-12
集計,2-12
フィールド,5-31
変数,1-6
方法,3-22
文字列,3-22
レコード,5-31
代入演算子,1-6
代入文
構文,13-3
例へのリンク,13-5
タブ,2-2
単一行コメント,2-8
単項演算子,2-19
単純な CASE 式,2-25
短絡評価,2-21
ち
チューニング
DBMS_PROFILE および DBMS_TRACE の使用,11-7
FORALL の使用,11-8
NOCOPY の使用,11-20
Oracle Technology Network の情報,11-1
PL/SQL コード,11-2
PL/SQL のパフォーマンス問題を回避するためのガイ
ドライン,11-3
PL/SQL プログラムの最適化,11-2
SQL 文の効率化,11-3
大きなサイズの VARCHAR2 変数の割当て,11-6
関連するサブプログラムのパッケージへのグループ
化,11-6
共有メモリー・プールでのパッケージの確保,11-6
組込みファンクションの使用,11-5
計算集中型プログラム,11-19
コンパイラの警告を回避するためのコードの改善,
11-7
システム固有の実行のための PL/SQL コードのコン
パイル,11-22
条件テストにおける最低コストの条件の先頭への配
置,11-5
整数の算術計算での PLS_INTEGER の使用,11-6
動的 SQL プログラム,11-20
ファンクション・コールの効率化,11-4
浮動小数点の算術計算での BINARY_FLOAT または
BINARY_DOUBLE の使用,11-6
プロファイルおよびトレース,11-7
変換パイプラインの使用,11-31
メモリーのオーバーヘッドの回避,11-6
ループ・オーバーヘッドの削減,11-8
ループの効率化,11-4
て
定義者権限
サブプログラムの権限,8-15
CONSTANT
定数の宣言用,1-7
定数
PL/SQL,1-5
構文,13-24
静的,2-32
宣言,1-7,2-9
例へのリンク,13-26
データ型
BFILE,3-11
BINARY_INTEGER,3-2
BLOB,3-11
BOOLEAN,3-12
CHAR,3-5
CLOB,3-11
DATE,3-13
INTERVAL DAY TO SECOND,3-16
INTERVAL YEAR TO MONTH,3-15
LONG,3-6
LONG RAW,3-6
NCHAR,3-9
NCLOB,3-12
NUMBER,3-3
NVARCHAR2,3-10
PLS_INTEGER,3-4
PL/SQL,3-1
RAW,3-6
RECORD,5-2
REF CURSOR,6-19
ROWID,3-7
TABLE,5-6
TIMESTAMP,3-13
TIMESTAMP WITH LOCAL TIME ZONE,3-15
TIMESTAMP WITH TIME ZONE,3-14
UROWID,3-7
VARCHAR2,3-8
VARRAY,5-3,5-6
暗黙的な変換,3-20
各国語キャラクタ,3-9
グループ,3-2
スカラーとコンポジット,3-2
明示的な変換,3-20
データの抽象化
PL/SQL,1-15
データの問合せ
BULK COLLECT 句,6-14
PL/SQL を使用,6-14
SELECT INTO,6-14
暗黙カーソル FOR ループ,6-15
暗黙カーソルの使用,6-15
維持,6-18
カーソル FOR ループ,6-15
作業領域,6-19
複雑な処理の実行,6-15
複数行にわたるループ,6-15
明示カーソルの使用,6-15
データベース・キャラクタ・セット,3-9
データベース・トリガー,1-19
自律型,6-39
テーブル・ファンクション
DML 操作の実行,11-37
Oracle Technology Network の情報,11-31
Oracle Technology Network の例,11-31
カーソル変数によるデータの引渡し,11-35
結果からのフェッチ,11-34
結果の戻し,11-33
データのパイプライン,11-34
問合せ,11-31
複数コールの編成,11-34
変換パイプラインの作成,11-32
変換パイプラインの使用,11-32
変換パイプラインの設定,11-31
例外処理,11-38
デッドロック
PL/SQL による処理,6-31
デフォルト値
%ROWTYPE 宣言の効果,2-11
%TYPE 宣言の効果,2-10
デフォルトのパラメータ値,8-9
デリミタ,2-2
伝播
PL/SQL の例外,10-9
索引 -15
と
問合せ作業領域,6-19
動的 SQL,1-2,7-2
EXECUTE IMMEDIATE 文の使用方法,7-2
NULL の引渡し,7-10
RESTRICT_REFERENCES,7-11
RETURNING 句,7-3
USING 句,7-3
カーソル属性の使用,7-9
ガイドライン,7-7
実行権限の使用,7-11
セミコロンの使用,7-7
チューニング,11-20
重複するプレースホルダを使用,7-9
データベース・リンクの使用,7-10
動的 SQL 活用時のヒント,7-7
動的複数行問合せのバインド,7-7
パフォーマンスの向上,7-8
パラメータとしてのオブジェクト名の引渡し,7-8
パラメータ・モードの指定,7-4
バルク SQL の使用,7-5
動的ディスパッチ,8-15
動的文字列の長さ
OPEN FOR 文,13-81
動的ラップ
DBMS_DDL パッケージ,A-1
ドット表記法,1-8
PL/SQL でのオブジェクト属性,12-4
PL/SQL でのオブジェクトメソッド,12-5
グローバル変数,4-12
コレクション・メソッド,5-18
パッケージ内容,9-5
トランザクション,6-3
PL/SQL での処理,6-3,6-28
可視性,6-38
コミット,6-29
コンテキスト,6-38
自律、PL/SQL 内,6-35
制限,6-32
セーブポイント,6-30
適切な終了,6-32
プロパティ,6-32
読取り専用,6-32
ロールバック,6-29
トリガー
自律型,6-39
ストアド PL/SQL サブプログラムとして,1-19
な
名前
修飾,2-13
セーブポイント,6-31
変数,2-13
明示カーソル,6-8
名前解決,2-14
DML 文の内部取得,B-6
PL/SQL と SQL の相違点,B-4
グローバル変数とローカル変数,B-2
サブプログラムでのオーバーライド,8-17
シノニム,8-17
修飾名およびドット表記法,B-2
索引 -16
取得の理解,B-4
属性およびメソッドへの参照の修飾,B-6
理解,B-2
に
二重引用符で囲んだ識別子,2-5
日時
算術,3-16
データ型,3-12
リテラル,2-7
ニブル
半バイト,3-22
ね
ネイティブ・コンパイル
dbmsupgnv.sql スクリプト,11-30
Oracle Metalink,11-22
Oracle Technology Network,11-22
plsql_code_type 列,11-27
PL/SQL コード,11-22
Real Application Clusters,11-24
spnc_commands ファイル,11-24
utlirp.sql スクリプト,11-27
utlrp.sql スクリプト,11-30
依存性,11-23
インストレーション・ガイドの動作保証済コンパイ
ラ,11-22
共有ライブラリ,11-23
再評価,11-23
仕組み,11-23
使用,11-27
初期化パラメータ,11-25
制限,11-24
設定,11-27
前提要件,11-22
データベースの作成,11-28
データベースの設定,11-28
データベースの変更,11-28
テスト,11-22
パフォーマンス向上,11-22
無効化,11-23
ライブラリ・サブディレクトリの設定,11-26
理解,11-22
ネーミング規則
PL/SQL,2-13
ネスト
FOR ループ,4-12
ブロック,1-5
レコード,5-29
ネストしたカーソル
使用,6-27
ネストしたコレクション,5-17
ネストした表
PL/SQL での操作,12-9
VARRAY との比較,5-5
一連の値,5-2
演算子を使用した変換,5-12
結合配列との比較,5-5
構文,13-16
理解,5-2
は
バイナリ演算子,2-19
パイプ,9-10
パイプライン
コレクション型のサポート,11-32
テーブル・ファンクションからの結果の戻し,11-33
テーブル・ファンクション間,11-34
テーブル・ファンクションの作成,11-32
テーブル・ファンクションの使用,11-32
パイプライン化
定義,11-31
パイプライン・ファンクション
DML 操作の実行,11-37
カーソル変数によるデータの引渡し,11-35
概要,11-31
結果からのフェッチ,11-34
結果の戻し,11-33
作成,11-32
データの変換,11-31
表の問合せ,11-31
変換,11-32
例外処理,11-38
配列
可変サイズ,5-2
結合,5-2
索引付き表,5-2
バインド,11-8
バインド変数,1-7
パターン一致,2-22
パッケージ
PL/SQL で使用する製品固有,1-4
STANDARD パッケージ,9-8
カーソル,9-11
カーソル仕様部,9-11
概要,1-13
概要、Oracle 提供,9-9
隠された宣言,9-2
機能の例,9-6
グローバル変数,9-8
コール仕様部,9-2
作成,1-13,9-2
作成のガイドライン,9-10
サブプログラムのオーバーロード,9-8
サブプログラムのコール,9-5
参照,9-5
参照の制限,9-5
仕様部,9-2,9-4,13-87
初期化,9-6
製品固有,9-9
宣言,13-84
逐次再使用可能,13-86
ドット表記法,9-5
内容,9-2
内容の可視性,9-2
プライベート・オブジェクトとパブリック・オブジェ
クトの比較,9-8
本体,9-2,9-5,13-87
本体なし,9-4
メリット,9-3
モジュール性,9-3
有効範囲,9-4
理解,9-2
例へのリンク,13-87
パッケージ・カーソル,9-11
パッケージ・サブプログラム,1-19
パッケージ宣言
構文,13-84
ハッシュ表
結合配列でのシミュレート,5-5
パフォーマンス
PL/SQL を使用した向上,1-3
メモリーのオーバーヘッドの回避,11-6
問題の回避,11-3
パフォーマンス,
「チューニング」を参照
パブリック・オブジェクト
パッケージ,9-8
パラメータ
IN OUT モード,8-9
IN モード,8-8
OUT モード,8-8
PL/SQL サブプログラム内,8-3
エイリアシング,8-23
カーソル,6-18
仮,6-19
実,6-19
実と仮の対比,8-6
デフォルト値,8-9
モード,8-8
モードのサマリー,8-9
パラメータの引渡し
値方式,8-23
参照方式,8-23
動的 SQL,7-4
バルク
フェッチ,11-16
リターン,11-18
バルク SQL
動的 SQL,7-5
ループ・オーバーヘッドの削減,11-8
範囲演算子,4-9
ハンドラ
PL/SQL の例外,10-2
ひ
比較
NULL,2-26
NULL であるコレクション,5-15
PL/SQL,2-19
演算子,2-21
式の比較,2-23
文字値,3-23
比較演算子,6-6
非空白埋めの方法,3-23
日付
TO_CHAR デフォルトの書式,3-22
変換,3-22
非同期操作,9-9
評価
短絡,2-21
評価の順序,2-19,2-20
表記法
位置表記法と名前表記法の対比,8-7
索引 -17
ふ
ファイル I/O,9-10
ファンクション
CREATE 文で,1-12,1-18
DETERMINISTIC ヒント,8-4
PARALLEL_ENABLE オプション,8-4
PL/SQL,8-1
RETURN 句,8-5
RETURN 文,8-5
概要,8-4
組込み,2-37
コール,8-5
作成,1-12,1-18,8-3
仕様部,8-5
宣言,13-58
パイプライン化,11-31
パラメータ,8-4
表,11-31
部分,8-5
本体,8-5,13-86
例へのリンク,13-61
ファンクション宣言
構文,13-58
フィールド
レコード,5-2
ブール
値の代入,2-18
式,2-23
リテラル,2-7
フェッチ
バルク,11-16
複数のコミット,6-34
副作用,8-8
制御,8-23
複数行コメント,2-8
副問合せ
PL/SQL での使用,6-16
相関,6-17
物理 ROWID,3-7
不明瞭化
CREATE_WRAPPED ファンクション,A-5
DBMS_DDL の CREATE_WRAPPED ファンクション
の使用,A-5
DBMS_DDL パッケージ,A-5
PL/SQL コード,A-1
PL/SQL コードの隠ぺい,A-1
WRAP ファンクション,A-5
wrap ユーティリティ,A-3
推奨事項,A-2
制限,A-2
ソースの表示,A-2,A-6
ヒント,A-2
理解,A-2
プライベート・オブジェクト
パッケージ,9-8
プラグマ
AUTONOMOUS_TRANSACTION,6-36
EXCEPTION_INIT,10-7
RESTRICT_REFERENCES,6-40,7-11,8-23
コンパイラ・ディレクティブ,10-7
プレースホルダ
重複,7-9
索引 -18
プログラム・ユニット,1-12
プロシージャ
ALTER PROCEDURE での再コンパイル,10-19
PL/SQL,8-1
PL/SQL の概要,8-3
コール,1-14,8-4
作成,1-12,1-18,8-3
仕様部,8-4
宣言,13-89
部分,8-4
本体,8-4,13-86
例へのリンク,13-91
プロシージャ宣言
構文,13-89
ブロック
BEGIN,1-5
DECLARE,1-5
END,1-5
EXCEPTION,1-5
PL/SQL,13-8
構造,1-5
構文,13-8
ネスト,1-5
ラベル,2-16
例へのリンク,13-12
ブロック宣言
構文,13-8
文
CASE,13-13
CLOSE,6-11,6-25,13-15
COMMIT,13-23
DELETE,13-35
EXECUTE IMMEDIATE,7-2,13-40
EXIT,13-43
FETCH,6-9,6-24,13-52
FORALL,11-8,13-55
FOR-LOOP,13-72
GOTO,13-62
IF,13-63
INSERT,13-65
LOCK TABLE,13-70
LOOP,13-71
MERGE,13-75
NULL,13-76
OPEN,6-9,13-79
OPEN-FOR,6-21,13-81
OPEN-FOR-USING,13-81
PL/SQL,13-1
RAISE,13-92
RETURN,13-98
ROLLBACK,13-101
SAVEPOINT,13-104
SELECT INTO,13-105
SET TRANSACTION,13-111
UPDATE,13-119
WHILE-LOOP,13-74
代入,13-3
分析関数
CORR,2-37
LAG,2-37
文の終了記号,13-12
へ
め
ベース型
PL/SQL 型,3-17
PL/SQL の数値型,3-3
別名
選択リストでの使用,2-12
変換
データ型,3-20
ファンクション,3-21
変数
IN OUT パラメータとして渡す,1-7
PL/SQL,1-5
PL/SQL の宣言,1-8
REF CURSOR データ型,6-19
値の代入,1-6,2-18
グローバル,9-8
構文,13-24
初期化,2-18
宣言,1-5,2-9
問合せ結果の代入,2-18
バインド,1-7,13-81
ホスト,13-81
例へのリンク,13-26
明示カーソル,6-8
明示的な宣言
カーソル FOR ループのレコード,6-16
明示的なデータ型変換,3-20
メソッド
コレクション,5-18
メモリー
過度のオーバーヘッドの回避,11-6
メリット
PL/SQL,1-2
メンバーかどうかのテスト,2-22
ほ
ポインタ
REF CURSOR,6-19
方法
空白埋め,3-23
代入,3-22
非空白埋め,3-23
文字列の比較,3-23
ホスト配列
バルク・バインド,11-19
本体
カーソル,9-11
パッケージ,9-5,13-87
ファンクション,8-5,13-86
プロシージャ,8-4,13-86
ま
マルチレベル・コレクション
使用,5-17
み
未初期化オブジェクト
PL/SQL による処理,12-3
未処理例外
伝播,10-9
捕捉,10-14
密コレクション
配列とネストした表との相違点,5-3
む
無限ループ,4-7
無名ブロック,1-5
も
文字値
選択,3-25
挿入,3-24
代入,3-22
比較,3-23
モジュール性,1-12
パッケージ,9-3
文字リテラル,2-6
文字列の比較方法,3-23
文字列リテラル,2-6
NCHAR,2-7
戻り型
REF CURSOR,6-20
オーバーロード,8-12
戻り値
ファンクション,8-5
ゆ
有効範囲,2-15
PL/SQL の例外,10-6
コレクション,5-6
識別子,2-15
定義,2-15
パッケージ,9-4
明示カーソル,6-8
明示カーソル・パラメータ,6-9
ループ・カウンタ,4-11
ユーザー定義
PL/SQL の例外,10-6
サブタイプ,3-17
レコード,5-2
優先順位、演算子,2-19
ユニバーサル ROWID,3-7
よ
要素型
コレクション,5-6
要素の参照
使用できる添字範囲,5-11
呼出し、例外
PL/SQL,10-9
読取り専用トランザクション,6-32
索引 -19
予約語
PL/SQL,D-1
PL/SQL での特別な意味,2-4
PL/SQL のリスト,D-1
ら
ラージ・オブジェクト(LOB)データ型,3-10
ラップ
CREATE_WRAPPED,A-5
DBMS_DDL パッケージ,A-5
オンザフライ,A-1
コードの不明瞭化,A-1
推奨事項,A-2
制限,A-2
ソースの表示,A-2,A-6
動的,A-1
ヒント,A-2
理解,A-2
ラップされた
PL/SQL のソース・コード,A-1
ラベル
GOTO 文,4-13
構文,13-11
ブロック,2-16
ブロック構造,13-11
ループ,4-8
ループの終了,4-8
ランタイム・エラー
PL/SQL,10-1
り
リターン
バルク,11-18
リテラル
NCHAR 文字列,2-7
NUMBER データ型,2-5
PL/SQL の型,2-5
構文,13-67
数値,2-5
数値データ型,2-5
日時,2-7
ブール,2-7
文字,2-6
文字列,2-6
例,13-68
リモート・アクセスのインジケータ,2-13
る
ルーチン
外部,8-21
ループ
カウンタ,4-9
カウンタの暗黙的な宣言,4-11
カウンタの反転,4-9
カウンタの有効範囲,4-11
動的範囲,4-11
反復,4-10
ラベル,4-8
ラベル使用の終了,4-8
索引 -20
れ
例外
DBMS_WARNING パッケージの使用,10-18
EXCEPTION_INIT プラグマの使用,10-7
GOTO での分岐,10-13
PL/SQL エラーの処理のヒント,10-15
PL/SQL 宣言の中での呼出し,10-13
PL/SQL での再呼出し,10-11
PL/SQL での宣言,10-6
PL/SQL での伝播,10-9
PL/SQL での未処理の捕捉,10-14
PL/SQL での呼出し,10-9
PL/SQL の OTHERS ハンドラ,10-12
PL/SQL のエラー条件,10-2
PL/SQL の警告メッセージ,10-17
PL/SQL のコンパイル時の警告,10-17
PL/SQL の事前定義,10-4
PL/SQL の事前定義の再宣言,10-8
PL/SQL の事前定義のリスト,10-4
PL/SQL の処理,10-1
PL/SQL のメリット,10-3
PL/SQL の有効範囲規則,10-6
PL/SQL のユーザー定義,10-6
raise_application_error プロシージャ,10-7
RAISE 文での呼出し,10-9
SQLCODE の使用,10-13
SQLERRM の使用,10-13
WHEN および OR の使用,10-12
WHEN 句,10-12
警告メッセージの制御,10-17
事前定義の明示的な呼出し,10-9
定義,13-38
トランザクションの再試行,10-16
ハンドラでの呼出し,10-13
例外が呼び出された後に実行を続ける方法,10-15
例外の位置を識別するためのロケータ変数,10-16
例へのリンク,13-39
例外処理
OTHERS ハンドラの使用,10-12
PL/SQL,10-1
PL/SQL 宣言としての呼出し,10-13
ハンドラでの呼出し,10-13
例外処理部
PL/SQL ブロック,1-5
ファンクション,8-5
プロシージャ,8-4
例外定義
構文,13-38
例外の再呼出し,10-11
例外ハンドラ
OTHERS ハンドラ,10-2
RAISE 文の使用,10-11,10-12
SQLCODE ファンクションの使用,10-13
SQLERRM ファンクションの使用,10-13
WHEN 句,10-12
概要,1-17
レコード
%ROWTYPE,6-16
RETURNING INTO 句,5-34
ROWTYPE 属性,5-5
値の代入,5-31
暗黙的な宣言,6-16
概要,1-16
関連したデータ項目のグループ,5-2
更新,5-33
コレクションのバルク・バインド,5-34
宣言,5-28
操作,5-30
挿入,5-32
挿入 / 更新に関する制約,5-34
代入の制限,5-31
定義,1-9,5-28,13-93
ネスト,5-29
パラメータとして渡す,5-30
比較,5-32
ファンクションの戻り値としての使用,5-30
フィールドのグループ,5-5
例へのリンク,13-94
レコード定義
構文,13-93
列の別名
カーソル・ループ内の式の値,6-16
必要な場合,2-12
連結演算子,2-23
NULL の扱い,2-28
ろ
ローカル・サブプログラム,1-19
ロールバック
FORALL 文,11-11
暗黙的,6-31
ロケータ変数
例外での使用,10-16
ロック
FOR UPDATE 句の使用,6-33
上書き,6-33
トランザクション処理,6-29
モード,6-29
論理 ROWID,3-7
論理演算子,2-20
わ
ワイルドカード,2-22
索引 -21
索引 -22
Fly UP