ワークスINDEXへ
SELECT文の替わりにBEGIN~ENDブロックを使用する  2000/07/05
以下は、当サイトで公開しているフリーウェア exp2csv の readme.txt に書いた話なんですが、 かなり応用範囲が広いので独立して紹介したいと思います。
 
対象となるRDBMSは
・Sybase Adaptive Server Enterprise (旧Sybase SQL Server)
・Sybase Adaptive Server Anywhere (SQL Anywhere)
・Microsoft SQL Server
・他??
 
対象となる言語は、C++, VB, Java, ASP, Access …要するに、接続方法として、 ADO, RDO, DAO, JDBC, ODBC API 等が選択できる言語すべてです。

■SELECT文⇒BEGIN~ENDブロック

ORACLEでは、BEGIN~ENDブロック(無名PL/SQLブロック)を、SQL*Plus などのネイティブなOCIツール以外から実行する場合、 Oracle Objects for OLE や Oracle JDBC Thin Driver などのORACLEネイティブなミドルウェアが必要です (Thin Driverについてはちょと記憶曖昧)。
 
一方、SQL Server系の言語(Tracsact-SQL, Watcom-SQL)の場合は、 汎用的なミドルウェアからBEGIN~ENDブロックを実行する事ができます。
 
SSA + Access のパススルークエリーを例にとります。 パススルーの編集画面で SELECT文の替わりに、
とすると、実行結果として 1 が表示されます。BEGIN~END の間は、 当然、以下の様な複数行の手続き型言語が書けるので、
これを応用して、ストアドプロシージャのOUTパラメータを DAOで受け取る方法を考えた人がいました。ブロック内で、 OUTパラメータを変数に代入し、end の前に『SELECT 変数』 とするのです。接続方法が限定されていた頃の話ですから、 これは大変有効なトリックでした。  
上記は、Access での話ですが、RDBMSに接続し、SELECT文を投げて 表示を行う様なアプリケーションは、
 
  接続
  実行(SQL文の文字列)
  表示などの処理
  切断
 
と云った手順で処理系が構築されるはずです。
これまで述べた手法は、RDBMS が SQL Server系で、かつ SQL文の文字列が動的に変更可能であるならば、 どのようなアプリケーションでも、どのようなミドルウェアでも、 使える技(常識?)なのです。
 
この手法には留意点が2つあります。

■留意点(1) SELECT文の位置によるトランザクションの中断

BEGIN~ENDブロック内に複数のSELECT文があった場合、表示されるSELECT文は、 ブロック内の最初のSELECT文が適用されます。
以下の例では、最後の select cnt は無視され、結果は 0 と表示されます。
これは重要な問題を含んでいます。
それは、途中で無視されるという事は、トランザクションの結果にも影響がある、 と言う点です。以下は SSA の ISQL と 拙作exp2csv で、 同じSQLスクリプトを実行した場合の差異について書いています。
 
●ISQLで実行した場合と振舞いが同じ
以下の場合、SELECT文は最後尾にのみ書かれているので、exp2csv でもトランザクションはロールバックされます。 ●ISQLで実行した場合と振舞いが異なる!
以下の場合、最初のSELECT文以降は無視されるので、exp2csv では、 プログラム終了時にコミットされ、ロールバックは行われません。

■留意点(2) 動的な長文の解析

動的にBEGIN~ENDブロック内のステートメントを変更して実行するという事は、 常に長大なSQL文の解析が行われる可能性を意味します。パフォーマンス・チューニング の観点から見れば好ましくありません。節度ある活用、これが基本です。

ワークスINDEXへ