免费试用

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 outputOUT param_name type参数方向显式声明
变量声明declare @x intDECLARE 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 xOB 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;

SQL Server执行截图 OceanBase MySQL执行截图

三、迁移总结

通过 SQLShift 转换,我们成功将 SQL Server 的 sp_protected_au 存储过程迁移到 OceanBase MySQL 模式下,并在测试数据下实现与源端逻辑一致。 这一实践说明:

  • 常见的变量声明、函数调用、条件判断等语法均可自动完成转换;
  • 此复杂度级别的存储过程可“一键迁移、即刻运行”,逻辑语义保持原样。
  • 对需要从 SQL Server 平滑切换到 OceanBase 的团队而言,SQLShift 可显著降低迁移改写与验证成本。

📢

  • 想快速体验迁移效果?,在线免费体验已开放;
  • 有其他数据库迁移需求,填份问卷 ,我们将收集需求并统一排期支持。

现在开始免费试用SQLShift

打破异构数据库限制,智能实现存储过程等非表对象无缝适配,免去您高额改造成本!

免费试用