第2章 アプリケーションの設計
2.4 コネクション
2.4.2 複数コネクション
アプリケーションの1つのセションで、複数のCONNECT文を実行することによって、複数のコネクションを接続することが できます。これによって、複数のデータベースに対し、データ操作を行うことができます。ここでは、複数コネクションの操 作について、以下の順に説明します。
・
複数コネクションの接続・
現コネクションとSQL文の実行・
現コネクションの変更・
複数コネクションの切断・
複数コネクションでSQL文を実行する場合の注意事項2.4.2.1 複数コネクションの接続
複数のコネクションの接続は、複数のCONNECT文を実行することによって行います。以下に具体例を示します。
2.4.2.2 現コネクションと SQL 文の実行
アプリケーションが複数のコネクションをもつ場合、SQL文の実行対象となるコネクションを決めておく必要があります。SQL 文の実行対象となるコネクションを現コネクションと呼びます。複数のCONNECT文を実行した場合、最後のCONNECT 文で接続したコネクションが、現コネクションとなります。
複数コネクションのプログラミング概要を以下に示します。
[アプリケーション]
:
EXEC SQL CONNECT TO 'DB01' AS 'C1' ; … (1) :
EXEC SQL CONNECT TO 'DB02' AS 'C2' ; … (2) :
EXEC SQL SELECT 在庫数量,倉庫番号 INTO :H1, :H2 FROM S.T … (3) WHERE 倉庫番号=2 ;
: :
EXEC SQL CONNECT TO 'SV3' AS 'C3' USER 'U3/PASS3'; … (4) :
EXEC SQL CONNECT TO 'SV4' AS 'C4' USER 'U4/PASS4'; … (5) :
EXEC SQL SELECT 在庫数量,倉庫番号 INTO :H1, :H2 FROM S1.T1 … (6) WHERE 倉庫番号=2 ;
:
(1)~(3)は、ローカルアクセスの場合です。(4)~(6)は、リモートアクセスの場合です。
(1) 1回目のCONNECT文により、“DB01”に対して“C1”のコネクションを接続します。
(2) 2回目のCONNECT文により、“DB02”に対して“C2”のコネクションを接続します。
(3) 現コネクションの“DB02”に対して単一行SELECT文を実行します。
(4) 3回目のCONNECT文により、サーバ“SV3”に対して“C3”のコネクションを接続します。
(5) 4回目のCONNECT文により、サーバ“SV4”に対して“C4”のコネクションを接続します。
(6) 現コネクションのサーバ“SV4”に対して単一行SELECT文を実行します。
2.4.2.3 現コネクションの変更
複 数 の コ ネ ク シ ョ ン を 接 続 し た 場 合 、SET CONNECTION文 で 現 コ ネ ク シ ョ ン を 変 更 す る こ と が で き ま す 。SET
CONNECTION文を利用することにより、変更した現コネクションのサーバとデータ操作を行うことができます。
現コネクションを変更する際に、トランザクションを終了する必要はありません。しかし、同一のトランザクションで、複数の コネクションに対してデータベースを更新するSQL文を実行することはできません。その際にはトランザクションを一度終 了してください。
現コネクションを変更するプログラミングの概要を以下に示します。
[アプリケーション]
:
EXEC SQL CONNECT TO 'DB01' AS 'C1' ; … (1) :
EXEC SQL SELECT 在庫数量,倉庫番号 INTO :H1, :H2 FROM 在庫表 … (2) WHERE 在庫数量=300 ; :
EXEC SQL COMMIT WORK ; … (3) :
EXEC SQL CONNECT TO 'DB02' AS 'C2' ; … (4) :
EXEC SQL INSERT INTO 伝票( 在庫カラム, 倉庫カラム) VALUES(:H1,:H2) ; … (5) EXEC SQL COMMIT WORK ; … (6) :
EXEC SQL SET CONNECTION 'C1' ; … (7) :
EXEC SQL SELECT 出荷量 INTO :H3 FROM 在庫表2 WHERE XX=100 ; … (8) EXEC SQL COMMIT WORK ; … (9) :
:
EXEC SQL CONNECT TO 'SV3' AS 'C3' USER 'U3/PASS3' ; … (10) :
EXEC SQL SELECT 在庫数量,倉庫番号 INTO :H1, :H2 FROM 在庫表1 … (11) WHERE 倉庫番号=2 ; :
EXEC SQL COMMIT WORK ; … (12) :
EXEC SQL CONNECT TO 'SV4' AS 'C4' USER 'U4/PASS4' ; … (13) :
EXEC SQL INSERT INTO 伝票1(在庫カラム, 倉庫カラム) VALUES(:H1,:H2) ; … (14) EXEC SQL COMMIT WORK ; … (15) :
EXEC SQL SET CONNECTION 'C3' ; … (16) :
EXEC SQL SELECT 出荷量 INTO :H3 FROM 在庫表3 WHERE XX=100 ; … (17) :
(1)~(9)は、ローカルアクセスの場合です。(10)~(17)は、リモートアクセスの場合です。
(1) 1回目のCONNECT文により、“DB01”に対して“C1”のコネクションを接続します。
(2) “DB01”の在庫表から単一行SELECT文で在庫数量と倉庫番号を取り出します。
(3) (2)の操作に対して、トランザクションを終了します。
(4) 2回目のCONNECT文により、“DB02”に対して“C2”のコネクションを接続します。
(5) “DB02”の伝票の在庫カラムと倉庫カラムに、“DB01”から取り出した在庫数量と倉庫番号を追加します。
(6) (5)の操作に対して、トランザクションを終了します。
(7) SET CONNECTION文により、現コネクションを“C1”に変更します。
(8) “DB01”の在庫表2から単一行SELECT文で出荷量を取り出します。
(9) (8)の操作に対して、トランザクションを終了します。
(10) 3回目のCONNECT文により、サーバ“SV3”に対して“C3”のコネクションを接続します。
(11) サーバ“SV3”の在庫表1から、単一行SELECT文で在庫数量と倉庫番号を取り出します。
(12) (11)の操作に対して、トランザクションを終了します。
(13) 4回目のCONNECT文により、サーバ“SV4”に対して“C4”のコネクションを接続します。
(14) サーバ“SV4”の伝票1の在庫カラムと倉庫カラムに、サーバ“SV3”から取り出した在庫数量と倉庫番号を追加しま
す。
(15) (14)の操作に対して、トランザクションを終了します。
(16) SET CONNECTION文により、現コネクションを“C3”に変更します。
(17) サーバ“SV3”の在庫表3から単一行SELECT文で出荷量を取り出します。
トランザクションを終了させずに現コネクションを変更するプログラミングの概要を以下に示します。
[アプリケーション]
EXEC SQL DECLARE CUR1 CURSOR FOR SELECT 在庫数量,倉庫番号 FROM 在庫表 ; EXEC SQL CONNECT TO 'DB01' AS 'C1' ;
: EXEC SQL OPEN CUR1 ;
EXEC SQL FETCH CUR1 INTO :H1,:H2 ; :
EXEC SQL CONNECT TO 'DB02' AS 'C2' ; :
EXEC SQL INSERT INTO 伝票(在庫カラム, 倉庫カラム) VALUES(:H1,:H2) ; :
EXEC SQL SET CONNECTION 'C1' ; :
EXEC SQL FETCH CUR1 INTO :H1,:H2 ; :
EXEC SQL SET CONNECTION 'C2' ; :
EXEC SQL INSERT INTO 伝票(在庫カラム, 倉庫カラム) VALUES(:H1,:H2) ; :
2.4.2.4 複数コネクションの切断
複数コネクションの切断は、CONNECT文で接続した、それぞれのコネクションに対してDISCONNECT文で行います。コ ネクションを切断する場合は、トランザクションは終了した状態でなければなりません。コネクションを切断せずに処理を 終了すると、利用されていないコネクションが残ったままとなります。
複数コネクションを切断するプログラミングの概要を以下に示します。
[アプリケーション]
EXEC SQL CONNECT TO 'DB01' AS 'C1' ; … (1) :
EXEC SQL SELECT 在庫数量,倉庫番号 INTO :H1, :H2 FROM 在庫表 … (2) WHERE 在庫数量=300;
:
EXEC SQL COMMIT WORK ; … (3) :
EXEC SQL CONNECT TO 'DB02' AS 'C2' ; … (4) :
EXEC SQL INSERT INTO 伝票(在庫カラム, 倉庫カラム) VALUES(:H1,:H2); … (5) :
EXEC SQL COMMIT WORK ; … (6) :
EXEC SQL DISCONNECT 'C1' ; … (7) :
EXEC SQL DISCONNECT 'C2' ; … (8) :
:
EXEC SQL CONNECT TO 'SV3' AS 'C3' USER 'U3/PASS3' ; … (9) :
EXEC SQL SELECT 在庫数量,倉庫番号 INTO :H1, :H2 FROM 在庫表1 … (10) WHERE 在庫数量=300 ; :
EXEC SQL COMMIT WORK ; … (11) :
EXEC SQL CONNECT TO 'SV4' AS 'C4' USER 'U4/PASS4' ; … (12) :
EXEC SQL INSERT INTO 伝票1(在庫カラム,倉庫カラム) VALUES(:H1,:H2) ; … (13) :
EXEC SQL COMMIT WORK ; … (14) :
EXEC SQL DISCONNECT 'C3' ; … (15) :
EXEC SQL DISCONNECT 'C4' ; … (16) (1)~(8)は、ローカルアクセスの場合です。(9)~(16)は、リモートアクセスの場合です。
(1) 1回目のCONNECT文により“DB01”に対して“C1”のコネクションを接続します。
(2) “DB01”の在庫表から単一行SELECT文で在庫数量と倉庫番号を取り出します。
(3) (2)の操作に対して、トランザクションを終了します。
(4) 2回目のCONNECT文により、“DB02”に対して“C2”のコネクションを接続します。
(5) “DB02”の伝票の在庫カラムと倉庫カラムに、“DB01”から取り出した在庫数量と倉庫番号を追加します。
(6) (5)の操作に対して、トランザクションを終了します。
(7) “DB01”に対して“C1”のコネクションを切断します。
(8) “DB02”に対して“C2”のコネクションを切断します。
(9) 3回目のCONNECT文により、サーバ“SV3”に対して“C3”のコネクションを接続します。
(10) サーバ“SV3”の在庫表1から、単一行SELECT文で在庫数量と倉庫番号を取り出します。
(11) (10)の操作に対して、トランザクションを終了します。
(12) 4回目のCONNECT文により、サーバ“SV4”に対して“C4”のコネクションを接続します。
(13) サーバ“SV4”の伝票1の在庫カラムと倉庫カラムに、サーバ“SV3”から取り出した在庫数量と倉庫番号を追加しま
す。
(14) (13)の操作に対して、トランザクションを終了します。
(15) サーバ“SV3”に対して“C3”のコネクションを切断します。
(16) サーバ“SV4”に対して“C4”のコネクションを切断します。
2.4.2.5 複数コネクションで SQL 文を実行する場合の注意事項
カーソル操作での注意
カーソルをオープンしたあとに、複数のコネクションにまたがって、同じカーソルの操作を行うことはできません。
ほかのコネクションで同じカーソルを操作するには、カーソルをクローズしたあとでなければなりません。このカーソル操 作の例として、誤った指定例および正しいカーソル操作の例を以下に示します。
例1
誤ったカーソル操作の場合 [アプリケーション]
EXEC SQL DECLARE CUR1 CURSOR FOR SELECT 在庫数量 FROM 在庫表 ; … (1) EXEC SQL CONNECT TO 'DB01' AS 'C1' ; … (2) EXEC SQL OPEN CUR1 ; … (3) EXEC SQL CONNECT TO 'DB02' AS 'C2' ; … (4) EXEC SQL FETCH CUR1 INTO :STOCK ; → エラー … (5) (1) カーソル“CUR1”を宣言します。
(2) “DB01”に対して“C1”のコネクションを接続します。
(3) “DB01”に対して、カーソル“CUR1”をオープンします。
(4) “DB02”に対して“C2”のコネクションを接続します。
(5) “DB02”に対して、カーソル“CUR1”をFETCHすると、すでに“DB01”に対してカーソルがオープンしているため、
エラーとなります。
例2
正しいカーソル操作の場合 [アプリケーション]
EXEC SQL DECLARE CUR1 CURSOR FOR SELECT 在庫数量 FROM 在庫表 ; … (1) EXEC SQL CONNECT TO 'DB01' AS 'C1' ; … (2) EXEC SQL OPEN CUR1 ; … (3) :
EXEC SQL CLOSE CUR1 ; … (4) EXEC SQL COMMIT WORK ; … (5) EXEC SQL CONNECT TO 'DB02' AS 'C2' ; … (6) EXEC SQL OPEN CUR1 ;
:
EXEC SQL CLOSE CUR1 ; (1) カーソル“CUR1”を宣言します。
(2) “DB01”に対して“C1”のコネクションを接続します。
(3) “DB01”に対して、カーソル“CUR1”をオープンします。
(4) カーソル“CUR1”をクローズします。
(5) (3)でオープンしたカーソルを使用して更新操作を行った場合、トランザクションを終了します。
(6) “DB02”にコネクションを接続して、カーソル“CUR1”をオープンします。
更新操作での注意
1つのトランザクションで、複数のコネクションに対してデータベースを更新するSQL文は実行できません。複数のコネク ションのデータを更新する場合は、別々のトランザクションにする必要があります。
この更新操作の例として、誤った指定例および正しい更新操作の例を以下に示します。
例1
誤った更新操作の場合 [アプリケーション]
EXEC SQL CONNECT TO 'DB01' AS 'C1' ; … (1) EXEC SQL CONNECT TO 'DB02' AS 'C2' ; … (2) EXEC SQL UPDATE 在庫表 SET 在庫数量=300 WHERE 品番号=10; … (3) EXEC SQL SET CONNECTION 'C1' ; … (4) EXEC SQL UPDATE 支店表 SET 社員数=100 WHERE 支店番号=80; → エラー … (5) (1) “DB01”に対して“C1”のコネクションを接続します。
(2) “DB02”に対して“C2”のコネクションを接続します。この場合のコネクションが現コネクションになります。
(3) “DB02”に対して更新操作を行います。
(4) “DB01”に現コネクションを変更します。
(5) “DB02”に対する更新操作のトランザクションが終了していないため、“DB01”に対する更新操作はエラーとなりま す。
例2
正しい更新操作の場合 [アプリケーション]
EXEC SQL CONNECT TO 'DB01' AS 'C1' ; EXEC SQL CONNECT TO 'DB02' AS 'C2' ;
EXEC SQL UPDATE 在庫表 SET 在庫数量=300 WHERE 品番号=10;
EXEC SQL COMMIT WORK ; … (1) EXEC SQL SET CONNECTION 'C1' ; … (2) EXEC SQL UPDATE 支店表 SET 社員数=100 WHERE 支店番号=80;
EXEC SQL COMMIT WORK ;
(1) “DB02”に対しての更新操作のトランザクションを終了します。
(2) “DB01”に現コネクションを変更して、“DB01”に対して更新操作を行います。