2010.03.11 Thursday
PL/SQL文法最速マスター
以下は途中で挫折しています。これを再利用してバージョンアップ版を公開するのは自由です(出典だけ明記してね、はあと)
まえがき
本記事は主に PL/SQL の文法面について解説します。基本的に Oracle 11i の範囲内の文法について取り扱います。
PL/SQL の仕様
Oracleが独自に決めた言語です。類似の言語は幾つかありますが、PL/SQLと呼べるOracle以外のものは、IBM DB2 9.7以降に実装されたものだけだと思ってよいでしょう。
PL/SQL の実行 (CLI編)
PL/SQL で書かれたを実行するためにはCLIでOracleに接続して実行するのが一番手っ取り早いです。GUIベースのDB接続アプリ・開発アプリで実行する方法のも便利ですが、入門としては CLI イメージでよいでしょう。最短のHELLO WOLDをやる場合
CLIのSQL*Plusでログイン後、
※SET SERVEROUTPUT ONは、SQL*Plus上で標準出力表示を簡易に行うためのおまじないで、PL/SQLの直接の構成要素ではありません。このおまじないがないとDBMS_OUTPUT.PUT_LINEで出力が帰ってくる保証はありません。
上記は無名のPL/SQLの実行方法ですが、通常はPL/SQLのオブジェクトをDB内に生成して名前をつけて実行します。プロシージャ(戻り値なし)かファンクション(戻り値あり)のどちらかになります。
基礎
PUT_LINE
言語仕様には画面デバイスへの入出力は定義されてませんので、標準パッケージDBMS_OUTPUTのPUT_LINEを使います。
コメント
--から改行までがコメントになります。
文法チェック
ファンクションかプロシージャをCREATEする際に基本的な文法チェックがかかります。 論理的には文法チェックでチェックできそうなことが全部チェックできるというわけではないですが、基本的な文法構造を満たしていなければ実行できずにエラーが出ます。
文
文の最後にはセミコロン ( ; ) を付けます。
変数の宣言
数値
PL/SQLの数値型は、基本的に当該バージョンのOracleでサポートしている数値型と同等のものが使えます。
PL/SQLの数値演算はOracleのSQLにおける数値演算と同じ型変換が行われます。
代入演算子とインクリメント・デクリメント
代入演算子は以下1つで、インクリメント・デクリメントはありません。
文字列
文字列はシングルクオート( ' )で囲みます。ダブルクオート ( " )は等価ではありませんので要注意です。
文字列操作
文字列操作は、当該バージョンのOracleで使えるSQLに準じます。
結合
分割は簡単にはできません。Oracleの場合は、後述の検索のINSTR/INSTRBと切り出しのSUBSTR/SUBSTRB(文字を指定文字数で切り取る)を組み合わせましょう。
長さ
PL/SQLの配列的なものはちょっと癖があります。
結合配列(PL/SQL表)、VARRAY、ネストした表とあります。一番一般的な配列に近いVARRAYは
要素の個数
・・・あったらいいなぁ。
制御文
if
while
for
loop
case
cとは違ってフォールスルーしない。IF-ELSEと等価。
ここで挫折続きがあるかどうかは神のみぞ知る
http://d.hatena.ne.jp/gifnksm/20100202/1265105961に後でトラバする
まえがき
本記事は主に PL/SQL の文法面について解説します。基本的に Oracle 11i の範囲内の文法について取り扱います。
PL/SQL の仕様
Oracleが独自に決めた言語です。類似の言語は幾つかありますが、PL/SQLと呼べるOracle以外のものは、IBM DB2 9.7以降に実装されたものだけだと思ってよいでしょう。
PL/SQL の実行 (CLI編)
PL/SQL で書かれたを実行するためにはCLIでOracleに接続して実行するのが一番手っ取り早いです。GUIベースのDB接続アプリ・開発アプリで実行する方法のも便利ですが、入門としては CLI イメージでよいでしょう。最短のHELLO WOLDをやる場合
CLIのSQL*Plusでログイン後、
SQL>SET SERVEROUTPUT ONの3行を入力します。 最短の実行要素は
SQL>
SQL>BEGIN DBMS_OUTPUT.PUT_LINE('HELLO WORLD!'); END; SQL>/
SQL>BEGIN 実行したい内容 END;通常は、読みにくいので、
SQL>/
SQL>のように改行を入れて記述します。
SQL>BEGIN
SQL> DBMS_OUTPUT.PUT_LINE('HELLO WORLD!');
SQL>END;
SQL>/
※SET SERVEROUTPUT ONは、SQL*Plus上で標準出力表示を簡易に行うためのおまじないで、PL/SQLの直接の構成要素ではありません。このおまじないがないとDBMS_OUTPUT.PUT_LINEで出力が帰ってくる保証はありません。
上記は無名のPL/SQLの実行方法ですが、通常はPL/SQLのオブジェクトをDB内に生成して名前をつけて実行します。プロシージャ(戻り値なし)かファンクション(戻り値あり)のどちらかになります。
SQL>CREATE OR REPLACE PROCEDURE HELLO_WORLD()で生成して
AS
BEGIN
DBMS_OUTPUT.PUT_LINE('HELLO WORLD!');
END HELLO_WORLD;
SQL>HELLO_WORLD();で実行です。
HELLO WORLD!
SQL>
基礎
PUT_LINE
言語仕様には画面デバイスへの入出力は定義されてませんので、標準パッケージDBMS_OUTPUTのPUT_LINEを使います。
コメント
--から改行までがコメントになります。
-- コメント
文法チェック
ファンクションかプロシージャをCREATEする際に基本的な文法チェックがかかります。 論理的には文法チェックでチェックできそうなことが全部チェックできるというわけではないですが、基本的な文法構造を満たしていなければ実行できずにエラーが出ます。
文
文の最後にはセミコロン ( ; ) を付けます。
変数の宣言
変数名 型名で宣言します。 宣言していない変数に代入することはできません。
数値
PL/SQLの数値型は、基本的に当該バージョンのOracleでサポートしている数値型と同等のものが使えます。
a NUMBER(2,1) := 1.1数値演算
PL/SQLの数値演算はOracleのSQLにおける数値演算と同じ型変換が行われます。
代入演算子とインクリメント・デクリメント
代入演算子は以下1つで、インクリメント・デクリメントはありません。
a := 1.1
文字列
文字列はシングルクオート( ' )で囲みます。ダブルクオート ( " )は等価ではありませんので要注意です。
a CHAR(7) := 'abcdef';
文字列操作
文字列操作は、当該バージョンのOracleで使えるSQLに準じます。
結合
a := 'abcdef' || 'abcdef';分割
b := CONCAT('abcdef', 'abcdef');
分割は簡単にはできません。Oracleの場合は、後述の検索のINSTR/INSTRBと切り出しのSUBSTR/SUBSTRB(文字を指定文字数で切り取る)を組み合わせましょう。
長さ
a := LENGTH('abcdef');切り出し
a := SUBSTR('abcdef', 2); -- bcdef検索
b := SUBSTR('abcdef', 2, 1); -- b
-- 見つからなかったら0が返る配列
a := INSTR('abcdef', 'b'); -- 2
b := INSTR('abcdef', 'c', 4); -- 0
PL/SQLの配列的なものはちょっと癖があります。
結合配列(PL/SQL表)、VARRAY、ネストした表とあります。一番一般的な配列に近いVARRAYは
DECLARE
TYPE varray_char_2 IS VARRAY(2) OF CHAR(2);
varray_a varray_char_2;
BEGIN
varray_a := varray_char_2('element index of 1', 'element index of 2');
DBMS_OUTPUT.PUT_LINE(varray_a(1)); DBMS_OUTPUT.PUT_LINE(varray_a(2)); END; / element index of 1 element index of 2
要素の個数
varray_a.COUNT -- 上の例の場合 2配列の操作
varray_a := varray_char_2('element index of 1', 'element index of 2');連想配列 (のようなもの)
// 先頭を取り出す
DBMS_OUTPUT.PUT_LINE(varray_a.FIRST); -- element index of 1
// 先頭に追加 ・・・はない
// 末尾を取り出す
DBMS_OUTPUT.PUT_LINE(varray_a.LAST); -- element index of 2
// 末尾に追加・・・はない
// 配列サイズを拡張
varray_a.EXTEND(1); -- COUNTが3に
// 部分コピーを得る・・・はない
// 一部を置き換える・・・はない
// 添え字の削除でtrimやdeleteがある。VARRAYは添え字連続の配列だが、
// 結合配列などでは添え字不連続で上述の操作可能。結合配列ではCOUNTとLIMITが
// 異なり、VARRAYは等しい
・・・あったらいいなぁ。
制御文
if
IF 条件 THENif-else
HOGE();
END IF;
IF 条件 THENif-elsif
HOGE();
ELSE
HUGA();
END IF;
IF 条件 THEN
HOGE();
ELSIF 条件 THEN
HUGA();
END IF;
while
WHILE 条件 LOOP
HOGE();
END LOOP;
for
FOR カウンタ変数 IN 最小値..最大値 LOOPカウンタ変数は事前の定義は不要です(通常はむしろしてはいけない)。
HOGE();
END LOOP;
FOR カウンタ変数 IN REVERSE 最小値..最大値 LOOP
HOGE();
END LOOP;
loop
LOOP脱出条件が必要なら任意にIF等を使って記述します。
HOGE();
END LOOP;
case
cとは違ってフォールスルーしない。IF-ELSEと等価。
CASE 条件プロシージャ/ファンクション
WHEN 条件 THEN
HOGE();
WHEN 条件 THEN
FUGA();
ELSE
DOBON();
END CASE;
ここで挫折続きがあるかどうかは神のみぞ知る
http://d.hatena.ne.jp/gifnksm/20100202/1265105961に後でトラバする