アットウィキロゴ

技術情報 > Oracle > PLSQL

Top > 技術情報 > Oracle > PLSQL

PL/SQLの概要

PL/SQLの実行

SQL*Plus で実行したり、CやCOBOLプログラム中に埋め込んだりして実行
複数のSQL文を含むSQLブロックをブロック単位で一度に送信
アプリケーションとOracle間の通信料を削減でき、パフォーマンス向上

サポートするSQL文

select文・DML文・トランザクション制御のみ

dbms_sqlパッケージ

DDL・動的SQL文は、dbms_sqlパッケージによりPL/SQL内での実行が可能になる

動的SQL

表名・列名を実行時に指定することができ、DDL文内で利用する

サポートするデータ型

Oracle Serverで提供するすべてのSQLデータ型をサポートする
データベース表の各列の属性に対応する変数を宣言し、処理を行える
データ型のサブタイプ ANSI/ISO・IBM型に対して、互換性を持たせるためのデータ型

PL/SQLエンジンの所在

サーバー側・ツール側の2通り

サーバー側 ~

 アプリがサーバへ送信・サーバー側で解析・プロシージャの実行後、同一サーバー上のSQL文エクゼキュータに送信
 埋め込み型のPL/SQL実行プロセス:DBトリガー・ファンクション・パッケージ

ツール側 ~

 アプリは同一サーバのエンジンへ送信・解析・プロシージャの実行号、サーバー上のエクゼキュータに送信
 Developer Forms/Reports : ストアドプロシージャ・DBトリガー・パッケージ
 共にPL/SQLエンジンへアプリが送信するものはPL/SQLブロック

PL/SQLブロックの構成

宣言部・実行部・例外処理部
 宣言部 DECLARE以下 スカラー型・コレクション型(複合型)もサポート
  変数・定数の宣言 配列・表・カーソル・プロシージャ・関数の定義
 実行部 BEGIN以下 記述が必須 SQL文を実行 子ブロックを挿入
 例外処理部 EXCEPTION以下 実行部での例外処理を記述
終了の記述は END;

コメントアウト

一行のみ -- 範囲指定 /* */

宣言部

変数・定数の命名規則

30バイト以内 先頭は文字 予約後は不可

名前の優先順位

SELECT 文・WHERE 文では、列名>変数名・定数名>表名
INTO 句などのように列を指定できないものには、変数名

変数の宣言

変数名 データ型 [ not null ][ (:=/default) 初期値];
not nullの場合には、必ず指定・複数の変数名を一度に指定できない

定数の宣言

定数名 constant データ型 (:=/default) 初期値;
宣言部でのみ一度だけ値を代入可能

ブール変数

変数名 boolean ; AND / OR / NOT を使用して true / false / nullのいずれかがが入る

LOB型の取り扱い

一つの表の複数列に対して定義が可能 列にはLOBロケータのみが格納
CLOB / NCLOB / BLOB / BFILE

システム環境変数の取得

select USER / SYSDATE from dual;

バインド変数

SQL*Plus環境でバインド変数を宣言すると、SQL*Plus内及びPL/SQLの複数ブロックで参照可
SQL*PlusからSQL文及びPL/SQLブロックへ変数を受け渡す時に使用
SQL*Plusでの宣言 variable バインド変数名 データ型
SQL*Plusでの表示 print バインド変数名
PL/SQLブロック内で、バインド変数を参照するには、変数名の前にコロンをつける :変数名 := 右辺 ;

dbms_outputパッケージ

dbms_output.put_line ( ); 括弧内にSQL*Plusのバッファより出力するデータを指定
PL/SQLブロック内でバインド変数などを取得して表示できる
SQL*Plusでは、set serveroutput on を指定する必要

複合データ型の宣言

索引付き表 type 表名(型) is table of データ型 [not null] index by binary_integer;
 作成表名 表型; < 索引付き表の宣言 → サイズ制限なし
レコード type レコード名(型) is record ( フィールド名 データ型 [not null][:=式], .... ) ;
 レコード変数名 レコード型; < フィールドを持つレコードの宣言 

索引付き表のメソッド

変数名.メソッド[(n[,m])]
delete(n,m) / exists(n) / count / first / last / prior(n) / next(n) / trim

レコードの索引付き表

DB表のような2次元表が型として定義可能
 1.レコードの宣言(表の列定義に対応)
 2.表型を宣言したレコードの集まりとして宣言
 3.2次元表名 レコードの索引付き表型; の形で宣言 

%TYPE属性

DBの列定義・以前に宣言された別の変数の型を参照できる
利点 参照先が未知の時や変更された時・複数を宣言する場合など
 表の列の属性を指定する場合 表名.列名%TYPE
第n行のある列の属性を指定するには、2次元表名(n).列名%TYPE
not null は継承しない

%ROWTYPE属性

DB表から選択された行・レコード型のフォーマットを参照できる
第n行の列定義を指定するには、2次元表名(n)%ROWTYPE
not null は継承しない 

実行部

変数への代入

左辺 := 右辺  データ型が同じ 或いは互換性がある必要
右辺には、変数・定数・値・式・SQL関数の記述が可能

select文を使用した変数への代入

select 列名1,列名2,列名3 into 変数1,変数2,変数3 from 表名;
単一行が返る場合のみ 複数行が返る場合はカーソル処理

DML文の実行

DML実行時に処理対象が存在しなくても、エラーにならずにそのまま進行

暗黙的変換

明示的に変換を行った方がパフォーマンスが良い システムのオーバーヘッドの発生
char / varchar2 との変換は、どの型にもどの型からも相互変換可能
long へは、rowid型から変換できない long が変換可能なのは、char / varchar2 / raw のみ
number と bin_int と pls_int は相互に変換可能

明示的変換

SQL変換関数による明示的変換
number -> to_char, to_date : date -> to_char : char -> to_number, to_date
RAW型は、16進数へ変換しchar型へ格納 rawtohex <-> hextoraw
ROWID型は、char型へ格納 rowidtochar <-> chartorowid

制御文

ループやカーソル処理を行える decode / dump / vsize / グループ関数などは使用できない

分岐制御

IF 条件 THEN 処理 ELSIF 条件2 THEN 処理2 ELSE 処理3;
CASE 変数名など WHEN 値 THEN 結果; WHEN 値2 THEN 結果2; ELSE 結果n END;
CASE WHEN 条件 THEN 処理; ... ELSE 処理n; END;
条件において、等号は「=」であって「==」や「:=」は使えない

反復制御

LOOP EXIT WHEN 終了条件; 処理; END LOOP;
LOOP IF 条件 THEN EXIT; END IF; 処理; END LOOP;
FOR カウンタ名 IN 最小値 .. 最大値 LOOP 処理; END LOOP;
FOR カウンタ名 IN REVERSE 最小値 .. 最大値 LOOP 処理; END LOOP;
FORループにおいて、REVERSEであっても最小値が先
小数値を入れた場合、小数第一位で四捨五入される
WHILE 条件 LOOP 処理; END LOOP;
反復制御に関するカウンタ名は、宣言部で変数宣言をしてはいけない ( bin_pls型で自動定義 )
[<<ラベル名>>] をループ前に、END LOOP ラベル名;で終わると、ネストループが可能

カーソル

結果セットへアクセスするためのポインタ
カーソル属性はSQL文で使用できない

結果セット

select文によって選択された行の集合

明示カーソル

宣言・オープン・フェッチ・クローズを明示的に行う
select文で複数の行を参照する場合にも使用 DML文は指定できない
宣言:cursor カーソル名 is select文;

行名 カーソル名%ROWTYPE;~

オープン:open カーソル名;
フェッチ:fetch カーソル名 into 行名;
クローズ:close カーソル名;
フェッチでは、行より一セット取得のみ、ループで実行させる

明示カーソルのロック

for update [of 列1[,列2]] [nowait] 宣言部のselect文の最後 order by - よりさえも後に記述
 カーソル範囲の行をロックし、ブロック内での更新・削除の間有効
 他のトランザクションによりロックされている場合、nowait指定であればエラーで停止
where current of カーソル名; 実行部のupdate文・delete文の最後 必ずfor update句の宣言が必要
※lock table文で表を指定すると、表全体をロック可能

明示カーソルの状態

%NOTFOUND fetch実行時に、取り出す行がない場合 true(例:exit when カーソル名%NOTFOUND)
%FOUND 取り出す行がある場合 true
%ROWCOUNT 取り出し行の累計
%ISOPEN カーソルがオープンしている間 true
%NOTFOUND / %FOUND / %ROWCOUNT は、オープンしていない場合、エラー又は例外処理
%NOTFOUND / %FOUND は、オープン後、初めのfetch文まで false
2次元表をカーソルで回せば、DML文などで行を処理できる 行名.列名
カーソルFORループ カーソルを宣言部で宣言するのみ 行名宣言不要 
 カウント名はループ内での行名、%ROWTYPE属性となり行名.列名%TYPEで属性取得

パラメータ付き明示カーソル

宣言文にて、引数を指定できる (例:cursor カーソル名 ( num number ) is select)
ただし引数のサイズは指定しない

暗黙カーソル

単一select行・DML文でカーソル取得 複数行返る場合・結果がない場合エラー又は例外処理

SQLカーソル

SQL%NOTFOUND SQL文が行を取り出さなかった場合 true
SQL%FOUND SQL文が行を取り出した場合 true
SQL%ROWCOUNT SQL文が実行された累計
SQL%ISOPEN 常にfalse なぜならSQLカーソルは暗黙カーソルであるから

例外処理

例外の種類

事前(内部)定義例外 PL/SQLの使用として、事前に定義されている
ユーザー定義例外 開発者が独自に例外を定義したもの

例外の宣言

宣言部で行う 例外名 exception;

例外の発生

実行部にて、raise 例外名; で明示的に発生可能
実行部で例外が発生した場合、例外処理部の例外ハンドラのルーチンで処理が行われる
その時制御は例外ハンドラへ移り、制御はブロックを抜け実行環境へ戻る(実行部には戻せない)
対応する例外ハンドラが(OTHERSさえも)ない場合、実行環境にエラーを返す

例外処理の書式

WHEN 例外名1 [OR 例外名2] THEN 処理1; [WHEN OTHERS THEN 処理2;]

エラー処理関数

処理中の例外についての情報は、SQLCODE 及び SQLERRM を参照
SQL文で直接利用できない為、予め宣言しておいた変数に代入して利用
SQLCODE (Oracleエラーコード) は number型
SQLERRM (SQLCODEに対応するエラーメッセージ)は varchar(n)型
例外が発生していない場合、SQLCODE = 0 ; ユーザー定義例外は指定なくばSQLCODE = +1

事前定義の例外

Oracle Server によって多数の例外が処理及びエラーコードに関連付けられている
access_into_null / collection_is_null / cursor_already_open / dup_val_on_index
invalid_cursor / invalid_number / login_denied / no_data_found / not_logged_on
program_error / rowtype_mismatch / self_is_null / storage_error / subscript_beyond_count
subscript_outside_limit / sys_invalid_rowid / timeout_on_resource / too_many_rows
value_error / zero_divide

エラーのユーザー定義

非事前定義例外の指定 OTHERS か 宣言 例外名 exception; pragma exception_init (例外名, エラーコード);
エラーをユーザー定義&発行する raise_application_error (エラーコード, エラーメッセージ);
その時、もし非事前定義が定義されていれば、そのエラーコードで例外処理
もしくは、raise で例外を発行して例外処理
例外参照するブロックの例外処理部では、通常通り WHEN文
ユーザー定義例外で使用できるエラーコードの範囲は、-20000 〜 -20999

ブロックのネスト

ネストブロック

実行部・例外処理部で記述する「無名PL/SQLブロック」と宣言部で予め宣言する「ストアドプログラム」がある
子ブロックの実行が終わると、親ブロックの次の行へ
例外処理は、親方向へ処理できるまで受け渡す ただし例外発生時点で終了

グローバル変数とローカル変数

親ブロックで宣言された変数をグローバル変数、それ以外をローカル変数と呼ぶ
ループで使用されるカウント名は・・・・
グローバル変数とローカル変数が同名の場合、ローカル変数が優先

ストアドプログラム

呼び出し可能な名前つきのPL/SQLブロック・定義は宣言部(カプセル化)もしくは実行部・例外処理部に埋め込む
ストアドプロシージャとストアドファンクションの2種類
ストアドプロシージャ:特定の処理の実行するストアドプログラム・パラメータを渡し返す
ストアドファンクション:関数のように、パラメータを渡して値を計算するプログラム・return句で返値がある 

プロシージャの定義構文

procedure プロシージャ名 [(パラメータ名 IN / OUT / IN OUT データ型, ..... )] is
 ローカル変数の宣言
begin
 実行部
exception
 例外処理
end [プロシージャ名] ;

プロシージャの呼び出し

プロシージャ名 [(パラメータ名, ....)];

Oracleアーキテクチャ

Oracleインスタンスの構成要素

SGAとバックグランドプロセス

SGAの構成要素

最大サイズ sga_max_size 超えない範囲でlog_buffer以外を動的に変更可
共有プール・データベースバッファキャッシュ・REDOログバッファ

共有プールの構成要素

サイズ shared_pool_size
データディクショナリキャッシュ・ライブラリキャッシュ・ロック

データディクショナリキャッシュ

直近に使われたDDの表と列の定義・ユーザー名・パスワード・権限

ライブラリキャッシュ

直近に使われたSQLの実行計画・解析ツリー・PL/SQL文の解析及びコンパイル済み情報
サーバープロセスは共有プールのライブラリキャッシュとDDキャッシュを使ってSQLを解析
ある文の実行計画が他の文の実行計画に置き換えられる前に問い合わせを再実行する場合、サーバープロセスは文を解析する必要が無いので、アプリケーションのパフォーマンスは向上

データベースバッファキャッシュ

サイズ db_cache_size
直近に使われたブロックのコピーを格納
db_keep_cache_size / db_recycle_cache_size により複数のバッファプールを構成
再利用される可能性が高い(低い)オブジェクトのデータブロックを格納するDBバッファキャッシュ
db_nK_cache_sizeにより非標準ブロックサイズを指定 ( 2k/4k/8k/16k/32k )

REDOログバッファ

サイズ log_buffer

Oracle データベースの構成要素

データファイル・REDOログファイル・制御ファイル
初期化パラメータファイル・パスワードファイル・アーカイブREDOログファイル

問い合わせ

解析・実行・フェッチのフェーズを経て処理される
ユーザープロセスはサーバープロセス ( Snnn ) に問い合わせ 以下はSnnnが主体
解析フェーズ 文の妥当性をチェックし、共有プール内でコンパイル、ユーザーにステータスを返す
実行フェーズ DBバッファキャッシュから必要なブロックを探し、見つからない場合データブロックから直接読み実行
フェッチフェーズ 結果を順次、ユーザーへ返す

DML文の流れ

1.解析フェーズを終えた後に、変更の対象をロック ( ビットマップでは全体をロック )
2.変更時には変更前後の値がREDOログバッファに記録される
3.変更前の値はUNDOセグメントに保存される
4.元データを新データに更新
delete 文が実行された場合、変更前の値として削除前の行が格納される
insert文が実行された場合、変更前の値として場所情報 ( ROWID ) のみが格納される

トランザクションの終了

コミット・DDL文
1.REDOログバッファにSCNとコミットレコードを書き込む
2.LGWRがREDOログバッファのエントリをREDOログファイルに書き込む
3.Snnnはユーザーに「コミット完了」が伝える
4.Snnnは、DBバッファキャッシュに「トランザクション完了」と「リソースロック解除」を書き込む

SCN

コミット完了毎に割り当てられる一意の番号 データの同期、読み取り一貫性を保証する内部タイムスタンプ

タグ:

+ タグ編集
  • タグ:
最終更新:2007年11月15日 07:21