统一SQL介绍
https://www.light-pg.com/docs/LTSQL/current/index.html
源和目标
源数据库:Oracle
目标数据库:TDSQL-MySQL
操作目标
在Oracle中,decode函数语法如下图:该函数功能是将 expr与每个 search
依次做比较,并返回对比结果。
- 如果expr和search匹配,则返回result
- 如果expr没有找到匹配项,则返回default,如果default被省略,则返回null
在TDSQL-MySQL没有与之对应的函数,由此为适配该功能,统一SQL对包含decode函数的SQL语句使用TDSQL-MySQL的其他特性进行改写,使改写后的语句在TDSQL-MySQL中运行时表现相同的功能。
统一SQL转换
改写方案
统一SQL使用TDSQL-MySQL中的case...when...特性来替换decode函数。
转换案例
-- 转换前Oracle SQL
SELECT
DECODE(SIGN((5*3-2)-(3*4-1)),0,'相等',1,'(5*3-2)大','(3*4-1)大') AS c1,
DECODE(INSTR('CLARK','S'), 0, '不含有 S', '含有 S') AS "CLARK",
DECODE(INSTR('KING','S'), 0, '不含有 S', '含有 S') AS "KING",
DECODE(INSTR('MILLER','S'), 0, '不含有 S', '含有 S') AS "MILLER",
DECODE(INSTR('ADAMS','S'), 0, '不含有 S', '含有 S') AS "ADAMS",
DECODE(INSTR('FORD','S'), 0, '不含有 S', '含有 S') AS "FORD",
DECODE(INSTR('JONES','S'), 0, '不含有 S', '含有 S') AS "JONES"
FROM DUAL;
C1 |CLARK|KING |MILLER|ADAMS|FORD |JONES|
--------+-----+-----+------+-----+-----+-----+
(5*3-2)大|不含有 S|不含有 S|不含有 S |含有 S |不含有 S|含有 S |
-- 转换后TDSQL-MySQL SQL
select
case
when SIGN((5 * 3-2)-(3 * 4-1))= 0 then '相等'
when SIGN((5 * 3-2)-(3 * 4-1))= 1 then '(5*3-2)大'
else '(3*4-1)大'
end as `c1`,
case
when instr('CLARK', if(binary 'S' = '', null, binary 'S'))= 0 then '不含有 S'
else '含有 S'
end as `CLARK`,
case
when instr('KING', if(binary 'S' = '', null, binary 'S'))= 0 then '不含有 S'
else '含有 S'
end as `KING`,
case
when instr('MILLER', if(binary 'S' = '', null, binary 'S'))= 0 then '不含有 S'
else '含有 S'
end as `MILLER`,
case
when instr('ADAMS', if(binary 'S' = '', null, binary 'S'))= 0 then '不含有 S'
else '含有 S'
end as `ADAMS`,
case
when instr('FORD', if(binary 'S' = '', null, binary 'S'))= 0 then '不含有 S'
else '含有 S'
end as `FORD`,
case
when instr('JONES', if(binary 'S' = '', null, binary 'S'))= 0 then '不含有 S'
else '含有 S'
end as `JONES`
from DUAL
c1 |CLARK|KING |MILLER|ADAMS|FORD |JONES|
--------+-----+-----+------+-----+-----+-----+
(5*3-2)大|不含有 S|不含有 S|不含有 S |含有 S |不含有 S|含有 S |
-- 准备测试数据,以下是Oracle语句,对应的TDSQL-MySQL准备语句也可以通过统一SQL进行转换后在目标库执行
DROP TABLE unisql_decode_test;
CREATE TABLE unisql_decode_test(id int, name varchar(10));
INSERT INTO unisql_decode_test(id,name) values(1,'Linda');
INSERT INTO unisql_decode_test(id,name) values(2,'Tom');
INSERT INTO unisql_decode_test(id,name) values(3,'Richar');
INSERT INTO unisql_decode_test(id,name) values(4,'Nancy');
INSERT INTO unisql_decode_test(id,name) values(5,'Jane');
INSERT INTO unisql_decode_test(id,name) values(6,'Kiko');
-- 转换前Oracle SQL 有默认值的情况
SELECT
id,
name,
decode(id,
1,'Southlake',
2, 'San Francisco',
3, 'New Jersey',
4, 'Seattle',
'Non domestic') AS domestic
FROM unisql_decode_test;
ID|NAME |DOMESTIC |
--+------+-------------+
1|Linda |Southlake |
2|Tom |San Francisco|
3|Richar|New Jersey |
4|Nancy |Seattle |
5|Jane |Non domestic |
6|Kiko |Non domestic |
-- 转换后TDSQL-MySQL
select
`id`,
`name`,
case
when `id` = 1 then 'Southlake'
when `id` = 2 then 'San Francisco'
when `id` = 3 then 'New Jersey'
when `id` = 4 then 'Seattle'
else 'Non domestic'
end as `domestic`
from `unisql_decode_test`
id|name |domestic |
--+------+-------------+
1|Linda |Southlake |
2|Tom |San Francisco|
3|Richar|New Jersey |
4|Nancy |Seattle |
5|Jane |Non domestic |
6|Kiko |Non domestic |
-- 转换前Oracle SQL 没有默认值的情况
SELECT
id,
name,
decode(id,
1,'Southlake',
2, 'San Francisco',
3, 'New Jersey',
4, 'Seattle') AS domestic
FROM unisql_decode_test;
ID|NAME |DOMESTIC |
--+------+-------------+
1|Linda |Southlake |
2|Tom |San Francisco|
3|Richar|New Jersey |
4|Nancy |Seattle |
5|Jane | |
6|Kiko | |
-- 转换后TDSQL-MySQL
select
`id`,
`name`,
case
when `id` = 1 then 'Southlake'
when `id` = 2 then 'San Francisco'
when `id` = 3 then 'New Jersey'
when `id` = 4 then 'Seattle'
end as `domestic`
from
`unisql_decode_test`
id|name |domestic |
--+------+-------------+
1|Linda |Southlake |
2|Tom |San Francisco|
3|Richar|New Jersey |
4|Nancy |Seattle |
5|Jane | |
6|Kiko | |
Oracle其他函数到TDSQL-MySQL的转换可参考统一SQL官方手册
https://www.light-pg.com/docs/LTSQL/current/develop/Oracle2TDSQL-MySQL/index.html