システム要件:SQL Server の一時テーブル sqlservertemp_table に格納された COMPANY, OGB04, OGA01, OGA03 フィールドを、事前にリンク済みの Oracle インスタンス ds へ転送し、Oracle 側での条件付き検索を効率化する。
初期実装手順
- Oracle 側にグローバル一時テーブルを作成
CREATE GLOBAL TEMPORARY TABLE param_buffer ( COMPANY VARCHAR2(50), OGB04 VARCHAR2(100), OGA01 VARCHAR2(100), OGA03 VARCHAR2(100) ) ON COMMIT PRESERVE ROWS; - SQL Server 側で Oracle の一時テーブルをクリア
EXEC ('DELETE FROM param_buffer') AT DS; - バッチ処理による挿入(ロック回避のため)
DECLARE @Chunk INT = 500; WHILE EXISTS (SELECT 1 FROM #TransferData) BEGIN INSERT INTO OPENQUERY(DS, 'SELECT COMPANY, OGB04, OGA01, OGA03 FROM param_buffer') SELECT TOP (@Chunk) COMPANY, OGB04, OGA01, OGA03 FROM #TransferData; DELETE TOP (@Chunk) FROM #TransferData; WAITFOR DELAY '00:00:01'; -- 負荷抑制用遅延 END DROP TABLE #TransferData;
初期案の課題とリスク
- OPENQUERY と EXEC AT の性能問題
遠隔操作は毎回ネットワークラウンドトリップを伴い、パラメータ化が不可能なため柔軟性と効率に欠ける。 - グローバル一時テーブルの並列性欠如
ON COMMIT PRESERVE ROWSではセッション間でデータが干渉し、複数ユーザー同時利用時に汚染される可能性がある。 - 全削除によるデータ競合
DELETE FROM ...が他のセッションのデータまで消去する恐れがあり、整合性を損なう。 - WAITFOR DELAY の非効率性
単純な遅延はリソース待ちを解決せず、スケーラビリティを阻害する安易な対応策である。
改良版設計:セッション分離型テーブル
Oracle 側でセッション識別子を含む永続テーブルを定義:
CREATE TABLE transfer_cache (
trace_id VARCHAR2(64), -- ユニークセッションID
COMPANY VARCHAR2(50),
OGB04 VARCHAR2(100),
OGA01 VARCHAR2(100),
OGA03 VARCHAR2(100)
);
SQL Server 側で転送時に識別子を付与:
DECLARE @TraceID VARCHAR(64) = 'JOB_' + REPLACE(NEWID(), '-', '_');
WHILE EXISTS (SELECT 1 FROM #TransferData)
BEGIN
INSERT INTO OPENQUERY(DS, 'SELECT trace_id, COMPANY, OGB04, OGA01, OGA03 FROM transfer_cache')
SELECT TOP (@Chunk) @TraceID, COMPANY, OGB04, OGA01, OGA03
FROM #TransferData;
DELETE TOP (@Chunk) FROM #TransferData;
END
再利用性を高めるため、ストアドプロシージャとしてカプセル化:
CREATE PROCEDURE PushDataToOracle
AS
BEGIN
DECLARE @TraceID VARCHAR(64) = 'JOB_' + REPLACE(NEWID(), '-', '_');
DECLARE @Chunk INT = 500;
EXEC ('DELETE FROM transfer_cache WHERE trace_id = ''' + @TraceID + '''') AT DS;
WHILE EXISTS (SELECT * FROM #TransferData)
BEGIN
INSERT INTO OPENQUERY(DS, 'SELECT trace_id, COMPANY, OGB04, OGA01, OGA03 FROM transfer_cache')
SELECT TOP (@Chunk) @TraceID, COMPANY, OGB04, OGA01, OGA03
FROM #TransferData;
DELETE TOP (@Chunk) FROM #TransferData;
END
SELECT @TraceID AS TransferKey;
END