联系我们
18591797788
hubin@rlctech.com
北京市海淀区中关村南大街乙12号院天作国际B座1708室
18681942657
lvyuan@rlctech.com
上海市浦东新区商城路660号乐凯大厦26c-1
18049488781
xieyi@rlctech.com
广州市越秀区东风东路华宫大厦808号1608房
029-81109312
service@rlctech.com
西安市高新区天谷七路996号西安国家数字出版基地C座501
在数据库迁移领域,SQL Server 到 OceanBase 数据库的迁移需求日益增长,但目前尚无官方的迁移工具,不过可以通过MySQL中间库实现数据库的数据结构和对象迁移,具体的步骤如下:
步骤一:通过MySQL workbench实现SqlServer到Mysql的迁移。
步骤二:通过OMS和DBcat实现MySQL到Oceanbase的迁移。
步骤二的迁移方法和思路大家已较为熟悉,本文主要介绍步骤一的迁移工具和方法。
在迁移前,需要先理清两者的核心差异。以下从数据类型、函数、关键语法三大维度,整理出高频适配要点:
| 数据类型 | SQL Server | Oceanbase MySQL租户 |
|---|---|---|
| 整形 | INT, BIGINT | 不变 |
| 字符串 | NVARCHAR(n) , VARCHAR(n) | VARCHAR(n) |
| 时间日期型 | DATETIME, DATETIME2 | DATETIME / TIMESTAMP |
| GUID类型 | UNIQUEIDENTIFIER (GUID) | CHAR(36) |
| 大对象 | NTEXT, TEXT, IMAGE | LONGTEXT, LONGBLOB |
| SQL_VARIANT | 无直接对应,需拆解或序列化 | |
| 二进制 | BIT | TINYINT(1) |
这是差异最大的类别之一,需重点关注函数名和参数顺序。
| 功能场景 | SQL Server 函数 | OceanBase MySQL 模式替换函数 | 示例对比 |
|---|---|---|---|
| 字符串长度 | LEN(字符串) | LENGTH(字符串) | SQL Server: LEN('test') → 4 OceanBase: LENGTH('test') → 4 |
| 字符截取 | SUBSTRING(字符串, 起始位, 长度) | SUBSTRING(字符串, 起始位, 长度) 或 SUBSTR(...) | 两者语法一致,示例:SUBSTRING('abcde',2,3) → 'bcd' |
| 查找字符位置 | CHARINDEX(目标字符, 原字符串, 起始位) | INSTR(原字符串, 目标字符, 起始位) | SQL Server: CHARINDEX('c','abcde',1) → 3 OceanBase: INSTR('abcde','c',1) → 3 |
| 字符串拼接 | +' 或 CONCAT(字符串1, 字符串2,...) | CONCAT(字符串1, 字符串2,...) | SQL Server: 'a'+'b' 或 CONCAT('a','b') → 'ab' OceanBase: CONCAT('a','b') → 'ab'(不支持 + 拼接) |
| 大小写转换 | UPPER(字符串) / LOWER(字符串) | UPPER(字符串) / LOWER(字符串) | 语法完全一致,示例:UPPER('test') → 'TEST' |
主要差异体现在获取系统时间、日期格式化及日期计算的函数名上。
| 功能场景 | SQL Server 函数 | OceanBase MySQL 模式替换函数 | 示例对比 |
|---|---|---|---|
| 获取当前时间 | GETDATE() | NOW() 或 SYSDATE() | SQL Server: GETDATE() → 2025-10-27 15:30:00OceanBase: NOW() → 2025-10-27 15:30:00 |
| 日期格式化 | CONVERT(目标格式, 日期, 格式码) | DATE_FORMAT(日期, 格式符) | SQL Server: CONVERT(VARCHAR(20), GETDATE(), 23) → '2025-10-27' OceanBase: DATE_FORMAT(NOW(), '%Y-%m-%d') → '2025-10-27' |
| 提取年份 / 月份 | YEAR(日期) / MONTH(日期) | YEAR(日期) / MONTH(日期) | 语法完全一致,示例:YEAR(NOW()) → 2025 |
| 日期加减 | DATEADD(单位, 数值, 日期) | DATE_ADD(日期, INTERVAL 数值 单位) | SQL Server: DATEADD(DAY, 1, GETDATE()) → 次日 OceanBase: DATE_ADD(NOW(), INTERVAL 1 DAY) → 次日 |
多数基础聚合函数语法一致,差异集中在 “去重计数” 和 “中位数” 等特殊场景。
| 功能场景 | SQL Server 函数 | OceanBase MySQL 模式替换函数 | 说明 |
|---|---|---|---|
| 计数(去重) | COUNT(DISTINCT 字段) | COUNT(DISTINCT 字段) | 语法完全一致,支持多字段去重(如 COUNT(DISTINCT a,b)) |
| 求和 / 平均值 | SUM(字段) / AVG(字段) | SUM(字段) / AVG(字段) | 语法完全一致,处理逻辑无差异 |
| 中位数 | PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY 字段) | PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY 字段) | OceanBase版本已支持该标准语法,低版本需用 SUBSTRING_INDEX() 自定义实现 |
主要涉及数据库元数据获取、空值处理等,函数名差异较大。
| 功能场景 | SQL Server 函数 | OceanBase MySQL 模式替换函数 | 示例 |
|---|---|---|---|
| 空值处理 | ISNULL(字段, 替换值) | IFNULL(字段, 替换值) | SQL Server: ISNULL(NULL, '0') → '0' OceanBase: IFNULL(NULL, '0') → '0' |
| 获取数据库名 | DB_NAME() | DATABASE() | SQL Server: DB_NAME() → 当前库名 OceanBase: DATABASE() → 当前库名 |
自增主键问题:SQL Server 使用IDENTITY列来实现自增主键,而 MySQL 使用AUTO_INCREMENT
分页查询: SQL Server 使用OFFSET FETCH或 ROW_NUMBER(),OceanBase 使用 MySQL 的LIMIT n, m
在迁移过程中,SQL Server 存储过程中的以下语法与 OceanBase MySQL 不兼容,需要手工进行转换:
| 类型 | 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 … |
MySQL Workbench 是专为 MySQL 设计的可视化工具,分开源与商业版,支持 Windows 和 Linux 系统,核心功能是数据库设计、管理及迁移。
设计与管理:可进行 ER / 数据库建模,创建数据库图示、建立文档。
数据库迁移:提供完整解决方案,将Microsoft SQL Server,Sybase ASE,PostreSQL和其他RDBMS表,对象和数据迁移到MySQL,也支持 MySQL 旧版本向新版本迁移。
Windows 11/Windows Server 2022系统,需要安装如下组件或者补丁。
Microsoft .NET Framework 4.5.2
Microsoft Visual C++ 2015-2022 Redistributable
MySql Workbench官方下载页,:https://dev.mysql.com/downloads/workbench/
首先到官网上下载安装包,选择对应系统版本。

运行安装包mysql-workbench-community-8.0.43-winx64.msi,点击“Next”。

点击“Next”

点击“Next”,

点击“Install”

点击“Finish”,完成安装。

在workbench的主界面,打开【Database】菜单。

选择【Migration Wizard】,选择【Open ODBC Administrator】,新建“用户DSN”,类似如下:
输入SQL Server的服务器名:

选择认证方式,二者均可。

测试数据源连接

选择Microsoft SQL Server数据源

点击下一步,数据MySQL连接信息。

选择迁移的数据库或者schema:

选择迁移的数据对象,表迁移默认勾选,选择勾选迁移View和Routine

选择Schema创建,需要选择Create a SQL script,后面需要手工编辑view和routine的创建脚本。

数据对象迁移结果:

数据迁移选项:

数据迁移完成:

I. Migration
本示例迁移了1张表t1,2行数据,一个索引t1_idx。
Workbench创建的script内容如下:视图和routine的创建语句默认已经被注销掉了,需要修改后,在MySQ端执行。
– MySQL Workbench Migration
– Migrated Schemata: testdb
– Source Schemata: testdb
– Created: Mon Oct 20 10:19:51 2025
– Workbench Version: 8.0.43
SET FOREIGN_KEY_CHECKS = 0;
– Schema testdb
DROP SCHEMA IF EXISTS testdb ;
CREATE SCHEMA IF NOT EXISTS testdb ;
– Table testdb.t1
CREATE TABLE IF NOT EXISTS testdb.t1 (
a CHAR(10) CHARACTER SET ‘utf8mb4’ NULL,
b SMALLINT NOT NULL,
c BIGINT NULL,
d VARBINARY(8) NULL,
INDEX t1_idx (c ASC) VISIBLE);
– View testdb.View_1
– USE testdb;
– CREATE OR REPLACE VIEW dbo.View_1
– AS
– SELECT b, a
– FROM dbo.t1
– ;
– View testdb.GetEmployeeById
– USE testdb;
– CREATE OR REPLACE PROCEDURE GetEmployeeById
– @EmployeeId INT – 输入参数:员工ID
– AS
– BEGIN
– SET NOCOUNT ON; – 不显示"受影响的行数"
– – 查询指定ID的员工信息
– SELECT a, b, c, d
– FROM t1
– WHERE a = @EmployeeId;
– END;;
– Routine testdb.GetEmployeeById
– DELIMITER $$
– DELIMITER $$
– USE testdb$$
– CREATE PROCEDURE GetEmployeeById
– @EmployeeId INT – 输入参数:员工ID
– AS
– BEGIN
– SET NOCOUNT ON; – 不显示"受影响的行数"
– – 查询指定ID的员工信息
– SELECT a, b, c, d
– FROM t1
– WHERE a = @EmployeeId;
– END;$$
– DELIMITER ;
– SET FOREIGN_KEY_CHECKS = 1;
将如上的存储过程修改如下:
MySQL 中参数需要使用IN/OUT/INOUT明确标识参数类型(此处为输入参数,用 IN)
参数名前不需要@符号,直接使用参数名
MySQL 没有SET NOCOUNT ON语法,默认不会显示类似 SQL Server 的 “受影响的行数”信息。
DELIMITER $$
USE testdb$$
CREATE PROCEDURE GetEmployeeById(
IN EmployeeId INT – 输入参数:员工ID,MySQL中使用IN标识输入参数
)
BEGIN
– MySQL中没有SET NOCOUNT ON,默认不显示受影响行数信息
– 查询指定ID的员工信息
SELECT a, b, c, d
FROM t1
WHERE a = EmployeeId; – 直接使用参数名,无需@符号
END$$
DELIMITER ;
至此SQL Server 迁移到 MySQL 已经完毕,下一步可以通过OMS和DBCat进行MySQL到Oceanbae的数据库迁移了。
如果你在使用 OceanBase 时也遇到过类似的难题,或是有独到的优化经验,欢迎在评论区留言分享,下次见!