统一SQL介绍
https://www.light-pg.com/docs/LTSQL/current/index.html
源和目标
源数据库:Oracle
目标数据库:TDSQL-MySQL
操作目标
在Oracle中,可以使用unpivot将列转换成行,在TDSQL-MySQL中没有对应的功能,由此,通过统一SQL进行语句改写,在限定条件下支持unpivot的功能。
统一SQL转换
Oracle 的unpivot语法图
统一SQL支持语法图
上图矩形框部分
转换方案
使用TDSQL-MySQL的 UNION ALL 特性进行Oracle unpivot的替换
转换案例
-- 前置准备Oracle-SQL:
CREATE TABLE unisql_unpivot(id INT,name VARCHAR(64),chinese NUMBER,math INT,english INT);
INSERT INTO unisql_unpivot VALUES(1,'张三',70,90,95);
INSERT INTO unisql_unpivot VALUES(2,'李四',75,85,90);
INSERT INTO unisql_unpivot VALUES(3,'张三',90,90,90);
drop table unisql_unpivot;
-- 转换前Oracle SQL:
SELECT id,name,score,subject FROM unisql_unpivot UNPIVOT(score FOR subject IN(chinese, math, english)) WHERE id IN (1, 2, 3) ORDER BY id;
ID|NAME|SCORE|SUBJECT|
--+----+-----+-------+
1|张三 | 70|CHINESE|
1|张三 | 90|MATH |
1|张三 | 95|ENGLISH|
2|李四 | 75|CHINESE|
2|李四 | 85|MATH |
2|李四 | 90|ENGLISH|
3|张三 | 90|CHINESE|
3|张三 | 90|MATH |
3|张三 | 90|ENGLISH|
-- 转换后TDSQL-MySQL
SELECT `id`,`name`,`chinese` AS `score`,'CHINESE' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) UNION ALL SELECT `id`,`name`,`math` AS `score`,'MATH' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) UNION ALL SELECT `id`,`name`,`english` AS `score`,'ENGLISH' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) ORDER BY `id`
id|name|score|subject|
--+----+-----+-------+
1|张三 | 70|CHINESE|
1|张三 | 95|ENGLISH|
1|张三 | 90|MATH |
2|李四 | 85|MATH |
2|李四 | 75|CHINESE|
2|李四 | 90|ENGLISH|
3|张三 | 90|MATH |
3|张三 | 90|CHINESE|
3|张三 | 90|ENGLISH|
-- 转换前Oracle SQL:
SELECT id,name,score,subject FROM unisql_unpivot UNPIVOT(score FOR subject IN(chinese, math, english)) WHERE id IN (1, 2, 3) ORDER BY id,name,score,subject OFFSET 1 ROWS FETCH NEXT 2 ROWS ONLY;
ID|NAME|SCORE|SUBJECT|
--+----+-----+-------+
1|张三 | 90|MATH |
1|张三 | 95|ENGLISH|
-- 转换后TDSQL-MySQL
SELECT `id`,`name`,`chinese` AS `score`,'CHINESE' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) UNION ALL SELECT `id`,`name`,`math` AS `score`,'MATH' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) UNION ALL SELECT `id`,`name`,`english` AS `score`,'ENGLISH' AS `subject` FROM `unisql_unpivot` WHERE `id` IN (1,2,3) ORDER BY `id`,`name`,`score`,`subject` LIMIT 1,2
id|name|score|subject|
--+----+-----+-------+
1|张三 | 90|MATH |
1|张三 | 95|ENGLISH|
使用限制
统一SQL当前对unpivot转换使用限制如下:
1. 只支持在单表查询语句中使用,参考如下:
SELECT id,name,score AS sc,subject AS su FROM unisql_unpivot UNPIVOT(score FOR subject IN(chinese, math, english)) WHERE id IN (1, 2, 3,4,5) ORDER BY id;
2. 只支持单字段的unpivot,如上(score for subject)
3. 统一SQL会将unpivot in中的字段转换为大写,如上(chinese-->CHINESE, math-->MATH, english-->ENGLISH)
4. 不支持join,with, 子查询,group by, having,rownum
5. 不支持unpivot和unpivot for字段上使用函数,表达式
6. 不支持unpivot in语句中的字段使用AS
7. 分页查询存在offset时必须有fetch
8. 注意oracle和tdmysql字符集,排序规则等底层实现存在差异,排序字段需要保证是唯一序,否则可能导致两个库执行结果获取结果顺序不一致。