ODBC の使用
ここでは、Oracle と SQL Server が ODBC をどのように使用するかについて説明し、ODBC を用いたアプリケーション開発または移行についての情報を提供します。
推奨変換ストラテジ
Oracle のアプリケーション コードを SQL Server のアプリケーション コードに変換する手順は次のとおりです。
アプリケーションが Oracle Pro*C または Oracle Call Interface(OCI)を使用して書かれている場合は、ODBC への変換を考えます。
SQL Server のデフォルトの結果セットとカーソル オプションについて理解し、アプリケーションにとって最も効率のよいフェッチ戦略を選びます。
Oracle の ODBC SQL データ型を SQL Server の ODBC SQL データ型に正しくマッピングしなおします。
ODBC 拡張 SQL の拡張機能を使用して SQL 汎用ステートメントを作成します。
SQL Server アプリケーションに必要な手動コミット モードを決定します。
アプリケーションのパフォーマンスをテストし、必要に応じてプログラムを修正します。
ODBC のアーキテクチャ
Microsoft は ODBC SQL Server ドライバとして 16 ビットと 32 ビットの両バージョンを提供しています。32 ビットの ODBC SQL Server ドライバは、スレッド セーフです。ドライバは、共有ステートメント ハンドル(hstmt)、接続ハンドル(hdbc)、環境ハンドル(henv)に対する複数スレッドによる同時アクセスを防止します。しかし、ODBC プログラムが複数のスレッドを使用するときでも、このプログラムは依然としてステートメントと接続空間内の処理を適切な順番に維持する役割を果たします。
Oracle の ODBC ドライバは、さまざまなベンダから提供されているので、アーキテクチャや処理には多くの可能性が考えられます。ODBC ドライバがアプリケーションの要件を満たしているかどうかも、ベンダに問い合せて確認する必要があります。
ほとんどの場合、Oracle の ODBC ドライバは SQL*Net を使用して Oracle RDBMS に接続します。ただし、Personal Oracle に接続する場合は SQL*Net を使用できない場合もあります。
次の図は 32 ビット環境のアプリケーション/ドライバ アーキテクチャです。
サンクという用語は、関数呼び出しをインターセプトし、16 ビット コードと 32 ビット コードの間の変換を行うためのなんらかの特殊処理をした後、制御をターゲット関数に渡すことを意味します。ODBC ドライバ マネージャと ODBC ドライバとの間には ODBC カーソル ライブラリを常駐させることができます。その場合、どのように常駐させるかに注意してください。このライブラリを使用すると、順方向専用カーソルしかサポートしないドライバに加えて、双方向スクロール可能なカーソル サービスが得られます。
順方向専用カーソル
結果セットとカーソルの扱いは Oracle と SQL Server とで異なります。この違いを理解できるかどうかは、クライアント アプリケーションを Oracle から SQL Server に移行して最適化するうえでの重要なポイントになります。
Oracle では、SELECT コマンドによって得られた結果セットはすべて、クライアント アプリケーションでフェッチされると順方向専用カーソルとして扱われます。これは、開発ツールとして ODBC、OCI、埋め込み型 SQL など何を使用するかとは無関係に当てはまることです。
デフォルトでは、クライアント プログラムがネットワーク経由で Oracle の FETCH コマンド(たとえば、ODBC の SQLFetch)をサーバーに投げると、サーバーから 1 行返されます。クライアント アプリケーションが一度に複数行をサーバーから取り出したい場合は、プログラムの中に配列を定義し、配列のフェッチを実行しなければなりません。
Oracle ではマルチバージョン方式の同時実行モデルが用いられているため、フェッチから次のフェッチまでの間にサーバー側で読み取り専用カーソル用にロックをかけることはありません。プログラムが FOR UPDATE 句で更新可能カーソルを指定しているときは、SELECT コマンドがオープンされるときにその中で要求された行がすべてロックされます。このような行レベルのロックは、プログラムが COMMIT または ROLLBACK 要求を実行するまで設定されたままになります。
SQL Server では、SELECT ステートメントは常にサーバーのカーソルと関連付けられているとは限りません。デフォルトでは、SQL Server は SELECT ステートメントによって得られるすべての結果セット行を単にクライアントに戻すだけです。この結果セット行の転送は SELECT が実行されるとすぐに開始されます。あるいは、ストアド プロシージャ内の SELECT ステートメントを用いてクライアントに結果セットを戻すこともできます。さらに、EXECUTE ステートメントを使用すれば、1 つのストアド プロシージャとコマンドのバッチのどちらでも、複数の結果セットを戻すことができます。
SQL Server クライアントでは、デフォルトの結果セットをサーバーから取得した後は、クライアント内部で結果セットのフェッチを行う必要があります。デフォルトの結果セットについては、クライアント側でフェッチを行ってもサーバーとの間でやり取りが発生することはありません。デフォルトの結果セットに対するフェッチでは、ローカル ネットワーク バッファからプログラム変数にデータが取り出されるだけです。このようなデフォルトの結果セットモデルは、サーバーとの間でネットワーク上を 1 往復するだけで複数のデータ行をクライアントに戻すことができる効率的なメカニズムとなります。一般に、ネットワーク上でサーバーとの間の往復回数を最小限にすることは、クライアント/サーバー アプリケーションのパフォーマンスを左右する最も重要な要因です。
Oracle のカーソルと比較すると、デフォルトの結果セットでは SQL Server のクライアント アプリケーションの方がいくぶん負荷が大きくなります。SQL Server のクライアント アプリケーションは、EXECUTE ステートメントによって戻された結果セットのすべての行を速やかにフェッチしなければなりません。プログラムのほかの部分に行を 1 行ずつ渡す必要がある場合は、この行を内部配列にバッファしなければなりません。すべての結果セット行をフェッチしないと SQL Server との接続がビジーのままになります。
このような状態が発生すると、そのほかの作業(UPDATE ステートメントなど)を実行できなくなり、結果セット行が全部フェッチされるか、あるいはクライアントが要求を取り消すまで待たなくてはなりません。さらに、サーバーはフェッチが終了するまでテーブル データ ページに対する共有ロックを解除しないので、できるだけ早くすべての行をフェッチする必要があります。この手法は Oracle アプリケーションに一般に見られるインクリメンタルなフェッチ方式とは対極をなしています。
サーバー カーソル
ネットワークを介して結果セットを順にフェッチする必要性に対応するために、SQL Server では「サーバー カーソル」を用意しています。SQLSetStmtOption を呼び出して SQL_CURSOR_TYPE オプションを設定するだけで、アプリケーションでサーバー カーソルを要求することができます。
SELECT ステートメントをサーバー カーソルとして実行すると、EXECUTE ステートメントによってカーソル識別子だけが戻されます。その後のフェッチ要求では、一度に取り出す行数を指定するパラメータと一緒にカーソル識別子がサーバーに戻されます。サーバーは要求された行数の行を戻します。
フェッチ要求から次のフェッチ要求までの間、接続は解放されるので、他のコマンド(他のカーソルの OPEN または FETCH 要求など)を実行することができます。ODBC から見ると、サーバー カーソルを用いることで SQL Server ドライバが 1 つの接続で複数のアクティブ ステートメントをサポートできるようになることを意味します。
さらに、サーバー カーソルはフェッチ要求から次のフェッチ要求までの間にロックを解除するのが普通なので、フェッチの間は一時停止してユーザー入力を受け取っても他のユーザーには影響しません。サーバー カーソルはオプティミスティックな競合検出とペシミスティックなスクロール ロック同時実行オプションのどちらを使用しても適所で更新できます。
このような機能があるため、Oracle 開発者にとってはサーバー カーソルを使用したプログラミングの方が馴染みやすいようですが、サーバー カーソルにもデメリットはあります。デフォルトの結果セットを用いる場合に比べ、サーバー カーソルは、次のデメリットが考えられます。
大きなサーバー リソースを必要とします。カーソルの状態に関する情報を保持するための一時格納領域がサーバー側で必要になるからです。
特定の結果セットの検索にかかる処理量が多くなります。サーバー カーソルでの EXECUTE ステートメントと各フェッチ要求の都度、サーバーとの間でやり取りが必要になるためです。
サーバー カーソルでサポートするバッチ プロシージャとストアド プロシージャの面で融通がききにくくなります。サーバー カーソルは SELECT ステートメントを一度に 1 つしか実行できないのに対し、デフォルトの結果セットは、複数の結果セットを戻すバッチ プロシージャやストアド プロシージャ、あるいは SELECT ステートメント以外のステートメントを含むバッチ プロシージャやストアド プロシージャに使用できるからです。
以上のような理由により、サーバー カーソルを使用するのは、アプリケーションの中でこの機能が必須である箇所にとどめておく方がよいでしょう。サーバーカーソルの使用例は、SQL Server ODBC サンプル プログラム ファイルの Ssdemo.cpp ファイル中の LIST_STUDENTS 関数にあります。
スクロール可能カーソル
Oracle RDBMS は順方向スクロール カーソルだけをサポートします。各行はクエリで指定された順序にアプリケーションにフェッチされます。Oracle は、既にフェッチした行まで逆向きに移動する要求を受け付けません。Oracle で逆向きに移動する唯一の方法は、カーソルを閉じ、それを再び開くことです。ただし、この方法ではその時点でアクティブなクエリ セットの最初の行に戻ってしまいます。
SQL Server はスクロール可能カーソルをサポートするため、SQL Server のカーソルは任意の行に移動できます。順方向と逆方向の両方にスクロールが可能です。ユーザー インターフェイスを必要とする多くのアプリケーションでは、スクロールは有用な機能です。スクロール可能カーソルを使用があれば、アプリケーションは一画面分の行を一度にフェッチし、それ以外の行はユーザーからの要求に応じてフェッチするようにできます。
Oracle はスクロール可能カーソルを直接にはサポートしませんが、ODBC オプションを使用すればこれによる制約を最小限に抑えることができます。たとえば、Microsoft Visual Studio に同梱されている Oracle ODBC ドライバの中には、ドライバそのものにクライアントベースのスクロール可能カーソルが用意されているものがあります。
あるいは、ODBC カーソル ライブラリを使用するという方法もあります。このライブラリにあるブロック スクロール可能カーソルは、サポート レベルがレベル 1 の任意の ODBC ドライバに使用できます。このようなクライアント カーソル オプションはいずれも、順方向のフェッチに RDBMS を使用し、結果セットのデータをメモリまたはディスクにキャッシュするという形でスクロールをサポートします。データが要求されると、ドライバは要求されたデータを必要に応じて RDBMS またはそのローカル キャッシュから取り出します。
また、クライアントベースのカーソルは、SELECT ステートメントによって生成された結果セットに対する位置指定 UPDATE および DELETE ステートメントもサポートします。カーソル ライブラリは、行の各列にキャッシュ値を指定する WHERE 句を含む UPDATE ステートメントまたは DELETE ステートメントを構成します。
スクロール可能カーソルが必要であり、Oracle と SQL Server の両方で同じソース コードを維持したい場合は、ODBC カーソル ライブラリを使う方法が便利です。ODBC カーソル ライブラリの詳細については、ODBC の仕様書を参照してください。
SQL Server デフォルトの結果セットとサーバー カーソルの使用に関する指針
SQL Server にはデータのフェッチ方法がいくつかあるため、どの方法をどのようなときに使用すべきか迷うことがあります。適切な判断をするための指針を次に示します。
どのような場合であっても、SQL Server からクライアントに特定のデータを一括して取り出すうえで最も高速なのは、デフォルトの結果セットを使用する方法です。SQL アプリケーションでこれを活用できるかどうか検討してみます。たとえば、バッチ レポート作成では一般に、結果セット全体が一括処理され、処理中にユーザーとの対話やデータの更新も発生しません。
更新可能カーソルがプログラムに必要な場合は、サーバー カーソルを使用します。デフォルトの結果セットでは、位置指定 UPDATE ステートメントまたは DELETE ステートメントを使用した更新はできません。また、更新時にはクライアントベース カーソルよりもサーバー カーソルを使う方がよいです。クライアントベース カーソルでは、検索指定 UPDATE または DELETE ステートメントを使用して、位置指定 UPDATE または DELETE ステートメントをシミュレートします。
スクロール可能な読み取り専用カーソルがプログラムに必要な場合は、ODBC カーソルライブラリやサーバー カーソルを使用するとよいでしょう。ODBC カーソル ライブラリの動作には SQL Server と Oracle との間で互換性があり、サーバー カーソルはネットワーク経由で一度にフェッチするデータの量に関してフレキシブルです。
デフォルトの結果セットを使用するか、ODBC カーソル ライブラリのカーソルをデフォルトの結果セットと併用する場合、できるだけ速やかに結果セットの終わりまでフェッチし、サーバー側で長時間に渡って共有ロックが保持されるのを避けるようにしてください。
サーバー カーソルを使用する場合、SQLExtendedFetch を使用して 1 行ずつではなく、まとまった量の行をまとめてフェッチしてください。これは Oracle アプリケーションでの配列型のフェッチと同じです。サーバー カーソルでは、フェッチ要求の都度、アプリケーションとネットワーク上の RDBMS との間でやり取りが必要になります。
これは、コンピュータの搬入にたとえてみるとわかりやすいと思います。コンピュータを 10 台購入するとします。このとき、1 台だけをトラックに積んで会社に帰り、またコンピュータ販売店まで戻って次の 1 台を運びます。実際にはこのようなことはしないでしょうが、サーバー カーソルを使って SQL Server とプログラムとの間で 1 行ずつフェッチするのは、このように 1 台ずつ運ぶのに似ています。
同じ接続で順方向の読み取り専用カーソルだけを複数開いておく必要があり、かつ結果セット全体を速やかにプログラム変数にフェッチできる場合は、デフォルトの結果セットを使用するとよいでしょう。結果セット全体を速やかにフェッチできるかどうかわからないときは、サーバー カーソルを使用してください。
文字で読むと難しそうに見えるかもしれませんが、実際にはそれほど難しくありません。ほとんどのプログラマは、どの部分で 1 行ずつしか返すことのできないようにしてあるかはよく分っているものです。1 行ずつフェッチするには、サーバー カーソルよりもデフォルトの結果セットのほうが効率的です。
この手法の使用例については、SQL Server ODBC サンプル プログラム ファイルの Ssdemo.cpp ファイル中の LIST_STUDENTS 関数を参照してください。SELECT ステートメントによって複数行が戻される可能性のある場合にのみ、サーバー カーソルを要求している点に注意してください。実行ステップの後、rowset サイズが適切なバッチ サイズに設定されます。これによって、同じ SQLExtendedFetch ループをデフォルト結果セットとサーバー カーソルの両方で効率的に機能させることができます。
カーソルの移行の詳細については、SQL Server の[Books Online]を参照してください。
1 つの接続に対する複数のアクティブ ステートメント ハンドル
ODBC ドライバは、ステートメント ハンドル(hstmt)を使用して、プログラム内の各アクティブ SQL ステートメントをトラッキングします。ステートメント ハンドルは常に RDBMS 接続ハンドル(hdbc)と関連しています。ODBC ドライバ マネージャは、接続ハンドルを使用して要求のあった SQL ステートメントを指定の RDBMS に送信します。Oracle の ODBC ドライバのほとんどは、1 つの接続で複数のステートメント ハンドルをサポートします。しかし、SQL Server の ODBC ドライバは、デフォルトの結果セットを使用すると 1 つの接続で 1 つのアクティブ ステートメント ハンドルしかサポートしません。この SQL Server ドライバの SQLGetInfo 関数は、SQL_ACTIVE_STATEMENTS オプションでクエリを実行すると値 1 を戻します。サーバー カーソルの使用を前提にしてステートメント オプションが設定されている場合は、1 つの接続につき複数のアクティブ ステートメント ハンドルがサポートされます。
ステートメント オプションを設定してサーバー カーソルを要求することの詳細については、SQL Server の[Books Online]を参照してください。
データ型のマッピング
SQL Server ODBC ドライバのデータ型の種類は、どの Oracle ODBC ドライバよりも豊富です。
SQL Server のデータ型
ODBC SQL のデータ型
|
binary
SQL_BINARY
bit}
SQL_BIT
char、character
SQL_CHAR
datetime
SQL_TIMESTAMP
decimal, dec
SQL_DECIMAL
float、double precision、float(n) n = 8〜15
SQL_FLOAT
image
SQL_LONGVARBINARY
int、integer
SQL_INTEGER
money
SQL_DECIMAL
nchar
SQL_WCHAR
ntext
SQL_WLONGVARCHAR
numeric
SQL_NUMERIC
nvarchar
SQL_WVARCHAR
real、float(n) n = 1〜7
SQL_REAL
smalldatetime
SQL_TIMESTAMP
smallint
SQL_SMALLINT
smallmoney
SQL_DECIMAL
sysname
SQL_VARCHAR
text
SQL_LONGVARCHAR
timestamp
SQL_BINARY
tinyint
SQL_TINYINT
uniqueidentifier
SQL_GUID
varbinary
SQL_VARBINARY
varchar
SQL_VARCHAR
timestamp データ型は SQL_BINARY データ型に変換されます。これは timestamp 型の列の値は datetime データではなく、binary(8) データであるためです。これらの値は、timestamp のある行に対する SQL Server の動作の履歴を示すために使用されます。
次の表は、Oracle から Microsoft の Oracle ODBC ドライバへのデータ型マッピングを示しています。
Oracle のデータ型
ODBC SQL のデータ型
|
CHAR
SQL_CHAR
DATE
SQL_TIMESTAMP
LONG
SQL_LONGVARCHAR
LONG RAW
SQL_LONGVARBINARY
NUMBER
SQL_FLOAT
NUMBER(P)
SQL_DECIMAL
NUMBER(P,S)
SQL_DECIMAL
RAW
SQL_BINARY
VARCHAR2
SQL_VARCHAR
ほかのベンダが提供している Oracle ODBC ドライバでは、データ型マッピングが表と異なる場合があります。
ODBC 拡張 SQL
ODBC 拡張 SQL 標準は、ODBC に対する SQL 機能を拡張したものであり、Oracle と SQL Server の両方に備わっている標準外の高度な SQL 機能をサポートします。この標準では、ODBC ドライバは SQL の汎用ステートメントを Oracle と SQL Server のそれぞれに固有の SQL 構文に変換することができます。
ODBC 拡張 SQL 標準を使用すると、述語エスケープ文字、スカラー関数、日付/時刻/タイムスタンプの値、ストアド プログラムなどの外部結合も処理できます。ODBC 拡張 SQL の構文では、次のような拡張のどちらでも使用できます。
--(*vendor(Microsoft), product(ODBC)extension *)--
OR
{extension}
変換は実行時に行われ、プログラム コードを修正する必要はありません。ほとんどのアプリケーション開発の過程では、最も適切な変換方法は、プログラムを作成した後、そのプログラムの実行時に ODBC による RDBMS 変換処理を施すことです。
外部結合
Oracle と SQL Server の外部結合構文には互換性がありませんが、この問題は ODBC 拡張 SQL の外部結合構文を使用すれば回避できます。SQL Server の構文は ODBC Extended SQL/SQL-92 の構文と同一です。唯一の違いは {oj } コンテナです。
ODBC 拡張 SQL と SQL-92
Oracle
SQL Server
|
SELECT STUDENT.SSN,
SELECT
SELECT
FNAME, LNAME,
SUBSTR(LNAME,1,5)
SUBSTRING(LNAME,1,5)
CCODE, GRADE FROM {oj STUDENT
FROM STUDENT
FROM STUDENT
LEFT OUTER JOIN GRADE ON
STUDENT.SSN = GRADE.SSN}
日付、時刻、タイムスタンプの値
ODBC には、日付、時刻、タイムスタンプの値を表すための 3 種類のエスケープ句があります。
種類
簡略構文
形式
|
日付
{d 'value'}
yyyy-mm-dd
時刻
{t 'value'}
hh:mm:ss
タイムスタンプ
{Ts 'value'}
yyyy-mm-dd hh:mm:ss[.f...]
SQL Server アプリケーションよりも Oracle アプリケーションの方が日付形式の影響を大きく受けます。Oracle では DD-MON-YY という日付形式を使用しています。いずれにしても、日付形式モデルに TO_CHAR または TO_DATE 関数を使用して形式の変換を実行します。
SQL Server は一般的な日付形式のほとんどを自動的に変換します。また、自動変換を実行できない場合のために CONVERT 関数も用意されています。
表からわかるように、ODBC 拡張 SQL はどちらのデータベースでも使えます。SQL Server では変換関数は不要です。ただし、ODBC 簡略構文は Oracle と SQL Server の両方に包括的に適用できます。
ODBC 拡張 SQL
Oracle
SQL Server
|
SELECT SSN, FNAME,
SELECT SSN, FNAME,
SELECT SSN, FNAME,
LNAME, BIRTH_DATE
LNAME,
LNAME,
FROM STUDENT WHERE
BIRTH_DATE
BIRTH_DATE
BIRTH_DATE < {D '1970-07-04'}
FROM STUDENT
FROM STUDENT
WHERE BIRTH_DATE <
WHERE BIRTH_DATE <
TO_DATE('1970-07-04',
'1970-07-04'
'YYYY-MM-DD')
ストアド プロシージャの呼び出し
ストアド プログラムを呼び出すための ODBC 簡略構文は、SQL Server のストアド プロシージャと Oracle のストアド プロシージャ、関数、パッケージをサポートしています。オプションとして "?=" を用いると、Oracle の関数または SQL Server のプロシージャに対する戻り値を取得できます。パラメータ構文を使用するのは、呼び出しプログラムとの間で値を受け渡しするためです。ほとんどの場合、この構文は Oracle と SQL Server の両方のアプリケーションに適用できます。
次の例で、SHOW_RELUCTANT_STUDENTS 関数は Oracle パッケージ P1 に含まれています。この関数は PL/SQL カーソルから複数行を戻すものであるため、パッケージ内になければなりません。パッケージ内に存在する関数またはプロシージャを呼び出す場合、パッケージ名をプログラム名の前に置いておく必要があります。
パッケージ P1 内の SHOW_RELUCTANT_STUDENTS 関数は、パッケージ カーソルを使用して複数のデータ行を取り出します。この関数での呼び出しは行ごとに行う必要があります。取り出す行がなくなれば、関数は 0 の値を戻し、取り出す行がないということを表します。Oracle サンプル パッケージとその関数を使用して得られるパフォーマンスは、満足のいくレベルに届かない場合があります。このタイプの処理には、SQL Server のプロシージャを使う方が効率的です。
汎用 ODBC 拡張 SQL
Oracle
SQL Server
|
{?=} call
SQLExecDirect(hstmt1,
SQLExecDirect(hstmt1,
procedure_name
(SQLCHAR *)"{? = call
(SQLCHAR*)"{? = call
[(parameter(s))]}
owner.procedure(?)}",
STUDENT_ADMIN.P1.
SQLExecDirect(hstmt1,
SQL_NTS);
SQL_NTS);
SHOW_RELUCTANT_STUDENTS(?)}",
(SQLCHAR*)"{? = call
STUDENT_ADMIN.
SHOW_RELUCTANT_STUDENTS}",
SQL_NTS);
ネイティブ SQL 変換
Oracle用 と SQL Server 用の ODBC ドライバには種類が多くあるため、拡張 SQL 関数のための変換文字列が必ずしも同じになるとは限りません。アプリケーションでデバッグを行いやすくするには、SQLNativeSql 関数の使用を検討する方がよいこともあります。この関数は、ドライバによって変換されたままの SQL 文字列を返します。
次の例は、スカラー関数 CONVERT を含む SQL 文字列を入力したときに返される可能性がある結果です。列 SSN は CHAR(9)型として定義されていますが、これが数値に変換されます。
元のステートメント
変換後の Oracle ステートメント
変換後の SQL Server ステートメント
|
SELECT(fn CONVERT
SELECT
SELECT CONVERT(INT, SSN)
(SSN, SQL_INTEGER)}
TO_NUMBER(SSN)
FROM STUDENT
FROM STUDENT
FROM STUDENT
サンプル プログラム Common.cpp
サンプル プログラム Common.cpp は ODBC 拡張 SQL 構文を活用したものではありません。このプログラムではビューとプロシージャとを使用して、Oracle と SQL Server とで異なるステートメントや関数を隠しています。このプログラムは ODBC を使用して書かれたものですが、Oracle と SQL Server で共通のプログラムを作成するプログラマにとって、障害と思われるものが意外と簡単に克服できることを示す目的で取り上げました。
このような方法は ODBC を通さない開発環境で使用するのに適しています。ODBC を使用している場合は、ODBC 拡張SQL 構文を使用して Oracle と SQL Server の構文の違いをカバーしてください。
手動コミット モード
Oracle では、データが変更されると自動的にトランザクションが開始されます。変更後は明示的に COMMIT を実行し、変更内容をデータベースに反映させる必要があります。変更を取り消す場合は ROLLBACK ステートメントを使います。
SQL Server では、特に設定しなければ、トランザクションは自動的にコミットされます。これは ODBC の自動コミットと呼ばれます。自動コミットを使用したくない場合は、トランザクション ブロックの先頭に BEGIN TRANSACTION ステートメントを置きます。このステートメントを使う場合は、COMMIT TRANSACTION または ROLLBACK TRANSACTION ステートメントでトランザクションの終了を明示的に定義します。
Oracle アプリケーションとの互換性を保つには、SQLConnectOption 関数を使用して SQL Server アプリケーションを暗黙トランザクション モードにすることをお勧めします。このためには SQL_AUTOCOMMIT オプションを OFF に設定しておく必要があります。次のコードは、この概念を示すためにサンプル プログラムから抜粋したものです。
SQLSetConnectOption(hdbc1, SQL_AUTOCOMMIT,-sql_AUTOCOMMIT_OFF);
SQL_AUTOCOMMIT_OFF オプションは、ドライバに対して暗黙トランザクションを使用するよう指示するためのものです。デフォルトの設定は SQL_AUTOCOMMIT_ON で、この状態のときには自動コミット モードになります。このモードでは各ステートメントが完了するとトランザクションがコミットされます。手動コミット モードから自動コミット モードに切り替えると、その接続で開かれているトランザクションがコミットされます。
SQL_AUTOCOMMIT_OFF オプションが設定されている間は、SQLTransact 関数を使用してトランザクションを明示的にコミットまたはロールバックする必要があります。この関数では、ある接続ハンドルに関連付けられているすべてのアクティブな操作でコミットまたはロールバックが必要です。また、この関数は、環境ハンドルに関連付けられているすべての接続に対してコミットまたはロールバック操作を実行するように要求することもできます。
SQLTransact(henv1, hdbc1, SQL_ROsLLBACK);
SQLTransact(henv1, hdbc1, SQL_COMMIT);
自動コミット モードをオフにすると、ドライバは SET IMPLICIT_TRANSACTIONS ON ステートメントをサーバーに渡します。SQL Server 6.5 以降のバージョンでは、このモードで DDL ステートメントをサポートしています。
手動コミット モードでトランザクションをコミットまたはロールバックするには SQLTransact を呼び出す必要があります。SQL Server のドライバは、トランザクションをコミットするときは COMMIT TRANSACTION ステートメント、トランザクションをロールバックするときは ROLLBACK TRANSACTION ステートメントを送信します。
手動コミット モードを使用すると、SQL Server アプリケーションのパフォーマンスに悪影響が出ることがあります。COMMIT を行うたびにサーバーに COMMIT TRANSACTION 文字列を送信し、サーバーとの間でやり取りが発生するためです。
単独のアトミック トランザクション(単独の INSERT、UPDATE、DELETE の直後に COMMIT が続いたもの)がある場合は、自動コミット モードを使用してください。
サンプル プログラムでは、Oracle RDBMS 用の類似のアプリケーションと同じような処理を行う SQL Server アプリケーションの開発がいかに容易であるかを示すため、アトミック トランザクションに対しても手動コミット モードをオンにしてあります。