SQL Server数据库迁移:V9R4C019 如何接住存量 T-SQL 批处理

做 SQL Server 数据库迁移时,让开发团队紧张的往往不是几百张表,而是仓库里那些跑了很多年的 T-SQL。库存日结用 MERGE 合并数据,账户变更用 OUTPUT 写审计记录,经营报表里还有窗口函数和 PIVOT。如果这几类代码都要重写,后面跟着变的就不只是 SQL,还有异常处理、受影响行数、审计日志和报表字段。

我把这类迁移看成一次"语义对位":不急着按文件数量估工期,先找出最常用、最容易牵动业务的语法块,看目标版本能不能保留原来的表达。V9R4C019 针对 MERGE、DML OUTPUT、窗口函数、PIVOT/UNPIVOTLIKE 通配符等高频 T-SQL 场景继续补强兼容能力,存量代码因此有了尽量保留原有业务语义的条件。

先选对目标版本和兼容模式

SQL Server 代码的语法习惯很明显:TOP、表变量、@name 局部变量、GO 批处理结束符、PRINTMERGE 和过程中的 BEGIN...END 通常会成组出现。数据迁过去以后再逐条处理,很快就会变成一份没有边界的改造清单。

目标库使用 KingbaseES V9R4C019 SQL Server 兼容版,对象评估、脚本转换和应用回归也要在同一版本上完成。金仓官方的 SQL Server 至 KingbaseES 迁移指南把数据类型、SQL 语法、PL/MSSQL、客户端接口和迁移工具放在一条路径里。这个顺序很实用:先确认代码能否保留,再处理少量确实与应用逻辑相关的差异。

MERGE 保住了日结任务的原有结构

一个典型的库存日结任务,会先把当天变动写入中间表,再按商品和仓库合并到库存主表。原有 T-SQL 可以保持一条 MERGE 的结构:匹配到旧记录就更新数量,没有匹配到就新增。

sql 复制代码
MERGE INTO inventory_balance AS t
USING inventory_delta AS s
ON t.warehouse_id = s.warehouse_id
AND t.product_id   = s.product_id
WHEN MATCHED THEN
    UPDATE SET
        quantity      = t.quantity + s.change_quantity,
        last_batch_no = s.batch_no,
        updated_at    = CURRENT_TIMESTAMP
WHEN NOT MATCHED THEN
    INSERT (
        warehouse_id,
        product_id,
        quantity,
        last_batch_no,
        updated_at
    )
    VALUES (
        s.warehouse_id,
        s.product_id,
        s.change_quantity,
        s.batch_no,
        CURRENT_TIMESTAMP
    );

如果把这段代码拆成"先查询、再判断、最后 UPDATEINSERT",事务中会多出一段不必要的分支。保留 MERGE 后,原来的匹配条件、更新表达式和新增字段仍放在一个语句中,回归测试也能继续围绕批次号、库存量和受影响行数展开。

验收时可以先核对这一批增量是否全部落到主表:

sql 复制代码
SELECT d.batch_no,
       COUNT(*) AS delta_rows,
       SUM(d.change_quantity) AS quantity_delta,
       SUM(b.quantity) AS current_quantity
FROM inventory_delta AS d
JOIN inventory_balance AS b
  ON b.warehouse_id = d.warehouse_id
 AND b.product_id   = d.product_id
WHERE d.batch_no = 'DAY-20260901'
GROUP BY d.batch_no;

DML OUTPUT 让审计链不用换写法

金融、会员和供应链系统里,更新数据的同时记录更改前后值是很常见的写法。SQL Server 的 DML OUTPUT 可以从 deletedinserted 中直接取值,再写入审计表。V9R4C019 对这类语法的支持,避免了把原子的一次更新改成应用层的"先读后写"。

sql 复制代码
DECLARE @customer_id bigint = 10012001;
DECLARE @new_limit   numeric(18,2) = 50000.00;

UPDATE customer_account
SET credit_limit = @new_limit,
    updated_at   = CURRENT_TIMESTAMP
OUTPUT inserted.customer_id,
       deleted.credit_limit,
       inserted.credit_limit,
       inserted.updated_at
INTO customer_limit_log (
       customer_id,
       old_credit_limit,
       new_credit_limit,
       changed_at
)
WHERE customer_id = @customer_id;

对这段代码做回归,查的不只是账户表中的新额度,还要确认审计表只产生一条对应记录,旧值和新值与业务变更一致:

sql 复制代码
SELECT a.customer_id,
       a.credit_limit,
       l.old_credit_limit,
       l.new_credit_limit,
       l.changed_at
FROM customer_account AS a
JOIN customer_limit_log AS l
  ON l.customer_id = a.customer_id
WHERE a.customer_id = 10012001
ORDER BY l.changed_at DESC;

窗口函数和 PIVOT 继续服务于原报表

报表 SQL 的改造风险往往比普通查询更高。一方面,报表字段已经被前端、导出模板和定时任务使用;另一方面,同一统计口径常常同时用到分组排名和行列转换。

例如,这段 SQL 用 ROW_NUMBER() 找每个仓库最后一次盘点结果:

sql 复制代码
WITH latest_stocktake AS (
    SELECT warehouse_id,
           product_id,
           stocktake_at,
           actual_quantity,
           ROW_NUMBER() OVER (
               PARTITION BY warehouse_id, product_id
               ORDER BY stocktake_at DESC, stocktake_id DESC
           ) AS rn
    FROM stocktake_record
)
SELECT warehouse_id,
       product_id,
       stocktake_at,
       actual_quantity
FROM latest_stocktake
WHERE rn = 1;

排序条件里除了 stocktake_at,还加上唯一的 stocktake_id。同一时刻有多条盘点数据时,结果仍然有确定顺序,源库和目标库才能稳定对比。

月度报表原来使用 PIVOT 把季度销售额展开为四列,迁移后也可以保留原来的列名和结果结构:

sql 复制代码
SELECT warehouse_id,
       [Q1],
       [Q2],
       [Q3],
       [Q4]
FROM (
    SELECT warehouse_id,
           quarter_code,
           sales_amount
    FROM warehouse_quarter_sales
) AS src
PIVOT (
    SUM(sales_amount)
    FOR quarter_code IN ([Q1], [Q2], [Q3], [Q4])
) AS p;

前端报表仍然接收 Q1Q4 四个字段,导出模板和图表配置也就不需要因为数据库切换而调整。UNPIVOT 用于反向将多个季度列还原成行,在导入标准明细表或者重新汇总时同样实用。

LIKE 里的字符范围不再另写正则

SQL Server 的 LIKE 除了 %_,存量代码里还经常能看到方括号字符范围。仓储系统用代码规则筛选 A 到 C 类物料时,可能就是这样一句:

sql 复制代码
SELECT material_code,
       material_name,
       warehouse_id
FROM material_master
WHERE material_code LIKE '[A-C][0-9][0-9]%'
ORDER BY material_code;

V9R4C019 对 SQL Server LIKE 通配符的完整支持,让这类搜索条件可以继续保留。项目组只需要把代码中用到的字符集、排序规则和样本结果放进回归清单,不用为每条范围匹配另造函数。

改动从"全面重写"收敛到连接和回归

一轮 T-SQL 梳理做完后,代码可以按处理方式分成三组:原样保留、工具自动转换、少量人工复核。MERGE、DML OUTPUT、窗口函数、PIVOT/UNPIVOT 和 SQL Server 风格的 LIKE 通配符可以进入第一组,开发人员把时间留给真正需要确认的业务对象。

上线前的回归也不用从头设计。库存日结核对批次和数量,账户额度核对主表与审计记录,窗口函数核对每组第一条,PIVOT 核对行数、四个季度列和合计值,LIKE 核对边界字符。这些都是原系统已经在用的业务语义,只需要在 V9R4C019 上重新确认一遍。

迁移计划也因此更容易排。数据库对象和存量 T-SQL 保留原结构,应用侧把改动集中在驱动、连接配置和必要的差异项上。开发团队面对的不再是一句"所有 SQL 都要改",而是一份已经按语法块分好类、能够逐项回归的迁移清单。

相关推荐
云飞云共享云桌面2 小时前
不用批量采购工作站|液压设备制造,SolidWorks 多人共享服务器方案
运维·服务器·网络·数据库·制造
写后端的胖头鱼2 小时前
【高频面试题】SQL 查询慢怎么排查
数据库·sql·mysql·oracle·慢查询·高频面试题
蓝速科技2 小时前
口岸政务窗口双屏翻译机落地应用指南
运维·数据结构·数据库·人工智能·科技·政务
风哥2号2 小时前
数据库教程FGMT20‑Oracle容灾体系架构与数据库升级迁移方案
数据库·oracle·架构
wudongfang6662 小时前
mysql全量同步数据改增量
数据库·mysql
志栋智能2 小时前
超自动化安全的变更与配置安全管理
数据库·安全·自动化
toooooop82 小时前
thinkphp查询数据表最后的自增id
前端·javascript·数据库
风哥2号2 小时前
数据库教程FGMT19‑Oracle多租户容器架构与新特性总结
数据库·oracle·架构
garmin Chen3 小时前
MySQL精简面试题
数据库·后端·mysql·面试