SQL Server 存储过程迁移到 OceanBase 的实战案例
目录
一、迁移背景
随着 OceanBase 在金融核心交易、政务系统、大型互联网平台等关键领域的广泛应用,大量使用 SQL Server 的企业面临向国产化、高性能 OceanBase 迁移的迫切需求。在迁移过程中,存储过程的兼容性和业务逻辑完整性成为关键瓶颈。
本次实战案例中,企业的某业务系统大量依赖 SQL Server 存储过程完成批量数据初始化和统计分析,迁移至 OceanBase MySQL 时需要解决事务控制、变量声明、日期函数、字符串拼接和异常处理等不兼容问题。为了确保迁移高效、准确,同时减少手工改写成本,我们使用 SQLShift 工具进行自动化转换。
二、SQLShift的转换能力
SQLShift 是一个面向异构数据库迁移的智能工具,自动识别 SQL Server 的 T-SQL 语法特性,并映射为OB等效语法,以下为待迁移的 SQL Server 存储过程:
点击查看原始 SQL Server 存储过程代码
CREATE PROCEDURE [dbo].[RT_Tang_YW_MainC_InitAwb60Finish]
AS
-- 声明变量
DECLARE @Period60 int
DECLARE @Period180 int
DECLARE @Yw_Op_Date datetime
DECLARE @Yw_Start_Time datetime
DECLARE @tran_error int
declare @AwbYwDate60 datetime
declare @AwbYwDate180 datetime
--变量赋值
SET @Period60 =-60
SET @Period180 =-180
SET @Yw_Start_Time = Getdate()
SET @tran_error = 0
SELECT @Yw_Op_Date = Max(Yw_Op_Date) FROM Tbl_Yw_Log WHERE OPTRESULT='RUN'
IF @Yw_Op_Date IS Null
BEGIN
SELECT @Yw_Op_Date=Getdate()
END
Set @AwbYwDate60 =DateAdd(day,@Period60,@Yw_Op_Date)
Set @AwbYwDate180 =DateAdd(day,@Period180,@Yw_Op_Date)
--定义隔离级别为最低
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
--Tbl_Awb_Basic_Temp
BEGIN TRAN
SET @tran_error = 0
BEGIN TRY
delete from Cargo2YWTemp..Tbl_Awb_Basic_Temp
where AwbPrefix+RTrim(AwbNo)+AwbPostfix
in(Select AwbPrefix+RTrim(AwbNo)+AwbPostfix as TmpFinishFlag
FROM Tbl_Cargo
WHERE AwbPrefix+RTrim(AwbNo)+AwbPostfix
In (Select AwbPrefix+RTrim(AwbNo)+AwbPostfix From Tbl_Awb_Basic Where (Op_Date < CONVERT(CHAR(10),@AwbYwDate60,121) And Op_Date > CONVERT(CHAR(10),@AwbYwDate180,121)) )
And FinishFlag !=0 --Finished
And Flight_Dep=Flight_Dest
GROUP BY AwbPrefix,AwbNo,AwbPostfix
)
Insert Into Cargo2YWTemp..Tbl_Awb_Basic_Temp(AwbPrefix,AwbNo,AwbPostfix,YwTreate)
Select distinct AwbPrefix,AwbNo,AwbPostfix,1
From
(
Select AwbPrefix,AwbNo,AwbPostfix,Min(FinishFlag) as TmpFinishFlag
FROM Tbl_Cargo
WHERE AwbPrefix+RTrim(AwbNo)+AwbPostfix
In (Select AwbPrefix+RTrim(AwbNo)+AwbPostfix From Tbl_Awb_Basic Where (Op_Date < CONVERT(CHAR(10),@AwbYwDate60,121) And Op_Date > CONVERT(CHAR(10),@AwbYwDate180,121)) )
And FinishFlag !=0 --Finished
And Flight_Dep=Flight_Dest
GROUP BY AwbPrefix,AwbNo,AwbPostfix
) Tbl_Temp
Where TmpFinishFlag>0
SET @tran_error = @tran_error + @@error
END TRY
BEGIN CATCH
--执行出错,回滚事务
ROLLBACK TRAN
SET @tran_error = @tran_error + 1;
-- 记录异常
INSERT INTO TBL_SP_ErrLog(ErrTable,ErrDate) VALUES('Tbl_Awb_Basic_Temp',getdate())
RAISERROR ( N'Tbl_Awb_Basic_Temp 出现异常', 17,1 );
END CATCH
IF(@tran_error = 0)
--没有异常,提交事务
COMMIT TRAN
BEGIN TRAN
SET @tran_error = 0
BEGIN TRY
UPDATE Cargo2YWTemp..Tbl_Awb_Basic_Temp
SET AwbDate=a.Op_Date,AwbDest=substring(a.routing,len(a.routing)-2,3),Piece=a.Piece
FROM Cargo2YWTemp..Tbl_Awb_Basic_Temp t ,Tbl_Awb_Basic a
WHERE a.AwbNo=t.AwbNo
AND a.AwbPrefix=t.AwbPrefix
AND a.AwbPostfix=t.AwbPostfix
SET @tran_error = @tran_error + @@error
END TRY
BEGIN CATCH
--执行出错,回滚事务
ROLLBACK TRAN
SET @tran_error = @tran_error + 1;
-- 记录异常
INSERT INTO TBL_SP_ErrLog(ErrTable,ErrDate) VALUES('Tbl_Awb_Basic_Temp',getdate())
RAISERROR ( N'Tbl_Awb_Basic_Temp 出现异常', 17,1 );
END CATCH
IF(@tran_error = 0)
--没有异常,提交事务
COMMIT TRAN
--Tbl_Awb_Basic_Temp
BEGIN TRAN
SET @tran_error = 0
BEGIN TRY
--
UPDATE Cargo2YWTemp..Tbl_Awb_Basic_Temp
SET YwTreate=0
FROM Cargo2YWTemp..Tbl_Awb_Basic_Temp bt ,(SELECT SUM(Piece) AS Piece,AwbPrefix,AwbNo,AwbPostfix
FROM (SELECT c.Piece,c.AwbPrefix,c.AwbNo,c.AwbPostfix
FROM Cargo2YWTemp..Tbl_Awb_Basic_Temp t
JOIN Tbl_Cargo c
ON c.Flight_Dep=t.AwbDest And c.Flight_Dest=t.AwbDest AND c.AwbNo=t.AwbNo AND c.AwbPrefix=t.AwbPrefix AND c.AwbPostfix=t.AwbPostfix
) b
GROUP BY AwbPrefix,AwbNo,AwbPostfix) a
WHERE a.AwbNo=bt.AwbNo AND a.AwbPrefix=bt.AwbPrefix AND a.AwbPostfix=bt.AwbPostfix AND bt.Piece=a.Piece
SET @tran_error = @tran_error + @@error
END TRY
BEGIN CATCH
--执行出错,回滚事务
ROLLBACK TRAN
SET @tran_error = @tran_error + 1;
-- 记录异常
INSERT INTO TBL_SP_ErrLog(ErrTable,ErrDate) VALUES('Tbl_Awb_Basic_Temp',getdate())
RAISERROR ( N'Tbl_Awb_Basic_Temp 出现异常', 17,1 );
END CATCH
IF(@tran_error = 0)
--没有异常,提交事务
COMMIT TRAN
--Tbl_Cargo_ChargeCorrection_Temp
BEGIN TRAN
SET @tran_error = 0
BEGIN TRY
delete from Cargo2YWTemp..Tbl_Cargo_ChargeCorrection_Temp where CCANo in(Select distinct AwbNo From Tbl_Awb_Basic_Temp)
INSERT INTO Cargo2YWTemp..Tbl_Cargo_ChargeCorrection_Temp (CCAPrefix,CCANo,CCAPostfix)
SELECT DISTINCT CCAPrefix,CCANo,CCAPostfix
FROM Tbl_Cargo_ChargeCorrectionDetail a
JOIN Cargo2YWTemp..Tbl_Awb_Basic_Temp t
ON a.AwbPrefix = t.AwbPrefix AND a.AwbNo = t.AwbNo AND a.AwbPostfix = t.AwbPostfix
SET @tran_error = @tran_error + @@error
END TRY
BEGIN CATCH
--执行出错,回滚事务
ROLLBACK TRAN
SET @tran_error = @tran_error + 1;
-- 记录异常
INSERT INTO TBL_SP_ErrLog(ErrTable,ErrDate) VALUES('Tbl_Cargo_ChargeCorrection_Temp',getdate())
RAISERROR ( N'Tbl_Cargo_ChargeCorrection_Temp 出现异常', 17,1 );
END CATCH
IF(@tran_error = 0)
--没有异常,提交事务
COMMIT TRAN
SQLShift自动识别并转换这些不兼容的语法点
在迁移过程中,SQL Server 存储过程中的以下语法与 OceanBase MySQL 不兼容,SQLShift将智能识别并转换:
类型 | SQL Server 写法 | OceanBase MySQL 替代方案 |
---|---|---|
存储过程声明 | CREATE PROCEDURE [dbo].[ProcName] | CREATE PROCEDURE ProcName() |
变量声明 | DECLARE @var INT | DECLARE var INT; (去掉 @ ) |
变量与列名冲突 | @Yw_Op_Date | 改名为 Yw_Op_Date_local |
日期函数 | GETDATE() | NOW() |
日期计算 | DATEADD(day, x, y) | DATE_ADD(y, INTERVAL x DAY) |
日期格式转换 | CONVERT(CHAR(10), date, 121) | DATE_FORMAT(date, '%Y-%m-%d') |
字符串拼接 | AwbPrefix+RTRIM(AwbNo)+AwbPostfix | CONCAT(AwbPrefix, RTRIM(AwbNo), AwbPostfix) |
字符串截取 | SUBSTRING(str, start, LEN(str)-2) | SUBSTRING(str, start, LENGTH(str)-2) |
双层表名 | Cargo2YWTemp..Tbl_X | Cargo2YWTemp.Tbl_X |
事务控制 | BEGIN TRAN / COMMIT / ROLLBACK | START TRANSACTION / COMMIT / ROLLBACK |
异常处理 | TRY...CATCH | DECLARE EXIT HANDLER FOR SQLEXCEPTION + 内部执行 ROLLBACK 、插入日志和 SIGNAL |
UPDATE 语法 | UPDATE t SET ... FROM t JOIN a ... | UPDATE t JOIN a ON ... SET ... |
三、SQLShift转换后在目标端成功执行
在 OceanBase MySQL 上执行转换后的存储过程,验证结果如下:
- 事务均能正常提交或回滚;
- DELETE、INSERT、UPDATE 操作正确执行,运单初始化逻辑保持一致;
- 日期计算、字符串拼接结果与 SQL Server 保持一致;
- 异常日志成功写入 TBL_SP_ErrLog 表;
- 整个过程无需修改业务逻辑,迁移一次成功。
四、总结:从繁琐手工迁移到智能转换
无论您是航空物流企业对核心运单处理系统进行数据库升级,还是大型企业将 SQL Server 存储过程迁移至 OceanBase 以统一数据库平台,SQLShift 都是快速、平稳落地 OceanBase 的关键加速器。它能够自动处理变量、日期、字符串、事务与异常等不兼容语法,显著节省手工改写、调试与验证成本,确保业务逻辑一致性,实现迁移效率与可靠性的双重提升。