The technologies for SQL migration

The function syntaxes of various types of databases are more or less different from each other. In order to make the SQL query statements of the same functionality be executed successfully in different types of databases, we need to translate these differentiated function syntaxes that are available in each database, and that is SQL migration. This article will explore several technologies for SQL migration and compare them in detail.

ORM technology

The queries written by programmers can be converted to SQLs of different databases with ORM, which equals certain migratability. But ORM is only suitable for simple SQL in OLTP scenario. As for OLAP scenario, it can hardly migrates the complex SQL.

Hibernate and Mybatis are two of the most common ORM technology. Mybatis is also known as semi-automatic ORM, which is mainly because the programmers need to write native SQL by themselves. That makes Mybatis hardly for migration, even with third-party expansion packages like Mybatis-plus and Mybatis-ext, Mybatis’ input method can be improved but its migratability is still far less than Hibernate. While Hibernate can use HQL to automatically generate corresponding SQL based on the database dialect in the configuration file, so it can perform migration for some simple situations (which are directly supported in Hibernate), for example:

HQL:

SELECT
client,
YEAR(orderDate),
sum(amount),
count(orderId)
FROM
OrdersEntity
GROUPBY
client,
YEAR(orderDate)
HAVING
sum(amount)>2000

MySQL:

SELECT
ordersenti0_.ClientAScol_0_0_,
YEAR(ordersenti0_.OrderDate)AScol_1_0_,
sum(ordersenti0_.Amount)AScol_2_0_,
count(ordersenti0_.OrderID)AScol_3_0_
FROM
orders ordersenti0_
GROUPBY
ordersenti0_.Client,
YEAR(ordersenti0_.OrderDate)
HAVING
sum(ordersenti0_.Amount)>2000

Oracle:

SELECT
ordersenti0_.ClientAScol_0_0_,
EXTRACT(YEARFROMordersenti0_.OrderDate)AScol_1_0_,
sum(ordersenti0_.Amount)AScol_2_0_,
count(ordersenti0_.OrderID)AScol_3_0_
FROM
system.orders ordersenti0_
GROUPBY
ordersenti0_.Client,
EXTRACT(YEARFROMordersenti0_.OrderDate)
HAVING
sum(ordersenti0_.Amount)>2000

In the SQL generated in HQL, the YEAR(d) function is used to correspond to MySQL and the EXTRACT(YEAR FROM d) function is used to Oracle, which can achieve SQL migration.

However, Hibernate may not perform migration successfully in some more complicated circumstances.

For example, we need to register custom functions according to the current database before generating SQL from HQL when using functions not directly supported in HQL itself, using MySQL as an example:

The key code to register custom functions:

registerFunction("udf_dateadd", new SQLFunctionTemplate(DateType.INSTANCE,"date_add(?1,INTERVAL ?2 DAY)"));

HQL:

SELECT
udf_dateadd (orderDate,3)
FROM
OrdersEntity

MySQL:

SELECT
date_add(ordersenti0_.OrderDate,INTERVAL3DAY)AScol_0_0_
FROM
orders ordersenti0_

But there is no date_add function in Oracle. If the database turns to Oracle, then we need to register other new custom functions based on the function syntax of Oracle, which can not be migrated automatically.

There are also some operations that cannot be described in HQL, such as the subquery in FROM:

SELECT
orderId,
m
FROM
(
SELECT
orderId,
MONTH(orderDate) m
FROM
OrdersEntity) t1

In order to solve such a problem, we usually execute native SQL to use SQLQuery interfaces, which will also lose the ability of migration.

SQL conversion tools

With the help of some tools to migrate SQL, we can directly translate the current original SQL (like Oracle SQL) to target SQL (like MySQL SQL). Even in some complex situations like nested subqueries, the conversion can still be achieved.

For example, in https://www.sqlines.com/online:

Select the database type of the original SQL as MySQL, and the SQL to be translated is:

SELECT
O_YEAR ,
SUM(CASEWHENNATION ='CHINA'THENVOLUMEELSE0END) /SUM(VOLUME)ASMKT_SHARE
FROM
(
SELECT
YEAR(O_ORDERDATE)ASO_YEAR,
L_EXTENDEDPRICE * (1- L_DISCOUNT)ASVOLUME,
N2.N_NAMEASNATION
FROM
PART,
SUPPLIER,
…

Select the database type of the target SQL as Oracle, and click the “convert” button, then the original SQL is converted to SQL that can be executed by the target database:

SELECT
O_YEAR ,
SUM(CASEWHENNATION ='CHINA'THENVOLUMEELSE0END) /SUM(VOLUME)ASMKT_SHARE
FROM
(
SELECT
EXTRACT(YEARFROMO_ORDERDATE)ASO_YEAR,
L_EXTENDEDPRICE * (1- L_DISCOUNT)ASVOLUME,
N2.N_NAMEASNATION
FROM
PART,
SUPPLIER,
…

Still, the method has its defects. Such tools are mostly independent applets which only support output of the target SQL on the command line or in the result file, and lack a programmatic interface for integration in various development tools.

esProc SPL

SPL has designed a set of standard SQL query syntax which has many built-in functions (and more are being added) to describe more common operations. And there is a sqltranslate function in SPL, which can translate the standard SQL to SQLs for different databases for the purpose of database migration.

Take this standard SQL for example:

SELECTCLIENT,YEAR(ORDERDATE),SUM(AMOUNT)
,COUNT(ORDERID)
FROMORDERS
GROUPBYCLIENT,YEAR(ORDERDATE)
HAVINGSUM(AMOUNT) >2000

Translate it with .sqltranlate("MYSQL") and the result will be:

SELECTCLIENT,YEAR(ORDERDATE),SUM(AMOUNT)
,COUNT(ORDERID)
FROMORDERS
GROUPBYCLIENT,YEAR(ORDERDATE)
HAVINGSUM(AMOUNT) >2000

Whereas the returned result of using .sqltranslate("ORACLE") will be:

SELECTCLIENT,EXTRACT(YEARFROMORDERDATE),SUM(AMOUNT)
,COUNT(ORDERID)
FROMORDERS
GROUPBYCLIENT,EXTRACT(YEARFROMORDERDATE)
HAVINGSUM(AMOUNT) >2000

As we can see, the standard function is able to correctly select the appropriate functions according to the databases.

In addition, SPL can also handle with those operations not supported in HQL itself like INTERVAL n DAY:

The standard SQL is:

SELECT
ADDDAYS(ORDERDATE,3)
FROM
ORDERS

Translate it to MySQL SQL as:

SELECT
ORDERDATE +INTERVAL3DAY
FROM
ORDERS

Translate it to Oracle SQL as:

SELECT
ORDERDATE + NUMTODSINTERVAL(3,'DAY')
FROM
ORDERS

In order to achieve SQL migration, SPL just translates the functions rather than the statements (copied as they are) in standard SQL so that the standard SQL is able to describe more operations. For example, the following subquery will not change and can be executed normally no matter which database SQL it is translated to.

SELECT
ORDERID,
M
FROM
(
SELECT
ORDERID,
MONTH(ORDERDATE) M
FROM
ORDERS) T1

SPL can be easily integrated with JAVA to enable migration in applications. For further information, please refer to How to Call an SPL Script in Java.

Leave a Reply