关于多数据库支持的两种方式
应用软件厂商面临不同的客户需求时,需要支持不同的数据库产品,可是不同的数据库产品之间的SQL相差是巨大。
例如以下的SQL,在不同的数据库中的写法是不一样的。
Oracle:
SELECT * FROM T1, T2 WHERE T1.Id = T2.ParentId (+) ORDER BY T1.Id ASC
)
WHERE ROWNUM <= 1
Sybase:
SELECT * FROM T1 LEFT OUTER JOIN T2 ON T1.Id = T2.ParentId ORDER BY T1.Id ASC
SET ROWCOUNT 0
MySQL:
ORDER BY T1.Id ASC LIMIT 0, 1
MS SQL Server:
DB2 UDB:
ORDER BY T1.Id ASC FETCH FIRST 1 ROW ONLY
支持多数据库是一种困难的事情。支持多数库有两种两种方式。
第一种方式,编写一个数据库抽象层,针对不同的数据库作不同的实现。
第二种方式,使用一种Common SQL,通过一个翻译引擎,将Common SQL翻译为Dialect SQL。
目前很多开放源代码项目,都支持多数据库,通常是使用第一种方式。第一种方式,有一个问题,就是要求程序员对不同数据库都熟悉,这个要对,对大多数程序员而言,太高了。包括著名开源项目的Hibernate,也只是利用到数据库的相当少的一部分功能,没有针对不同数据库的优化选项。不同数据库对Query Hints和Locking Hints的支持都不相同,而Hints又是数据库访问优化的重要办法。这种方式在实现的过程中,会占用相当大一部分的开放实现,而且对程序的可维护性造成影响。
第二种方式,需要定义一套Common SQL,接近SQL-92标准,跟某一种Dialect SQL相似,例如可以跟MS SQL Server的Transact SQL相似。还需要一个翻译引擎,把Common SQL翻译到不同的Dialect SQL,例如DB2的SQL、Oracle的P/L SQL,Microsoft的Transact SQL。这样,大多数程序员只需要了解一种Dialect SQL,如果以Microsoft的Transact SQL为基准定义Common SQL,大多数的程序员都了解SQL Server的Transact SQL,几乎不需要或者只需要很低培训成本,就可以支持多数据库了。
目前国外有一间公司提供有一个SQL翻译的产品,http://www.swissql.com/,但是该公司的翻译引擎做得还很不成熟,BUG很多。国内的也有相应的软件厂商提供有相应的产品,其成熟度要比SwisSQL要高,翻译速度也相当快。