要将 SQL Server 数据库迁移到
适用于 Aurora PostgreSQL 的 Babelfish
,你通常需要执行自动和手动任务。自动任务包括使用带有 -rewrit
e 标志的
Babelfish Compass 工具
进行自动代码转换,以及使用
亚马逊云科技 数据库迁移服务 (亚马逊云科技 DMS) 进行数据迁移
。手动任务包括使用 Babelfish Compass 工具检查数据库兼容性、Babelfish 不支持的某些数据库对象的迁移变通办法以及手动验证结果。
在这篇文章中,我们将重点介绍 Babelfish Compass 工具的 -rewrit
e 标志功能,该功能会自动将 SQL Server 的 MERGE 语句转换为兼容 BabelFish 的 T-SQL 代码。MERGE 语句是这篇文章中显示的一个示例,但是 -rewrit
e 也可以用于其他功能。我们还将讨论手动验证结果的最佳实践。
使用 Babelfish Compass,你可以检查你的源 SQL Server 数据库是否与你的目标 Babelfish 数据库兼容,以及 Babelfish 目前不支持哪些功能且无法迁移。
PostgreSQL 15 支持合并,但是 Babelfish 尚不支持合并。
此外,PostgreSQL MERGE 并不完全等同于 SQL Server 的 MERGE,例如,不支持 RETURNING 和 NOT MATCHED BY SOUR CE
Babelfish Compass-重写旗帜概述
使用 -rewrit
e 标志,您可以转换 Babelfish Compass 评估报告中不支持的部分中包含的 MERGE 语句。
在命令提示符下运行 Babelfish 指南针工具:
在 Mac 和 Linux 上运行指南针的说明。
BabelfishCompass.bat MyFirstReport C:\work\merge_example.sql -rewrite -reportoption xref
事实证明,当 Babelfish Compass 评估报告建议手动重写 SQL 代码以使其与 Babelfish 目标兼容时, -
rewrite 标志很有用。
你可以省去将 SQL 转换为兼容 BabelFish 的 T-SQL 代码的一些手动操作。但是,您还必须仔细检查相应的重写的 SQL 代码。
理解 SQL Server 合并语句
SQL Server 的 MERGE 将插入、更新和删除合并为一个语句和事务。MERGE 语句从源表中选择行,并在单个事务中对目标表执行多个 DML 操作。
为了演示 SQL Server MERGE 的场景,我们在 SQL Server 数据库和 Babelfish 中创建了以下测试表。
Person_Target 是目标
表, Person_Sourc
e 是源表,其行根据合并条件合并到 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 语句将示例数据插入到 Person_S ource 和 Person_Targ
et 表中:
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')
以下代码将 Person_S ource 表中的数据合并到 Person_
Targ et
表中,合并后的分号实际上是强制性的:
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;
对于 Per son_ Target
表中的每一行,SQL Server 都会评估被称为合并条件的 搜索条件。 如果条件匹配,则结果变为真,并且 SQL Server 使用来自 Pers on_Sou
rce 表的相应数据更新目标表中的行。如果任何行的条件都不匹配,则结果为 false,SQL Server 会将源表中的相应行插入到目标表中。如果源表中任何行的条件都不匹配,则该行将从目标中删除。下图说明了这个工作流程。
![](https://rebrand-images.s3.cn-north-1.amazonaws.com.cn/d2908q01vomqb2.cloudfront.net/887309d048beef83ad3eabf2a79a64a389ab1c9f/2023/05/28/DBBLOG-2704.png)
我们可以验证目标表并检查 Pers on_Target
表中的数据是否与前面的图表相匹配。
相当于 Babelfish 中的 SQL 服务器合并
因为 PostgreSQL 没有类似合并的直接结构。但是,指南针工具可以将 Babelfish 的 MERGE 重写为单独的 “插入”、“更新” 或 “删除” 语句
以下语句在 Babelfish 中创建 Person_Sour
ce 和 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');
以下代码是在报告文件夹内名为 rewriten 的 文件夹中自动生成的。
/* 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
区别之一是 @ @rowcount
与 SQL Server 相比有所不同。这就是为什么我们在重写的代码 中有 @MERGE_RWRITTEN_ROWCOUNT_n
。
转换该过程的代码后,你可以验证 SQL Server 和 Babelfish PostgreSQL pers on_target
表中的数据是否匹配。
注意事项
当 MERGE 语句在字符串变量中动态构造时,不会使用 Babelfish Compass 工具对其进行重写。在这种情况下,您必须手动对其进行转换。只要 Babelfish 不支持 MERGE, -rewr
ite 标志才会影响 MERGE,一旦支持该功能, -rewrite 就 不会再尝试重写
它了。
结论
在这篇文章中,我们介绍了 SQL Server 中使用的 MERGE 语句的一个示例,并解释了如何使用 Babelfish Compass 工具中的 -rewrit
e 标志将其转换为等效的 Babelfish T-SQL 代码。
作者简介
Shyam Sunder Rakhecha 是位于印度海得拉巴的 亚马逊云科技 专业服务团队的首席顾问,专门研究数据库迁移和现代化。他正在帮助客户在 亚马逊云科技 云中进行迁移和优化。他很想探索数据库方面的新兴技术。他对 RDBMS 和大数据着迷。他还喜欢组织团队建设活动和团队奖励。