当前位置: 首页 > news >正文

源代码:大批量SQL代码语法转换实战:PIVOT函数改写(案例1)

### 背景:在不同数据库迁移的项目中,往往会遇到SQL语法不兼容的情况。比如有的数据库支持PIVOT函数,有的不支持。遇到这种情况,就必须对PIVOT函数进行改写。

### 问题:如果存在大量代码需要改写的情况,靠人工处理会很耗时,且容易出错。能否通过工具实现代码语法的大批量自动转换?

### 方案:可以使用开源代码 解析器 ZGLanguage 对SQL代码进行大批量自动转换

### 案例演示:

# 存在 SQL PIVOT函数 如下所示:

SELECT *
FROM (select country,state,yr,qtr,sales,cogs from table111)
PIVOT
(SUM(sales) AS ss1,SUM(cogs)  AS sc FOR qtr IN ('Q1' AS Quarter1,'Q2' AS Quarter2,'Q3' AS Quarter3,'Q4' AS Quarter4)
) tmp
;

# 使用开源软件  ZGLanguage 执行转换,可得到结果:

SELECT *
FROM 
(select ###,###,###SUM (case when qtr='Q1' then sales else null end) AS Quarter1_ss1,SUM (case when qtr='Q2' then sales else null end) AS Quarter2_ss1,SUM (case when qtr='Q3' then sales else null end) AS Quarter3_ss1,SUM (case when qtr='Q4' then sales else null end) AS Quarter4_ss1,SUM (case when qtr='Q1' then cogs else null end) AS Quarter1_sc,SUM (case when qtr='Q2' then cogs else null end) AS Quarter2_sc,SUM (case when qtr='Q3' then cogs else null end) AS Quarter3_sc,SUM (case when qtr='Q4' then cogs else null end) AS Quarter4_scfrom (select country,state,yr,qtr,sales,cogs from table111) where qtr IN('Q1','Q2','Q3','Q4')group by ###,###,###
) tmp
;

# 转换规则如下所示 :

__DEF_FUZZY__             Y
__DEF_DEBUG__             N
__DEF_CASE_SENSITIVE__    N__DEF_LINE_COMMENT__      -- 
__DEF_LINES_COMMENT__     /*     */__DEF_STR__   __IF_KW__
<1,100>
[1,1]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
[0,100]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_
[NO] XXX__DEF_PATH__    __FROM_PIVOT_1_1__
1              : frm         @ %__IF_KW__             | from: tab         @                        | __TABLE_NAME__: ssl         @                        + __SUB_SELECT__: pvt         @                        | pivot: x1          @                        | (
N              : fun         @                        | __NAME__        __//__ sum ....: fs          @                        | (: col1        @                        | __NAME__: fe          @                        | ): as1         @ %__IF_KW__ CAN_SKIP    | as: colas       @                        | __NAME__
e              : dh1         @                        | ,
1              : for         @ %__IF_KW__             | for: col2        @                        | __NAME__: in          @                        | in: x3          @                        | (
N              : val1        @                        | __INT__: val2        @                        + __STRING__: as2         @ CAN_SKIP               | as: coln        @                        | __NAME__
e              : dh          @                        | ,
1              : x4          @                        | ): x2          @                        | )
-------------------------------------------------------------------------
1              : frm         @                        | from: tab         @                        | __TABLE_NAME__: ssl         @                        | __SUB_SELECT__: pvt         @                        | pivot: x1          @                        | (
N              : fun         @                        | __NAME__: fs          @                        | (: col1        @                        | __NAME__: fe          @                        | ): as1         @                        | as: colas       @                        | __NAME__
e              : dh1         @                        | ,
1              : for         @                        | for: col2        @                        | __NAME__: in          @                        | in: x3          @                        | (
N              : val1        @                        | __\b__: val2        @                        | __\b__: col2        @                        | __NAME__: col2        @                        | =: val1        @                        | __INT__: val2        @                        | __STRING__: as2         @                        | as: coln        @                        | __NAME__
e              : dh          @                        | ,
1              : x4          @                        | ): x2          @                        | )__DEF_PATH__    __FROM_PIVOT_1_2__
1              : frm         @ %__IF_KW__             | from: tab         @                        | __TABLE_NAME__: ssl         @                        + __SUB_SELECT__: pvt         @                        | pivot: x1          @                        | (
N              : fun         @                        | __NAME__        __//__ sum ....: fs          @                        | (: col1        @                        | __NAME__: fe          @                        | ): as1         @ %__IF_KW__ CAN_SKIP    | as: colas       @                        | __NAME__
e              : dh1         @                        | ,
1              : for         @ %__IF_KW__             | for: col2        @                        | __NAME__: in          @                        | in: x3          @                        | (
N              : col22       @                        | __NAME__: col23       @                        | =: val1        @                        | __INT__: val2        @                        + __STRING__: as2         @ CAN_SKIP               | as: coln        @                        | __NAME__
e              : dh          @                        | ,
1              : x4          @                        | ): x2          @                        | )
--------------------------------------------------------------------
1              : frm         @                        | from: tab         @                        | __TABLE_NAME__: ssl         @                        | __SUB_SELECT__: pvt         @                        | pivot: x1          @                        | (
N              : fun         @                        | __NAME__: fs          @                        | (: col1        @                        | __NAME__: fe          @                        | ): as1         @                        | as: colas       @                        | __NAME__
*              : col22       @                        | __NAME__: col23       @                        | =: val1        @                        | __INT__: val2        @                        | __STRING__: as2         @                        | as: coln        @                        | __NAME__
e              : coln        @                        | ,
1              : for         @                        | where: col2        @                        | __NAME__: in          @                        | in: x3          @                        | (
N              : val1        @                        | __INT__: val2        @                        | __STRING__
e              : dh          @                        | ,
1              : x4          @                        | )
1              : x2          @                        | )__DEF_PATH__    __FROM_PIVOT_1_3__
1              : frm         @ %__IF_KW__             | from: tab         @                        | __TABLE_NAME__: ssl         @                        + __SUB_SELECT__: pvt         @                        | pivot: x1          @                        | (
N              : fun         @                        | __NAME__: fs          @                        | (: col1        @                        | __NAME__: fe          @                        | ): as1         @ %__IF_KW__ CAN_SKIP    | as: colas       @                        | __NAME__: col22       @                        | __NAME__: col23       @                        | =: val1        @                        | __INT__: val2        @                        + __STRING__: as2         @ %__IF_KW__ CAN_SKIP    | as: coln        @                        | __NAME__
e              : dh          @                        | ,
1              : for         @                        | where: col2        @                        | __NAME__: in          @                        | in: x3          @                        | (
N              : val3        @                        | __INT__: val4        @                        + __STRING__
e              : dh1         @                        | ,
1              : x4          @                        | ): x2          @                        | )
--------------------------------------------------------------------
1              : frm         @ STRING                 | from: pvt         @ STRING                 | (select ###,###,###
N              : fun         @                        | __NAME__: fs          @                        / (: col22       @ STRING                 \ case when: col22       @                        / __NAME__: col23       @                        / =: val1        @                        / __INT__: val2        @                        / __STRING__: col1        @                        / then: col1        @                        / __NAME__: col1        @ STRING                 / else null end: fe          @                        \ ): as1         @                        | as: coln        @                        | __NAME__: coln        @                        \ _: colas       @                        \ __NAME__
e              : dh          @                        | ,
1              : pvt         @                        | from: tab         @                        | __TABLE_NAME__: ssl         @                        | __SUB_SELECT__
1              : for         @                        | where: col2        @                        / __NAME__: in          @                        / in: x3          @                        \ (
N              : val3        @                        \ __INT__: val4        @                        \ __STRING__
e              : dh1         @                        \ ,
1              : x4          @                        \ ): x4          @ STRING                 | group by ###,###,###: x2          @                        | )__DEF_SUB_PATH__       __TABLE_NAME__
1        : srctab           @               | __NAME__
+        : schema           @               | __NAME__: pp               @               | .: srctab2          @               | __NAME____DEF_SUB_PATH__   __SUB_SELECT__
1        : x1               @               | __SUB____DEF_PATH__   __SUB__
1        : x1               @               | ( 
N        : x2               @               | __ALL_STR__: x3               @               + __SUB__
1        : x4               @               | )__DEF_STR__   __ALL_STR__
<1,20000>
[1,20000]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*-_+={}[]\|:;'"<,>.?/
__DEF_STR__   __NAME__
<1,100>
[1,1]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_??
[0,100]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_??
[NO] create insert update delete truncate drop merge table select inner left join on from where group order partition by having union all with as set between and or like in is not null case when then pivot lateral view 
__DEF_STR__   __INT__
<1,100>
[1,100]0123456789
__DEF_SUB_PATH__   __STRING__
1       : x1                  | ': x2                  | __ANY__: x3                  | '

 

### 转换规则详细说明:

以上PIVOT函数的转换规则比较复杂,不能一次性转换完毕,这里分成3次转换完成:

ZGLanguage -e PIVOT_UNPIVOT_SQL_REPLACE.syn -r pivot_unpivot.code -o 1_mid_result.zgl
ZGLanguage -e PIVOT_UNPIVOT_SQL_REPLACE.syn -r 1_mid_result.zgl -o 2_mid_result.zgl
ZGLanguage -e PIVOT_UNPIVOT_SQL_REPLACE.syn -r 2_mid_result.zgl -o result.zgl

# 第1次转换规则 “__FROM_PIVOT_1_1__” 对源代码进行转换,完成 值“qtr” 和 枚举值 “Q1,Q2,Q3,Q4” 的一一映射关系,得到如下结果:

SELECT *
FROM (select country,state,yr,qtr,sales,cogs from table111) 
PIVOT
(SUM(sales ) AS ss1 ,SUM(cogs) AS scFOR qtr IN(  qtr = 'Q1' AS Quarter1 ,  qtr = 'Q2' AS Quarter2 ,  qtr = 'Q3' AS Quarter3 ,  qtr = 'Q4' AS Quarter4)
) tmp
;

# 第2次转换规则 “__FROM_PIVOT_1_2__” 对 “__FROM_PIVOT_1_1__” 的转换结果(以上)再次进行转换。 
  完成:
  (A) 聚合函数“SUM字段” 和 “qtr字段” 的笛卡尔积映射
  (B) FOR 结构转成 where 结构
  得到如下结果:

SELECT *
FROM (select country,state,yr,qtr,sales,cogs from table111) PIVOT
(SUM(sales) AS ss1   qtr = 'Q1' AS Quarter1 ,SUM(sales) AS ss1   qtr = 'Q2' AS Quarter2 ,SUM(sales) AS ss1   qtr = 'Q3' AS Quarter3 ,SUM(sales) AS ss1   qtr = 'Q4' AS Quarter4 ,SUM(cogs) AS sc     qtr = 'Q1' AS Quarter1 ,SUM(cogs) AS sc     qtr = 'Q2' AS Quarter2 ,SUM(cogs) AS sc     qtr = 'Q3' AS Quarter3 ,SUM(cogs) AS sc     qtr = 'Q4' AS Quarter4 where qtr IN('Q1' ,'Q2' ,'Q3' ,'Q4')
) tmp
;

# 第3次转换规则 “__FROM_PIVOT_1_3__” 对 “__FROM_PIVOT_1_2__” 的转换结果(以上)再次进行转换。 
  完成:
  (A) 对SUM开头的字段内容进行新增、位移、合并 等操作,形成语法正确的字段逻辑
  (B) 剔除PIVOT关键字,移动子查询到 where 语句上方
  (C) 新增待人工补充部分: select ###,###,###   group by ###,###,###
  得到最终结果:

SELECT *
FROM 
(select ###,###,###SUM(case when qtr='Q1' then sales else null end) AS Quarter1_ss1,SUM(case when qtr='Q2' then sales else null end) AS Quarter2_ss1,SUM(case when qtr='Q3' then sales else null end) AS Quarter3_ss1,SUM(case when qtr='Q4' then sales else null end) AS Quarter4_ss1,SUM(case when qtr='Q1' then cogs else null end) AS Quarter1_sc,SUM(case when qtr='Q2' then cogs else null end) AS Quarter2_sc,SUM(case when qtr='Q3' then cogs else null end) AS Quarter3_sc,SUM(case when qtr='Q4' then cogs else null end) AS Quarter4_scfrom (select country,state,yr,qtr,sales,cogs from table111) where qtr IN('Q1','Q2','Q3','Q4')group by ###,###,###
) tmp
;

### 新增待补充部分 “###,###,###” 说明:

1、通过简单的配置,不能直接转换成完全可用的SQL代码,有些代码部分依然需要人工补充
2、需要人工补充的部分,已经通过 ###,###,### 明显地标注出来
3、通过工具已经完成了大部分的转换工作,极大的减轻了人工参与的工作量,规避人工修改失误的风险

源代码下载: https://gitee.com/zgl-20053779/zglanguage

 

http://www.jsqmd.com/news/436064/

相关文章:

  • 【图像加密解密】行列像素灰色图像加密解密【含Matlab源码 15120期】
  • 2026年湖北文化课集训参考:艺术生/高三文化课冲刺实力机构推荐 - 品牌推荐官
  • winform GDI+ 在矩形框中间绘制文字
  • 【vllm】EngineCoreProc 的run_engine_core 中才创建EngineCoreProc 对象,为什么? 这是什么用法?
  • MacOS应用主菜单连接到ViewController的事件
  • 2025最新阴离子树脂厂家测评与应用推荐:技术与产能双维度解析 - 深度智识库
  • 2026年3月长岛民宿推荐,特色体验与品牌保障口碑之选 - 品牌鉴赏师
  • Linux的vim更新到9.2
  • 关于MoE Load Balance
  • 天虹购物卡回收可行方法全解析,正规平台让闲置卡券轻松兑现 - 京回收小程序
  • 记录学习网络安全的第一章
  • 主流MES厂商量化评分榜(附推荐指数与决策地图):告别“凭感觉选型” - 华Sir1
  • 解决MI50在Ollama0.17.4无法运行最新的Qwen3.5模型的问题(II)
  • 2026南通专业铝艺大门厂家推荐榜适配全场景 - 优质品牌商家
  • 2026年商务调查优质服务推荐指南:成都寻人公司/成都找人/成都找人公司/四川商务调查公司/四川寻人/选择指南 - 优质品牌商家
  • mac Mini安装openclaw
  • 天津雅思机构排名避坑版|5家热门机构优劣势全拆解 - 大喷菇123
  • 2026年 ARO/GRACO涂胶机厂家推荐排行榜:汽车玻璃/新能源电机/锂电/双组分精密涂胶设备实力品牌深度解析 - 品牌企业推荐师(官方)
  • 2026年固废堆填场所环境风险评估专业机构推荐:填埋场/尾矿库/磷石膏堆场风险评估服务精选 - 品牌推荐官
  • 2026年陕西废品回收行业最新榜单:西安震霆工贸凭什么领跑西北资源循环赛道? - 深度智识库
  • 探讨把强模型推理经验变成可复用资产——最后和Meta撞了
  • 2026四川消防维保优质服务商推荐指南 - 优质品牌商家
  • 线程与进程的区别与联系:操作系统入门详解(含 Python 示例)
  • unity中简单创建后视镜/镜片
  • Claude Code 10大神级Skills笔记
  • 2026年山东水下打捞服务推荐:飞龙水下打捞,专业潜水打捞金戒指/手机/金项链及同城24小时蛙人声呐打捞团队精选 - 品牌推荐官
  • React Native + OpenHarmony:Stepper步进器组件 - 实践
  • 2026天津雅思机构排名TOP5|实测不踩坑,新手必看 - 大喷菇123
  • Containerd容器运行时介绍与应用
  • potplayer视频使用lossless scaling小黄鸭补帧卡顿解决方法