SQL*Plusコマンドの@とDEFINEでコピペを減らす

ほとんどのプログラム言語では大量のコピペはダメなソースコードの典型であるものの、SQLでは大量のコピペが平気で行われている。Oracle Database に付属するSQLPlusでは以下のコマンドが使えるので、バッチ・プログラムのようなSQLPlusからSQLを発行するようなプログラムでは、これらを使うことでコピペを大きく減らすことができる。

たとえば年月ごとの表領域を4個作りたい場合、以下のようにできる。

たとえばパーティションする列が同じ表を複数作りたい場合、以下のようにできる。

一つの完全なSQLを呼び出すのに@を使っている人は少なくないけど、こうやって一部だけでも使えるので、PCTFREEとかSTORAGEとか使える場面はけっこう多い。

というわけで、@DEFINEを使うことでコピペをどのように減らせるかはなんとなく分かってもらえただろう。ここで応用。さて、以下のようなSQL文を実行した場合、どのような表が作成されるだろうか?

正解は以下の4つの表である。

  • 2011年8月分のデータが入ったT201105表
  • 2011年8月分のデータが入ったT201106表
  • 2011年8月分のデータが入ったT201107表
  • 2011年8月分のデータが入ったT201108表

ステップごとに説明しよう。まず、divide.sqlの全ての&range.はcrets.sqlの9行目でDEFINEされた値、201108で置き換えられてしまう。これはグローバル変数でよくありそうな変数の初期化の問題なのでdivide.sqlかcrets.sqlのどちらかが UNDEFINE range すべきっぽいが、UNDEFINEするとこのSQLは動作しないことを後ほど説明する。

その直後に@sel201108が展開される。

8行目に入ると、3/4行目の&range.は8行目で定義された値、201105に置き換えられるが、@は展開されたままで変数は置き換えられない。

以下同様に、中身が2011年8月分のT201106表 / T201107表 / T201108表が作られてしまう。

さて、先ほど指摘したUNDEFINEを使うとどうなるだろうか。

つまり、undef_divide.sqlの10行目に来る前に8行目が評価され、この時点では&range.は未定義なので空文字となってしまい、そんなファイルはないと怒られてしまう。

やりたいことを正しく実行するには以下のように記述する。

もっとも簡単な例でクセをまとめておく。以下のSQLは2が返る。

以下のSQLではf1.sqlが実行される。

コメントを残す