找回密码
 立即注册
首页 业界区 安全 源代码:大批量SQL代码语法转换实战:PIVOT函数改写(案 ...

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

少屠 昨天 23:50
### 背景:在不同数据库迁移的项目中,往往会遇到SQL语法不兼容的情况。比如有的数据库支持PIVOT函数,有的不支持。遇到这种情况,就必须对PIVOT函数进行改写。
### 问题:如果存在大量代码需要改写的情况,靠人工处理会很耗时,且容易出错。能否通过工具实现代码语法的大批量自动转换?
### 方案:可以使用开源代码 解析器 ZGLanguage 对SQL代码进行大批量自动转换
### 案例演示:
# 存在 SQL PIVOT函数 如下所示:
  1. SELECT *
  2. FROM (select country,state,yr,qtr,sales,cogs from table111)
  3. PIVOT
  4. (
  5.     SUM(sales) AS ss1,
  6.     SUM(cogs)  AS sc
  7.     FOR qtr IN
  8.     (
  9.         'Q1' AS Quarter1,
  10.         'Q2' AS Quarter2,
  11.         'Q3' AS Quarter3,
  12.         'Q4' AS Quarter4
  13.     )
  14. ) tmp
  15. ;
复制代码
# 使用开源软件  ZGLanguage 执行转换,可得到结果:
  1. SELECT *
  2. FROM
  3. (
  4.   select ###,###,###
  5.          SUM (case when qtr='Q1' then sales else null end) AS Quarter1_ss1,
  6.          SUM (case when qtr='Q2' then sales else null end) AS Quarter2_ss1,
  7.          SUM (case when qtr='Q3' then sales else null end) AS Quarter3_ss1,
  8.          SUM (case when qtr='Q4' then sales else null end) AS Quarter4_ss1,
  9.          SUM (case when qtr='Q1' then cogs else null end) AS Quarter1_sc,
  10.          SUM (case when qtr='Q2' then cogs else null end) AS Quarter2_sc,
  11.          SUM (case when qtr='Q3' then cogs else null end) AS Quarter3_sc,
  12.          SUM (case when qtr='Q4' then cogs else null end) AS Quarter4_sc
  13.   from (select country,state,yr,qtr,sales,cogs from table111)
  14. where qtr IN('Q1','Q2','Q3','Q4')
  15. group by ###,###,###
  16. ) tmp
  17. ;
复制代码
# 转换规则如下所示 :
  1. __DEF_FUZZY__             Y
  2. __DEF_DEBUG__             N
  3. __DEF_CASE_SENSITIVE__    N
  4. __DEF_LINE_COMMENT__      --
  5. __DEF_LINES_COMMENT__     /*     */
  6. __DEF_STR__   __IF_KW__
  7. <1,100>
  8. [1,1]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
  9. [0,100]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_
  10. [NO] XXX
  11. __DEF_PATH__    __FROM_PIVOT_1_1__
  12. 1              : frm         @ %__IF_KW__             | from
  13.                : tab         @                        | __TABLE_NAME__
  14.                : ssl         @                        + __SUB_SELECT__
  15.                : pvt         @                        | pivot
  16.                : x1          @                        | (
  17. N              : fun         @                        | __NAME__        __//__ sum ....
  18.                : fs          @                        | (
  19.                : col1        @                        | __NAME__
  20.                : fe          @                        | )
  21.                : as1         @ %__IF_KW__ CAN_SKIP    | as
  22.                : colas       @                        | __NAME__
  23. e              : dh1         @                        | ,
  24. 1              : for         @ %__IF_KW__             | for
  25.                : col2        @                        | __NAME__
  26.                : in          @                        | in
  27.                : x3          @                        | (
  28. N              : val1        @                        | __INT__
  29.                : val2        @                        + __STRING__
  30.                : as2         @ CAN_SKIP               | as
  31.                : coln        @                        | __NAME__
  32. e              : dh          @                        | ,
  33. 1              : x4          @                        | )
  34.                : x2          @                        | )
  35. -------------------------------------------------------------------------
  36. 1              : frm         @                        | from
  37.                : tab         @                        | __TABLE_NAME__
  38.                : ssl         @                        | __SUB_SELECT__
  39.                : pvt         @                        | pivot
  40.                : x1          @                        | (
  41. N              : fun         @                        | __NAME__
  42.                : fs          @                        | (
  43.                : col1        @                        | __NAME__
  44.                : fe          @                        | )
  45.                : as1         @                        | as
  46.                : colas       @                        | __NAME__
  47. e              : dh1         @                        | ,
  48. 1              : for         @                        | for
  49.                : col2        @                        | __NAME__
  50.                : in          @                        | in
  51.                : x3          @                        | (
  52. N              : val1        @                        | __\b__
  53.                : val2        @                        | __\b__
  54.                : col2        @                        | __NAME__
  55.                : col2        @                        | =
  56.                : val1        @                        | __INT__
  57.                : val2        @                        | __STRING__
  58.                : as2         @                        | as
  59.                : coln        @                        | __NAME__
  60. e              : dh          @                        | ,
  61. 1              : x4          @                        | )
  62.                : x2          @                        | )
  63. __DEF_PATH__    __FROM_PIVOT_1_2__
  64. 1              : frm         @ %__IF_KW__             | from
  65.                : tab         @                        | __TABLE_NAME__
  66.                : ssl         @                        + __SUB_SELECT__
  67.                : pvt         @                        | pivot
  68.                : x1          @                        | (
  69. N              : fun         @                        | __NAME__        __//__ sum ....
  70.                : fs          @                        | (
  71.                : col1        @                        | __NAME__
  72.                : fe          @                        | )
  73.                : as1         @ %__IF_KW__ CAN_SKIP    | as
  74.                : colas       @                        | __NAME__
  75. e              : dh1         @                        | ,
  76. 1              : for         @ %__IF_KW__             | for
  77.                : col2        @                        | __NAME__
  78.                : in          @                        | in
  79.                : x3          @                        | (
  80. N              : col22       @                        | __NAME__
  81.                : col23       @                        | =
  82.                : val1        @                        | __INT__
  83.                : val2        @                        + __STRING__
  84.                : as2         @ CAN_SKIP               | as
  85.                : coln        @                        | __NAME__
  86. e              : dh          @                        | ,
  87. 1              : x4          @                        | )
  88.                : x2          @                        | )
  89. --------------------------------------------------------------------
  90. 1              : frm         @                        | from
  91.                : tab         @                        | __TABLE_NAME__
  92.                : ssl         @                        | __SUB_SELECT__
  93.                : pvt         @                        | pivot
  94.                : x1          @                        | (
  95. N              : fun         @                        | __NAME__
  96.                : fs          @                        | (
  97.                : col1        @                        | __NAME__
  98.                : fe          @                        | )
  99.                : as1         @                        | as
  100.                : colas       @                        | __NAME__
  101. *              : col22       @                        | __NAME__
  102.                : col23       @                        | =
  103.                : val1        @                        | __INT__
  104.                : val2        @                        | __STRING__
  105.                : as2         @                        | as
  106.                : coln        @                        | __NAME__
  107. e              : coln        @                        | ,
  108. 1              : for         @                        | where
  109.                : col2        @                        | __NAME__
  110.                : in          @                        | in
  111.                : x3          @                        | (
  112. N              : val1        @                        | __INT__
  113.                : val2        @                        | __STRING__
  114. e              : dh          @                        | ,
  115. 1              : x4          @                        | )
  116. 1              : x2          @                        | )
  117. __DEF_PATH__    __FROM_PIVOT_1_3__
  118. 1              : frm         @ %__IF_KW__             | from
  119.                : tab         @                        | __TABLE_NAME__
  120.                : ssl         @                        + __SUB_SELECT__
  121.                : pvt         @                        | pivot
  122.                : x1          @                        | (
  123. N              : fun         @                        | __NAME__
  124.                : fs          @                        | (
  125.                : col1        @                        | __NAME__
  126.                : fe          @                        | )
  127.                : as1         @ %__IF_KW__ CAN_SKIP    | as
  128.                : colas       @                        | __NAME__
  129.                : col22       @                        | __NAME__
  130.                : col23       @                        | =
  131.                : val1        @                        | __INT__
  132.                : val2        @                        + __STRING__
  133.                : as2         @ %__IF_KW__ CAN_SKIP    | as
  134.                : coln        @                        | __NAME__
  135. e              : dh          @                        | ,
  136. 1              : for         @                        | where
  137.                : col2        @                        | __NAME__
  138.                : in          @                        | in
  139.                : x3          @                        | (
  140. N              : val3        @                        | __INT__
  141.                : val4        @                        + __STRING__
  142. e              : dh1         @                        | ,
  143. 1              : x4          @                        | )
  144.                : x2          @                        | )
  145. --------------------------------------------------------------------
  146. 1              : frm         @ STRING                 | from
  147.                : pvt         @ STRING                 | (select ###,###,###
  148. N              : fun         @                        | __NAME__
  149.                : fs          @                        / (
  150.                : col22       @ STRING                 \ case when
  151.                : col22       @                        / __NAME__
  152.                : col23       @                        / =
  153.                : val1        @                        / __INT__
  154.                : val2        @                        / __STRING__
  155.                : col1        @                        / then
  156.                : col1        @                        / __NAME__
  157.                : col1        @ STRING                 / else null end
  158.                : fe          @                        \ )
  159.                : as1         @                        | as
  160.                : coln        @                        | __NAME__
  161.                : coln        @                        \ _
  162.                : colas       @                        \ __NAME__
  163. e              : dh          @                        | ,
  164. 1              : pvt         @                        | from
  165.                : tab         @                        | __TABLE_NAME__
  166.                : ssl         @                        | __SUB_SELECT__
  167. 1              : for         @                        | where
  168.                : col2        @                        / __NAME__
  169.                : in          @                        / in
  170.                : x3          @                        \ (
  171. N              : val3        @                        \ __INT__
  172.                : val4        @                        \ __STRING__
  173. e              : dh1         @                        \ ,
  174. 1              : x4          @                        \ )
  175.                : x4          @ STRING                 | group by ###,###,###
  176.                : x2          @                        | )
  177. __DEF_SUB_PATH__       __TABLE_NAME__
  178. 1        : srctab           @               | __NAME__
  179. +        : schema           @               | __NAME__
  180.          : pp               @               | .
  181.          : srctab2          @               | __NAME__
  182. __DEF_SUB_PATH__   __SUB_SELECT__
  183. 1        : x1               @               | __SUB__
  184. __DEF_PATH__   __SUB__
  185. 1        : x1               @               | (
  186. N        : x2               @               | __ALL_STR__
  187.          : x3               @               + __SUB__
  188. 1        : x4               @               | )
  189. __DEF_STR__   __ALL_STR__
  190. <1,20000>
  191. [1,20000]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*-_+={}[]\|:;'"<,>.?/
  192. __DEF_STR__   __NAME__
  193. <1,100>
  194. [1,1]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_??
  195. [0,100]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_??
  196. [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
  197. __DEF_STR__   __INT__
  198. <1,100>
  199. [1,100]0123456789
  200. __DEF_SUB_PATH__   __STRING__
  201. 1       : x1                  | '
  202.         : x2                  | __ANY__
  203.         : x3                  | '
复制代码
 
### 转换规则详细说明:
以上PIVOT函数的转换规则比较复杂,不能一次性转换完毕,这里分成3次转换完成:
  1. ZGLanguage -e PIVOT_UNPIVOT_SQL_REPLACE.syn -r pivot_unpivot.code -o 1_mid_result.zgl
  2. ZGLanguage -e PIVOT_UNPIVOT_SQL_REPLACE.syn -r 1_mid_result.zgl -o 2_mid_result.zgl
  3. 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” 的一一映射关系,得到如下结果:
  1. SELECT *
  2. FROM (select country,state,yr,qtr,sales,cogs from table111)
  3. PIVOT
  4. (
  5.     SUM(sales ) AS ss1 ,
  6.     SUM(cogs) AS sc
  7.     FOR qtr IN
  8.     (  
  9.     qtr = 'Q1' AS Quarter1 ,  
  10.     qtr = 'Q2' AS Quarter2 ,  
  11.     qtr = 'Q3' AS Quarter3 ,  
  12.     qtr = 'Q4' AS Quarter4
  13.     )
  14. ) tmp
  15. ;
复制代码
# 第2次转换规则 “__FROM_PIVOT_1_2__” 对 “__FROM_PIVOT_1_1__” 的转换结果(以上)再次进行转换。 
  完成:
  (A) 聚合函数“SUM字段” 和 “qtr字段” 的笛卡尔积映射
  (B) FOR 结构转成 where 结构
  得到如下结果:
  1. SELECT *
  2. FROM (select country,state,yr,qtr,sales,cogs from table111) PIVOT
  3. (
  4.     SUM(sales) AS ss1   qtr = 'Q1' AS Quarter1 ,
  5.     SUM(sales) AS ss1   qtr = 'Q2' AS Quarter2 ,
  6.     SUM(sales) AS ss1   qtr = 'Q3' AS Quarter3 ,
  7.     SUM(sales) AS ss1   qtr = 'Q4' AS Quarter4 ,
  8.        
  9.     SUM(cogs) AS sc     qtr = 'Q1' AS Quarter1 ,
  10.     SUM(cogs) AS sc     qtr = 'Q2' AS Quarter2 ,
  11.     SUM(cogs) AS sc     qtr = 'Q3' AS Quarter3 ,
  12.     SUM(cogs) AS sc     qtr = 'Q4' AS Quarter4
  13.        
  14.         where qtr IN
  15.     (
  16.         'Q1' ,
  17.         'Q2' ,
  18.         'Q3' ,
  19.         'Q4'
  20.     )
  21. ) tmp
  22. ;
复制代码
# 第3次转换规则 “__FROM_PIVOT_1_3__” 对 “__FROM_PIVOT_1_2__” 的转换结果(以上)再次进行转换。 
  完成:
  (A) 对SUM开头的字段内容进行新增、位移、合并 等操作,形成语法正确的字段逻辑
  (B) 剔除PIVOT关键字,移动子查询到 where 语句上方
  (C) 新增待人工补充部分: select ###,###,###   group by ###,###,###
  得到最终结果:
  1. SELECT *
  2. FROM
  3. (
  4.   select ###,###,###
  5.          SUM(case when qtr='Q1' then sales else null end) AS Quarter1_ss1,
  6.          SUM(case when qtr='Q2' then sales else null end) AS Quarter2_ss1,
  7.          SUM(case when qtr='Q3' then sales else null end) AS Quarter3_ss1,
  8.          SUM(case when qtr='Q4' then sales else null end) AS Quarter4_ss1,
  9.          SUM(case when qtr='Q1' then cogs else null end) AS Quarter1_sc,
  10.          SUM(case when qtr='Q2' then cogs else null end) AS Quarter2_sc,
  11.          SUM(case when qtr='Q3' then cogs else null end) AS Quarter3_sc,
  12.          SUM(case when qtr='Q4' then cogs else null end) AS Quarter4_sc
  13.   from (select country,state,yr,qtr,sales,cogs from table111)
  14. where qtr IN('Q1','Q2','Q3','Q4')
  15. group by ###,###,###
  16. ) tmp
  17. ;
复制代码
### 新增待补充部分 “###,###,###” 说明:
1、通过简单的配置,不能直接转换成完全可用的SQL代码,有些代码部分依然需要人工补充
2、需要人工补充的部分,已经通过 ###,###,### 明显地标注出来
3、通过工具已经完成了大部分的转换工作,极大的减轻了人工参与的工作量,规避人工修改失误的风险
源代码下载: https://gitee.com/zgl-20053779/zglanguage


 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册