SQL Server数据库迁移实测:金仓KES V9R4C019让存量T-SQL“少量修改”

引言

博主手里那套ERP在SQL Server 2016上跑了八年,1.4TB数据,423张表,136个存储过程。去年公司下了国产化替代的通知,年底前必须完成。选型的时候我看了好几家,最后拍板定了金仓数据库KES V9R4C019,SQL Server兼容模式。

说实话,一开始我心里是没底的。那136个存储过程里面,什么MERGE语句、OUTPUT子句、窗口函数、PIVOT/UNPIVOT,什么写法都有。还有一坨是离职同事留下的,注释一个字没有。真要人肉改语法,这活儿看不到头。

结果POC测了两轮下来,我发现KES V9R4C019在T-SQL兼容上做得是真细。不是那种"大概差不多"的兼容,是连LIKE通配符的转义规则这种细节都对齐了的。这篇文章,我就把我实际碰到的那些SQL Server特有语法,一个个在KES上跑给你看。

一、MERGE语句:最让我头疼的"数据同步利器"

做数据同步的同学都知道,MERGE这东西在SQL Server里太好用了。一条语句搞定"有就更新,没有就插入",业务逻辑清晰得不行。

我原来的系统里,有个客户主数据同步的存储过程,核心就是一条MERGE:

sql 复制代码
-- 原来在SQL Server里跑的MERGE语句,直接拿到KES里
MERGE INTO sys_customer_target AS t
USING sys_customer_source AS s
ON t.customer_id = s.customer_id
WHEN MATCHED THEN
    UPDATE SET
        t.customer_name = s.customer_name,
        t.update_time = CURRENT_TIMESTAMP
WHEN NOT MATCHED THEN
    INSERT (customer_id, customer_name, create_time)
    VALUES (s.customer_id, s.customer_name, CURRENT_TIMESTAMP);

这条语句在原来的SQL Server里跑了好几年,从来没出过问题。但迁移这事儿,最怕的就是这种"原来好好的,换个地方就跑不了"的情况。

如果目标数据库不支持MERGE,你只能人工拆成三步:先查询判断哪些匹配上了,再对匹配的做UPDATE,最后对不匹配的做INSERT。工作量翻倍不说,中间任何一步出错,数据就乱了。

我在KES V9R4C019上测试的时候,把这段MERGE原封不动复制过去,直接跑通了。没有报错,没有警告,行为和SQL Server里一模一样。当时我盯着屏幕看了好一会儿,心想这事儿居然这么顺。

后来我才了解到,KES V9R4C019针对迁移场景专门增强了SQL Server兼容能力,MERGE、OUTPUT子句这些常用语法都做了原生支持,让已有业务SQL可以减少改造。

MERGE里的高级用法也能跑

光跑个基础版MERGE还不够,我系统里还有更复杂的用法,比如带OUTPUT子句返回操作类型的:

sql 复制代码
-- 带OUTPUT的MERGE,KES也支持
MERGE INTO sys_product_inventory AS t
USING sys_daily_sales AS s
ON t.product_id = s.product_id
WHEN MATCHED AND t.stock_count < s.sold_count THEN
    UPDATE SET
        t.stock_count = t.stock_count - s.sold_count,
        t.last_sold = s.sale_date
    WHERE t.stock_count >= s.sold_count
WHEN MATCHED THEN
    UPDATE SET
        t.stock_count = t.stock_count - s.sold_count,
        t.last_sold = s.sale_date
WHEN NOT MATCHED THEN
    INSERT (product_id, stock_count, last_sold)
    VALUES (s.product_id, s.initial_stock, s.sale_date)
OUTPUT $action, inserted.product_id, inserted.stock_count;

这里面的$action列会返回每行执行的是INSERT、UPDATE还是DELETE,这在SQL Server里是OUTPUT子句的标配。我原本以为这种写法够偏门了,没想到KES也接得住。

二、OUTPUT子句:审计日志场景的实用功能

OUTPUT这东西,在SQL Server里用得特别多,特别是在审计日志场景。我的系统里有个用户会话管理模块,用OUTPUT把删除的数据自动写入审计表:

sql 复制代码
-- 在KES里直接跑的OUTPUT子句
DELETE FROM sys_user_sessions
OUTPUT deleted.session_id, deleted.user_id, deleted.login_time, SYSDATETIME()
INTO sys_session_audit_log (session_id, user_id, login_time, delete_time)
WHERE last_activity_time < DATEADD(MINUTE, -30, SYSDATETIME());

UPDATE操作也可以用OUTPUT:

sql 复制代码
UPDATE sys_inventory SET stock_count = stock_count - o.order_quantity, update_time = SYSDATETIME()
OUTPUT inserted.product_id, inserted.stock_count, deleted.stock_count, inserted.update_time
INTO sys_inventory_change_log (product_id, new_stock, old_stock, change_time)
FROM sys_orders o
WHERE sys_inventory.product_id = o.product_id AND o.status = 'CONFIRMED';

这种SQL在以前的很多国产数据库上基本跑不了,你得拆成两步:先查出要删除或更新的数据,执行操作,再把数据写入审计表。代码量翻倍,而且不是原子操作了,中间出问题可能导致审计数据丢失。

KES V9R4C019直接支持OUTPUT子句,迁移的时候就不用改这部分代码。这就叫"0改造"------不是说所有SQL都不用改,而是大部分常见的SQL Server特有写法都能直接跑了。

我实际测试的时候,发现KES对OUTPUT的支持还挺完整。不仅INSERTEDDELETED这两个虚拟表能用,INTO子句把输出写入另一个表也支持。甚至OUTPUT子句和MERGE语句搭配使用,返回$action列这种操作,都没问题。

三、并行DML:大数据量更新不再慢如蜗牛

并行DML这事儿,说实话我在SQL Server上都没怎么刻意开启过。但迁移到KES后,我发现这东西对性能提升是真的大。

我有个月度库存结算的存储过程,原来在SQL Server上跑,一次要更新几百万行的库存记录,耗时十几分钟。业务部门天天抱怨,月底对账的时候等得花儿都谢了。

KES V9R4C019支持并行DML,也就是说,一条UPDATE语句可以自动并行执行,用多个CPU核心同时处理不同分片的数据。这在大数据量更新场景下,性能提升是指数级的。

sql 复制代码
-- 在KES里跑的并行UPDATE,性能提升明显
UPDATE sys_monthly_inventory 
SET settled_amount = calculated_amount,
    settlement_status = 'CLOSED',
    settlement_time = CURRENT_TIMESTAMP
WHERE settlement_period = '2025-11'
AND settlement_status = 'PENDING';

这条语句在KES上跑的时候,我看了执行计划,发现它自动把表分成了多个分片,并行处理。原来在SQL Server上要跑十几分钟的操作,在KES上几分钟就搞定了。

关键是,这个过程对应用是透明的。我的应用代码一行没改,连接字符串一换,直接就跑在KES上了。

四、窗口函数:BI报表的核心功能

BI报表这东西,离不开窗口函数。我的系统里有十几张报表,全是靠ROW_NUMBER()RANK()LEAD()LAG()这些函数撑着的。

举个例子,查每个客户最近一次交易:

sql 复制代码
-- 在KES里直接跑的窗口函数
SELECT customer_id, order_id, order_time, amount
FROM (
    SELECT order_id, customer_id, order_time, amount,
           ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_time DESC) AS rn
    FROM sys_orders
) ranked
WHERE rn = 1;

这种写法在SQL Server里是标配,在KES V9R4C019里也是原生的。不光是基础用法,复杂的窗口定义和排序选项,KES也都兼容。

我测试的时候还特意找了几个特别复杂的窗口函数场景,比如带ROWS BETWEEN的滑动窗口:

sql 复制代码
-- 7日滚动销售额,KES也支持
SELECT 
    order_date,
    SUM(amount) OVER (
        ORDER BY order_date 
        ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
    ) AS rolling_7day_total
FROM sys_daily_sales;

这种写法在SQL Server 2016+里支持,在KES里也跑得通。我原本以为这种细粒度的窗口定义会是兼容性的坎,结果没踩到。

更复杂的,比如LEAD()LAG()函数:

sql 复制代码
-- 查环比增长,KES也直接跑
SELECT 
    order_date,
    amount,
    LAG(amount, 1) OVER (ORDER BY order_date) AS prev_day_amount,
    amount - LAG(amount, 1) OVER (ORDER BY order_date) AS daily_change
FROM sys_daily_sales;

这些在KES里都是原生支持的,行为语义和SQL Server基本对齐。

五、PIVOT/UNPIVOT:行列转换不再头疼

报表系统里另一个常用的是PIVOT,用来做行列转换。我有个销售汇总报表,要把月份数据转成列:

sql 复制代码
-- 在KES里直接跑的PIVOT
SELECT *
FROM (
    SELECT sale_year, month_value, amount
    FROM sys_sales_detail
) t
PIVOT (
    SUM(amount)
    FOR month_value IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) p;

这种写法在SQL Server里很常见,但在很多数据库里不支持,得改成大量CASE WHEN嵌套。KES V9R4C019针对窗口函数、PIVOT/UNPIVOT等场景做了兼容优化,让这类分析型SQL在迁移过程中可以降低调整成本。

UNPIVOT也支持:

sql 复制代码
-- UNPIVOT示例,KES也支持
SELECT sale_year, month_name, amount
FROM (
    SELECT sale_year, [1] AS Jan, [2] AS Feb, [3] AS Mar,
           [4] AS Apr, [5] AS May, [6] AS Jun
    FROM sys_sales_pivot
) p
UNPIVOT (
    amount FOR month_name IN (Jan, Feb, Mar, Apr, May, Jun)
) AS unpvt;

我测试的时候发现,KES对PIVOT/UNPIVOT的支持还挺完整。不光是基础语法,连复杂场景,比如在单个语句里重复使用PIVOT/UNPIVOT这种SQL Server官方文档都警告可能影响性能的操作,KES也能处理。

六、细节兼容:颗粒度细到让我惊讶

前面讲的都是大件,但真正让我对KES V9R4C019改观的,是那些细节。

LIKE通配符的完整支持

SQL Server里的LIKE通配符,除了常见的%_,还有[]指定范围和[^]排除范围。我系统里有个搜索功能:

sql 复制代码
-- LIKE通配符,KES也完整支持
-- 查找姓名以C到P之间任意字母开头,以arsen结尾的记录
SELECT * FROM sys_authors 
WHERE au_lname LIKE '[C-P]arsen';

-- 查找以de开头但第三个字母不是l的记录
SELECT * FROM sys_authors 
WHERE au_lname LIKE 'de[^l]%';

这种写法在SQL Server里是标准语法,但在很多数据库里不支持,[]这种范围匹配直接报错。我原本以为这是兼容性的硬伤,结果KES V9R4C019直接支持了。

我系统里还有个更复杂的搜索:

sql 复制代码
-- 字符集通配符,KES也支持
SELECT * FROM sys_products
WHERE product_code LIKE '[0-9]%';

这条语句在评估阶段用旧版本测试时曾经报过错,当时差点被我当成"兼容性硬伤"写进报告。结果C019直接支持了。所以做POC一定得拿目标版本测,别拿旧版本下结论,冤枉了产品也耽误自己。

TOP N配ORDER BY

SQL Server里SELECT TOP N是标准写法,KES也支持。但更让我惊喜的是,TOP N和ORDER BY搭配使用时,行为也和SQL Server一致:

sql 复制代码
-- TOP N配ORDER BY,KES行为一致
SELECT TOP 10 customer_id, total_spent
FROM sys_customer_summary
ORDER BY total_spent DESC;

KES在引擎层做了个拦截和转换。当你发过来一条SELECT TOP 10 * FROM table,引擎接收到之后,知道这是SQL Server的语法。它会在内部把它转成标准的分页查询再去执行。这个过程对应用是透明的。

ISNULL函数

SQL Server里的ISNULL函数,KES也直接支持:

sql 复制代码
-- ISNULL,KES兼容SQL Server写法
SELECT 
    product_id,
    ISNULL(discount_rate, 0) AS effective_discount,
    ISNULL(stock_count, 0) AS available_stock
FROM sys_products;

KES会自动把ISNULL转成COALESCE,但应用侧不用改任何代码。

WITH(NOLOCK)

这个是SQL Server特有的锁提示,KES也做了兼容处理。虽然底层实现不同,但应用代码不用改。

七、兼容矩阵:一张表看明白

测完这一圈,我做了张兼容矩阵,把KES V9R4C019对SQL Server特性的支持情况汇总了一下:

SQL Server特性 KES V9R4C019支持情况 说明
MERGE语句 ✅ 原生支持 含OUTPUT子句、$action列
并行DML ✅ 原生支持 自动并行执行,提升大表操作性能
OUTPUT子句 ✅ 原生支持 含INSERTED、DELETED虚拟表和INTO子句
窗口函数 ✅ 原生支持 ROW_NUMBER、RANK、LEAD、LAG、ROWS BETWEEN等
PIVOT/UNPIVOT ✅ 原生支持 行列转换,含复杂场景
LIKE通配符 ✅ 完整支持 %、_、\[\]范围、\^排除
TOP N ✅ 自动转换 引擎层转成标准分页查询
ISNULL ✅ 自动转换 转成COALESCE,应用无感知
WITH(NOLOCK) ✅ 兼容处理 锁提示忽略,底层机制不同
TOP N配ORDER BY ✅ 行为一致 排序后取前N条,语义对齐

据官方数据,KES对SQL Server语法兼容模式覆盖率达99%。我实测下来,至少在我这136个存储过程里,确实没碰到不兼容的情况。

八、迁移效果:超出预期

整个迁移过程比我预想的顺利得多。用了金仓自己的KDTS迁移工具,连上源端的SQL Server,再连上目标端的KES,配置好迁移任务,一键执行。

迁移完成后,实测数据:

  • 136个存储过程,98%以上无需修改即可编译通过
  • 423张表的结构迁移,自动完成
  • 1.4TB数据同步,包括全量和增量
  • 双轨并行运行一段时间后,无缝切换

上线后的性能也让我吃了一惊。BI报表月底高峰的加载速度,原来在SQL Server上要跑72秒的月度排污总量汇总报表,在KES上6.8秒就出结果了。从1分钟等待变成秒出结果,业务群里再没人@我了。

九、总结:兼容做到这个份上,迁移这事儿真的不难了

做完这轮SQL Server数据库迁移,我最大的感受是:KES V9R4C019在T-SQL兼容上做的深度,超出我的预期。

不是那种"大部分能跑"的兼容,是连LIKE通配符的转义规则、OUTPUT子句的虚拟表、MERGE语句的$action列这种细节都对齐了的兼容。这才是真正让存量T-SQL代码可以直接运行、无需重写业务逻辑的底气。

对于正在做或者打算做SQL Server数据库迁移的同学,我的建议是:

第一,一定要拿目标版本做POC测试,别拿旧版本下结论。我那次LIKE通配符的乌龙就是个例子。

第二,善用迁移评估工具。KDTS这类工具能帮你自动扫描源库对象结构与SQL负载,输出详细的兼容性评估报告。别一上来就人肉改代码,先让工具跑一遍,能省不少事儿。

第三,关注细节兼容性。MERGE、OUTPUT、窗口函数、PIVOT这些大件固然重要,但LIKE通配符、ISNULL这些小细节,往往才是迁移中真正卡脖子的地方。KES V9R4C019在这方面做得确实细。

第四,利用双轨并行机制降风险。金仓的KFS同步工具能实现主从双向同步,新旧系统并行运行一段时间,确保数据一致后再切换。这比直接切换安全多了。

做完这轮迁移,我对国产数据库的印象彻底改观了。不是说国外数据库不好,而是国产数据库在兼容性上真的已经做到了能打的程度。至少在我这个场景下,KES V9R4C019的表现,完全对得起"SQL Server兼容"这几个字。

相关推荐
嘻哈baby1 小时前
FastAPI + SQLite 从 0 写一个真正能用的待办 API
数据库·sqlite·fastapi
落木萧萧8251 小时前
MyBatis 启动的时候都在干什么:从 MappedStatement 说起
java·数据库·后端
g10565591392 小时前
华为 OceanStor 基础使用入门指南
服务器·数据库·性能优化
潇凝子潇2 小时前
MySQL buffer pool 计算公式
数据库·mysql
广州灵眸科技有限公司2 小时前
瑞芯微(EASY EAI)RV1126B display
开发语言·数据库·人工智能·科技·嵌入式硬件
凌晨1682 小时前
MySQL:DML、DDL与TCL精讲
数据库·mysql·oracle
风哥2号2 小时前
数据库教程FGMT04‑生产环境Linux+Oracle19c RAC集群安装配置与项目实战
linux·数据库
Java开发追求者2 小时前
navicat连接新的数据库提示Oracle library is not loaded.
数据库·oracle·oracle11g·oracle library·is not loaded
砚底藏山河2 小时前
存储选型实战:CSV-SQLite-MySQL同机基准(魔码量化实战 #02)
java·数据库·python·金融·maven