SQL Server 存储过程迁移到 OceanBase 的实战案例
目录
一、迁移背景
随着 OceanBase 在金融核心交易、政务系统、大型互联网平台等关键领域的广泛应用,大量使用 SQL Server 的企业面临向国产化、高性能 OceanBase 迁移的迫切需求。在迁移过程中,存储过程的兼容性和业务逻辑完整性成为关键瓶颈。
本文将以一个真实业务的 SQL Server 存储过程为例,展示如何借助 SQLShift 自动化工具将其转换为可在 OceanBase MySQL 模式 中成功执行的版本,并详细分析转换中的语法差异与修正思路。
二、SQLShift智能转换能力
以南航信息中心某业务的存储过程为实践示例:sp_protected_au 是一个在航班起飞前检查“Y 舱保护位”是否被误标的存储过程,该存储过程最初运行在 SQL Server 环境中。迁移目标为 OceanBase 4.2.5(MySQL 模式)。
1. SQL Server存储过程
点击查看原始 SQL Server 存储过程代码
CREATE procedure [dbo].[sp_protected_au]
@implemente datetime,
@flight_date datetime,
@carr char(4),
@flight_no char(5),
@enter_time datetime,
@agent char(8),
@success int output
As
declare @inventoryid nchar(3),
@imp datetime,
@au int,
@classStr varchar(30)
select @inventoryid='001'
select distinct top 1 @inventoryid=inventoryid,@imp=max(implementdate) from schedule
where rtrim(ltrim(carrier))= rtrim(ltrim(@carr)) and rtrim(ltrim(flight_no))=rtrim(ltrim(@flight_no)) and effdate<=@flight_date and discontinuedate>=@flight_date
group by inventoryid
order by max(implementdate) desc
select @classStr=compartment3 from class where inventory_id=@inventoryid
select @au=0
select @au=count(*) from upload with (nolock)
where implemente_date=@implemente and flight_date=@flight_date
and carr=@carr and flight_no=@flight_no and agent=@agent and enter_time=@enter_time
and charindex(class,@classStr)>0 and class<>'O' and leg_seg_ind='S'
group by origin_station,destination_station,leg_seg_ind
having sum(protected_au)=0
if (@au>0)
begin
set nocount on
update upload set success_flag='Fail',error_log='Y compartment sum(au)=0'
where implemente_date=@implemente and flight_date=@flight_date
and carr=@carr and flight_no=@flight_no and agent=@agent and enter_time=@enter_time
set @success=1
set nocount off
end
else
begin
set @success=0
end
2. 使用 SQLShift 自动转换
通过 SQLShift,我们将 SQL Server 存储过程转换为 OceanBase MySQL 模式 的兼容语法。
点击查看转换为OB MySQL模式的存储过程
DELIMITER $$
CREATE PROCEDURE sp_protected_au (
IN param_implemente DATETIME,
IN param_flight_date DATETIME,
IN param_carr CHAR(4),
IN param_flight_no CHAR(5),
IN param_enter_time DATETIME,
IN param_agent CHAR(8),
OUT param_success INT
)
BEGIN
DECLARE param_inventoryid CHAR(3);
DECLARE imp DATETIME;
DECLARE au INT;
DECLARE classStr VARCHAR(30);
SET param_inventoryid = '001';
SELECT inventoryid, MAX(implementdate)
INTO param_inventoryid, imp
FROM schedule
WHERE TRIM(carrier) = TRIM(param_carr)
AND TRIM(flight_no) = TRIM(param_flight_no)
AND effdate <= param_flight_date
AND discontinuedate >= param_flight_date
GROUP BY inventoryid
ORDER BY MAX(implementdate) DESC
LIMIT 1;
SELECT compartment3
INTO classStr
FROM class
WHERE inventory_id = param_inventoryid
LIMIT 1;
SET au = 0;
SELECT COUNT(*)
INTO au
FROM upload
WHERE implemente_date = param_implemente
AND flight_date = param_flight_date
AND carr = param_carr
AND flight_no = param_flight_no
AND agent = param_agent
AND enter_time = param_enter_time
AND INSTR(classStr, class) > 0
AND class <> 'O'
AND leg_seg_ind = 'S'
GROUP BY origin_station, destination_station, leg_seg_ind
HAVING SUM(protected_au) = 0;
IF au > 0 THEN
UPDATE upload
SET success_flag = 'Fail',
error_log = 'Y compartment sum(au)=0'
WHERE implemente_date = param_implemente
AND flight_date = param_flight_date
AND carr = param_carr
AND flight_no = param_flight_no
AND agent = param_agent
AND enter_time = param_enter_time;
SET param_success = 1;
ELSE
SET param_success = 0;
END IF;
END$$
DELIMITER ;
3. 语法转换分析
在迁移过程中,SQL Server 存储过程中的以下语法与 OceanBase MySQL 不兼容,SQLShift将智能识别并转换: 点击查看SQLShift转换效果
| 类型 | SQL Server 写法 | OceanBase MySQL 替代方案 | 备注 |
|---|---|---|---|
| 参数声明 | @param type output | OUT param_name type | 参数方向显式声明 |
| 变量声明 | declare @x int | DECLARE x INT; | 每行单独声明 |
| 字符串函数 | rtrim(ltrim(x)) | TRIM(x) | 保留逻辑一致性 |
| 查找子串 | charindex(a,b) | INSTR(a,b) | 语义等价 |
| 分页取1行 | TOP 1 ... ORDER BY ... | ORDER BY ... LIMIT 1 | 语义转换 |
| 输出变量赋值 | SELECT @x = ... | SELECT ... INTO x | OB MySQL 语法 |
4. 验证迁移结果
在 OceanBase MySQL 4.2.5 的环境中可以成功创建转换后的存储过程。

并使用以下测试数据分别在SQL Server与OB Mysql中执行,结果一致:
点击查看测试数据(OceanBase MySQL适用)
-- 插入测试数据
INSERT INTO schedule VALUES ('MU', '5123', '2025-10-01', '2025-12-31', '001', '2025-09-20 10:00:00');
INSERT INTO class VALUES ('001', 'YBMOC');
INSERT INTO upload VALUES
('2025-09-20 10:00:00','2025-10-15 08:00:00','MU','5123','AGT001','2025-10-20 09:00:00','Y','S','PVG','PEK',0,NULL,NULL);
-- 调用存储过程
SET @res = 0;
CALL sp_protected_au('2025-09-20 10:00:00','2025-10-15 08:00:00','MU','5123','2025-10-20 09:00:00','AGT001',@res);
SELECT @res AS success_flag;
-- 验证结果
SELECT * FROM upload;

三、迁移总结
通过 SQLShift 转换,我们成功将 SQL Server 的 sp_protected_au 存储过程迁移到 OceanBase MySQL 模式下,并在测试数据下实现与源端逻辑一致。 这一实践说明:
- 常见的变量声明、函数调用、条件判断等语法均可自动完成转换;
- 此复杂度级别的存储过程可“一键迁移、即刻运行”,逻辑语义保持原样。
- 对需要从 SQL Server 平滑切换到 OceanBase 的团队而言,SQLShift 可显著降低迁移改写与验证成本。
📢