Amazon Web Services ブログ

SQL Server MERGE ステートメントを例にした SQL ステートメントの Babelfish for Aurora PostgreSQL 移行ベストプラクティス

SQL Server データベースを Babelfish for Aurora PostgreSQL に移行するには、通常、自動タスクと手動タスクの両方を実行する必要があります。自動化タスクには、-rewrite フラグの付いた Babelfish Compass ツールを使用した自動コード変換と、AWS Database Migration Service (AWS DMS) を使用したデータ移行が含まれます。手動タスクには、Babelfish Compass ツールを使用したデータベース互換性チェック、Babelfish でサポートされていない特定のデータベースオブジェクトの移行回避策、および結果の手動検証が含まれます。

この投稿では、SQL Server の MERGE ステートメントを Babelfish 互換の T-SQL コードに自動的に変換する Babelfish Compass ツールの -rewrite フラグ機能に焦点を当てます。この記事で紹介した一例が MERGE ステートメントですが、-rewrite は他の機能にも使用できます。また、結果を手動で検証するベストプラクティスについても説明します。

Babelfish Compass を使用すると、ソースである SQL Server データベースがターゲットの Babelfish データベースと互換性があるかどうか、および Babelfish で現在サポートされていない機能や移行できない機能を確認できます。

PostgreSQL 15 は MERGE をサポートしていますが、Babelfish はまだサポートしていません。また、PostgreSQL の MERGE は SQL Server の MERGE と完全には同じではありません。たとえば、「RETURNING」や「NOT MATCHED BY SOURCE」という句はサポートされていません。

Babelfish Compass の -rewrite フラグの概要

-rewrite フラグを使用すると、Babelfish Compass 評価レポートの「unsupported」セクションに含まれている MERGE ステートメントを変換することができます。

コマンドプロンプトで Babelfish Compass ツールを実行します。

Mac および Linux でコンパスを実行するための手順はこちら。

BabelfishCompass.bat MyFirstReport C:\work\merge_example.sql -rewrite -reportoption xref
Bash

-rewrite フラグは、Babelfish Compass 評価レポートで、Babelfish ターゲットとの互換性を確保するために SQL コードを手動で書き直すよう提案されている場合に役立ちます。

Babelfish-compatible の T-SQL コードに変換する手作業の一部を取り除くことができます。ただし、対応する書き換えられた SQL コードを注意深く確認する必要もあります。

SQL Server の MERGE ステートメントの理解

SQL Server の MERGE は、挿入、更新、削除を 1 つのステートメントとトランザクションにまとめます。MERGE ステートメントは、ソーステーブルから行を選択し、1 回のトランザクションでターゲットテーブルに対して複数の DML 操作を実行します。

SQL Server MERGE のシナリオを示すために、SQL Server データベースと Babelfish に次のテストテーブルを作成します。

Person_Target はターゲットテーブルで Person_Source はソースで、その行はマージ条件に基づいて Person_Target テーブルにマージされます。

CREATE TABLE dbo.Person_Target(
PersonID int NULL,
PersonName varchar(100) NULL
)

CREATE TABLE dbo.Person_Source(
PersonID int NULL,
PersonName varchar(100) NULL
)
SQL

次の INSERT ステートメントは、Person_Source テーブルと Person_Target テーブルにサンプルデータを挿入します。

INSERT INTO Person_Source values 
(1,'Ana Carolina Silva') ,(3,'Carlos Salazar'), (4,'John Doe')
INSERT INTO Person_Target values 
(1,'Ana Carolina '),(2,'Diego Ramirez') ,(3,'Carlos Salazar')
SQL

次のコードは、Person_Source テーブルのデータを Person_Target テーブルにマージします。MERGE の後のセミコロンは実際には必須です。

MERGE Person_Target T
USING Person_Source S ON T.PersonID=S.PersonID

WHEN MATCHED THEN
UPDATE SET PersonName=S.PersonName


WHEN NOT MATCHED BY TARGET
THEN
INSERT (PersonID,PersonName)
VALUES (S.PersonID,S.PersonName)

WHEN NOT MATCHED BY SOURCE
THEN
DELETE;
SQL

Person_Target テーブルの各行について、SQL Server はマージ条件と呼ばれる検索条件を評価します。条件が一致すると、結果が true になり、SQL Server は Person_Source テーブルの対応するデータでターゲットテーブルの行を更新します。どの行でも条件に一致しない場合、結果は false となり、SQL Server は対応する行をソーステーブルからターゲットテーブルに挿入します。ソーステーブルのどの行でも条件が一致しない場合、その行はターゲットから削除されます。次の図は、このワークフローを示しています。

ターゲットテーブルを検証し、Person_Target テーブル内のデータが前の図と一致するかどうかを確認できます。

Babelfish での SQL Server MERGE ステートメントの書き換え

PostgreSQL の場合、MERGE ステートメントのような構造はありません。ただし、Compass ツールは MERGE を Babelfish の個々の挿入、更新、削除ステートメントとして書き換えることができます。

次のステートメントは、Babelfish に Person_Source テーブルと Person_Target テーブルを作成し、データを挿入します。

CREATE TABLE dbo.Person_Target(
PersonID int NULL,
PersonName varchar(100) NULL
);
CREATE TABLE dbo.Person_Source(
PersonID int NULL,
PersonName varchar(100) NULL
);


INSERT INTO Person_Source values 
(1,'Ana Carolina Silva') ,(3,'Carlos Salazar'), (4,'John Doe');
INSERT INTO Person_Target values 
(1,'Ana Carolina '),(2,'Diego Ramirez') ,(3,'Carlos Salazar');
SQL

次のコードは、レポートフォルダー内の rewrite というフォルダー内に自動的に生成されます。

/* original MERGE statement -- MERGE Person_Target T USING Person_Source S ON T.PersonID=S.PersonID WHEN MATCHED THEN UPDATE SET PersonName=S.PersonName WHEN NOT MATCHED BY TARGET THEN INSERT (PersonID,PersonName) VALUES (S.PersonID,S.PersonName) WHEN NOT MATCHED BY SOURCE THEN DELETE; -- end original MERGE statement */

/*REWRITTEN*/ 
/* --- start rewritten MERGE statement #1 --- */
/* Note: please review/modify the rewritten SQL code below, especially for handling of ROLLBACK */
BEGIN TRANSACTION
SAVE TRANSACTION savept_merge_rewritten_1
DECLARE @MERGE_REWRITTEN_ROWCOUNT_1 INT = 0 /* use instead of original @@ROWCOUNT */
DECLARE @MERGE_REWRITTEN_ERROR_1 INT /* temporary variable */
DECLARE @MERGE_REWRITTEN_RCTMP_1 INT /* temporary variable */

/* WHEN MATCHED THEN UPDATE */
UPDATE T
SET PersonName=S.PersonName
FROM 
Person_Target T, 
Person_Source S
WHERE T.PersonID=S.PersonID
SELECT @MERGE_REWRITTEN_ERROR_1=@@ERROR, @MERGE_REWRITTEN_RCTMP_1=@@ROWCOUNT
IF @MERGE_REWRITTEN_ERROR_1 <> 0 GOTO lbl_rollback_merge_rewritten_1
SET @MERGE_REWRITTEN_ROWCOUNT_1 += @MERGE_REWRITTEN_RCTMP_1

/* WHEN NOT MATCHED BY SOURCE THEN DELETE */
DELETE T
FROM Person_Target T
WHERE NOT EXISTS (
SELECT * FROM Person_Source S
WHERE T.PersonID=S.PersonID
)
SELECT @MERGE_REWRITTEN_ERROR_1=@@ERROR, @MERGE_REWRITTEN_RCTMP_1=@@ROWCOUNT
IF @MERGE_REWRITTEN_ERROR_1 <> 0 GOTO lbl_rollback_merge_rewritten_1
SET @MERGE_REWRITTEN_ROWCOUNT_1 += @MERGE_REWRITTEN_RCTMP_1

/* WHEN NOT MATCHED BY TARGET THEN INSERT */
INSERT INTO Person_Target
(PersonID,PersonName)
SELECT S.PersonID,S.PersonName 
FROM Person_Source S
WHERE NOT EXISTS (
SELECT * FROM Person_Target T
WHERE T.PersonID=S.PersonID
)
SELECT @MERGE_REWRITTEN_ERROR_1=@@ERROR, @MERGE_REWRITTEN_RCTMP_1=@@ROWCOUNT
IF @MERGE_REWRITTEN_ERROR_1 <> 0 GOTO lbl_rollback_merge_rewritten_1
SET @MERGE_REWRITTEN_ROWCOUNT_1 += @MERGE_REWRITTEN_RCTMP_1

GOTO lbl_commit_merge_rewritten_1
/* in case of an error, roll back to savepoint at the start but do no abort the transaction: there may be an outermost transaction active*/
lbl_rollback_merge_rewritten_1: ROLLBACK TRANSACTION savept_merge_rewritten_1
lbl_commit_merge_rewritten_1:   COMMIT
;/* --- end rewritten MERGE statement #1 --- */

END
GO
SQL

違いの1つは、@@rowcount は SQL Server と異なるということです。これが、書き直されたコードに @MERGE_RWRITTEN_ROWCOUNT_n が含まれている理由です。

コードをプロシージャ用に変換した後で、SQL Server テーブルと Babelfish PostgreSQL の person_target テーブル内のデータが一致していることを確認できます。

考慮事項

MERGE ステートメントが文字列変数で動的に作成される場合、Babelfish Compass ツールを使用して書き換えることはありません。このようなシナリオでは、手動で変換する必要があります。-rewrite フラグは Babelfish がサポートしていないかぎり MERGE に影響します。いったん機能がサポートされると、-rewrite はそれ以上書き換えを試みません。

結論

この投稿では、SQL Server で使用される MERGE ステートメントの例を1つ取り上げて、Babelfish Compass ツールの -rewrite フラグを使用してそれらを同等の Babelfish T-SQL コードに変換する方法を説明しました。

翻訳はソリューションアーキテクトのYoshinori Sawada が担当しました。原文はこちらです。


著者について

Shyam Sunder Rakhecha は、インドのハイデラバードを拠点とする AWS のプロフェッショナルサービスチームのリードコンサルタントで、データベースの移行とモダナイゼーションを専門としています。AWS クラウドの移行と最適化においてお客様を支援しています。彼はデータベースという観点から新しいテクノロジーを探求することと、 RDBMS とビッグデータに興味を持っています。また、チームビルディングのイベントを開催したり、チームで集まったりするのも大好きです。