怎样写出可在各种数据库间移植的SQL

简介: 国际标准没有对这些函数做规定,这种 SQL 语句就会和数据库相关而无法移植了,而这些函数在应用开发中还特别常见。Hibernate 能将包括这些函数的标准 HQL 语句转换成不同数据库的 SQL,但 HQL 支持的函数太少,碰到不认识的函数还是要分别注册,这就丧失了可移植性;而且 HQL 能生成的 SQL 本身也比较简单,覆盖面太窄了。

任意的SQL语句都可移植是做不到的。因为各种数据库的功能并不一样,某些数据库的语法在另一种数据库中根本就没有对应的实现机制,这时当然就不可能移植了。

如果我们不用数据库的特殊功能,只在国际标准的范围内,也就是只使用所有数据库的功能交集,其实也相当丰富了,这总该能移植了吧。

基本的情况确实是可以,比如

select * from employee where age>50
select area,sum(amount) from orders group by area

在所有数据库中都能正常执行。

但是,还有很多SQL函数在各种数据库中的写法不一样,特别是字符串和日期相关的,比如

MySQL: year( x )
Oracle: extract( year from x )

国际标准没有对这些函数做规定,这种SQL语句就会和数据库相关而无法移植了,而这些函数在应用开发中还特别常见。

Hibernate能将包括这些函数的标准HQL语句转换成不同数据库的SQL,但HQL支持的函数太少,碰到不认识的函数还是要分别注册,这就丧失了可移植性;而且HQL能生成的SQL本身也比较简单,覆盖面太窄了。

转换SQL语句中的不同的函数,esProc SPL是个更好的解决方案。

esProc SPL是个Java写的开源软件,在这里 https://github.com/SPLWare/esProc。

SPL中有个sqltranslate函数,能够使用了某些“标准”的函数语法书写的SQL翻译成各种数据库的函数。比如:

sql = "select * from Orders where year(OrderDate)=2000"
sql.sqltranslate("MySQL") -> "select * from Orders where year(OrderDate)=2000"
sql.sqltranslate("Oracle") -> "select * from Orders where extract( year from OrderDate )=2000"

sqltranslate中已经预定义了很多数据库中很多函数的写法,比如:

sql = "select * from Orders where ADDDAYS(OrderDate,3)>ShipDate"
sql.sqltranslate("MySQL") -> "select * from Orders where (OrderDate + INTERVAL 3 DAY)>ShipDate"
sql.sqltranslate("Oracle") -> "select * from Orders where (OrderDate + NUMTODSINTERVAL(3, "DAY")>ShipDate"
sql.sqltranslate("DB2") -> "select * from Orders where (OrderDate + 3 DAYS )>ShipDate"

如果碰到了新的函数或新的数据库,esProc还允许程序员自己在配置表中增加。

esProc提供了JDBC接口,很容易被集成进Java应用以实现SQL移植。这里有完整的使用方法:SPL:跨数据库移植 SQL

esProc当然并不是仅仅为了移植SQL而设计的,SPL是功能强大的结构数据处理语言,转换SQL只是SPL顺便实现的一点点小功能而已,SPL更多的作用在于替代SQL实现复杂的查询运算。

当计算需求复杂时我们会用到某些数据库特有的语法或函数。比如Oracle有个KEEP函数可以方便地计算每组的第一条/最后一条记录,其它很多数据库都没有。如果SQL语句中用到了这个函数,就不能再用上面的简单办法移植到其它数据库上了。这种情况下,我们可以只用基本的SQL读取数据,而把更复杂的运算交给SPL来做,SPL是完全不依赖于数据库的,这样写出来的代码就可以继续拥有可移植性了。

select Area, max(Amount) KEEP( dens_rank first order by extract( month from OrderDate) )
from Orders where extract( year from OrderDate)=2000 group by Area

这条Oracle的SQL语句可以用SPL改成这样:





A
B


1
'select OrderDate, Area, Amount from Orders where year(OrderDate)=2000
/读数SQL


2
=A1.sqltranslate("Oracle")
/转成目标数据库的SQL


3
=db.query@x(A2)
/读出数据


4
=A3.group(Area;~.minp@a(month(OrderDate)).max(Amount))
/用SPL计算目标结果


(SPL代码写在格子里,这和普通程序语言很不像,参考这里:写在格子里的程序语言

SPL拥有所有SQL的运算能力(过滤、分组、连接等),并且都是自行实现的(不是翻译成SQL),不依赖于任何数据库,保证这个代码可以在任何数据库上正确执行,就可以移植了。

事实上,SPL提供的运算能力远比SQL更强大丰富(所以也不可能翻译成SQL执行)。有些即使可以用SQL写出来的复杂运算,用SPL也会更简单。比如我们经常举例的任务:计算一支股票最长连续上涨的天数,SQL要写成多层嵌套,冗长且难懂:

    select max(ContinuousDays) from (
        select count(*) ContinuousDays from (
            select sum(UpDownTag) over (order by TradeDate) NoRisingDays from (
                select TradeDate,case when Price>lag(price) over ( order by TradeDate) then 0 else 1 end UpDownTag from Stock ))
        group by NoRisingDays )

SPL提供了更多的基础函数,同样的计算逻辑,写起来要简单得多:

    Stock.sort(TradeDate).group@i(Price<Price[-1]).max(~.len())

这样的代码,是不是既开发简单又容易移植了?

相关文章
|
2月前
|
SQL 存储 关系型数据库
第二篇:关系型数据库的核心概念与 SQL 基础
本篇内容深入浅出地讲解了关系型数据库的核心概念与SQL基础,适合有一定计算机基础的学习者。文章涵盖数据库的基本操作(CRUD)、数据类型、表的创建与管理等内容,并通过实例解析SELECT、INSERT、UPDATE、DELETE等语句的用法。此外,还推荐了多种学习资源与实践建议,帮助读者巩固知识。学完后,你将掌握基础数据库操作,为后续高级学习铺平道路。
129 1
|
3月前
|
SQL 数据库 数据安全/隐私保护
数据库数据恢复——sql server数据库被加密的数据恢复案例
SQL server数据库数据故障: SQL server数据库被加密,无法使用。 数据库MDF、LDF、log日志文件名字被篡改。 数据库备份被加密,文件名字被篡改。
|
22天前
|
SQL 人工智能 关系型数据库
GitHub 热门!MindsDB 破解 AI + 数据库瓶颈,究竟有什么惊艳亮点?只需 SQL 即可实现智能预测
MindsDB 是一款将 AI 能力直接注入数据库的开源工具,支持 MySQL、PostgreSQL 等多种数据库连接,通过 SQL 即可完成模型训练与预测。它提供 AutoML 引擎、LLM 集成、联邦查询等功能,简化 MLOps 流程,实现数据到智能的无缝衔接。项目在 GitHub 上已获 32.4k 星,社区活跃,适用于客户流失预警、推荐系统、情感分析等场景。开发者无需深入模型细节,即可快速构建智能解决方案。项目地址:https://github.com/mindsdb/mindsdb。
111 0
|
3月前
|
SQL 关系型数据库 MySQL
大数据新视界--大数据大厂之MySQL数据库课程设计:MySQL 数据库 SQL 语句调优方法详解(2-1)
本文深入介绍 MySQL 数据库 SQL 语句调优方法。涵盖分析查询执行计划,如使用 EXPLAIN 命令及理解关键指标;优化查询语句结构,包括避免子查询、减少函数使用、合理用索引列及避免 “OR”。还介绍了索引类型知识,如 B 树索引、哈希索引等。结合与 MySQL 数据库课程设计相关文章,强调 SQL 语句调优重要性。为提升数据库性能提供实用方法,适合数据库管理员和开发人员。
|
3月前
|
关系型数据库 MySQL 大数据
大数据新视界--大数据大厂之MySQL 数据库课程设计:MySQL 数据库 SQL 语句调优的进阶策略与实际案例(2-2)
本文延续前篇,深入探讨 MySQL 数据库 SQL 语句调优进阶策略。包括优化索引使用,介绍多种索引类型及避免索引失效等;调整数据库参数,如缓冲池、连接数和日志参数;还有分区表、垂直拆分等其他优化方法。通过实际案例分析展示调优效果。回顾与数据库课程设计相关文章,强调全面认识 MySQL 数据库重要性。为读者提供综合调优指导,确保数据库高效运行。
|
4月前
|
SQL 数据库连接 Linux
数据库编程:在PHP环境下使用SQL Server的方法。
看看你吧,就像一个调皮的小丑鱼在一片广阔的数据库海洋中游弋,一路上吞下大小数据如同海中的珍珠。不管有多少难关,只要记住这个流程,剩下的就只是探索未知的乐趣,沉浸在这个充满挑战的数据库海洋中。
99 16
|
4月前
|
SQL 关系型数据库 MySQL
如何优化SQL查询以提高数据库性能?
这篇文章以生动的比喻介绍了优化SQL查询的重要性及方法。它首先将未优化的SQL查询比作在自助餐厅贪多嚼不烂的行为,强调了只获取必要数据的必要性。接着,文章详细讲解了四种优化策略:**精简选择**(避免使用`SELECT *`)、**专业筛选**(利用`WHERE`缩小范围)、**高效联接**(索引和限制数据量)以及**使用索引**(加速搜索)。此外,还探讨了如何避免N+1查询问题、使用分页限制结果、理解执行计划以及定期维护数据库健康。通过这些技巧,可以显著提升数据库性能,让查询更高效流畅。
|
3月前
|
SQL IDE 关系型数据库
JetBrains DataGrip 2025.1 发布 - 数据库和 SQL 跨平台 IDE
JetBrains DataGrip 2025.1 (macOS, Linux, Windows) - 数据库和 SQL 跨平台 IDE
199 0
|
5月前
|
SQL 数据库
数据库数据恢复—SQL Server报错“错误 823”的数据恢复案例
SQL Server数据库附加数据库过程中比较常见的报错是“错误 823”,附加数据库失败。 如果数据库有备份则只需还原备份即可。但是如果没有备份,备份时间太久,或者其他原因导致备份不可用,那么就需要通过专业手段对数据库进行数据恢复。
|
5月前
|
SQL 存储 关系型数据库
【SQL技术】不同数据库引擎 SQL 优化方案剖析
不同数据库系统(MySQL、PostgreSQL、Doris、Hive)的SQL优化策略。存储引擎特点、SQL执行流程及常见操作(如条件查询、排序、聚合函数)的优化方法。针对各数据库,索引使用、分区裁剪、谓词下推等技术,并提供了具体的SQL示例。通用的SQL调优技巧,如避免使用`COUNT(DISTINCT)`、减少小文件问题、慎重使用`SELECT *`等。通过合理选择和应用这些优化策略,可以显著提升数据库查询性能和系统稳定性。
158 9