SQL方言:传统关系型数据库下的方言对比

前言:

技术多元化是一个趋势,多语言并存,多数据库适配,多环境兼容><

场景:

当从SQL Server数据库迁移到MySql数据库或者Oracle数据库,甚至国产化数据库,不同数据库之间可以自定义切换?

此时,在不同版本类型的数据库下,各自独有的SQL方言,并不能同时在多个数据库中共用,那如何能够做到尽可能复用,毕竟你不能改变ta,那只有适配。而如何适配又能够做到最小改造量?

SQL方言对比:

这里,我们来看看各大数据库厂商下分页SQL的写法,其中pageNo表示页码数,pageSize表示一页包含的记录数,

SQL Server (row_number 关键字)

select top pageSize * 
from (select row_number() 
over(order by id asc) as rownumber,* 
from yx_test) temp_row
where rownumber>((pageNo-1)*pageSize);

例:分页查询第二页,每页展示10条记录
select top 10 * 
from (select row_number() 
over(order by id asc) as rownumber,* 
from yx_test) temp_row
where rownumber > 10;

MySql (limit 关键字分页-结合mybatis-xml写法)

limit (pageNo-1),pageSize

<select id="pageRecords" resultMap="BaseResultMap" databaseId="mysql">
      select
      <include refid="base_column">
          <property name="alias" value="T."/>
      </include>
      from Test T
      <where>
          <if test="null != idCard and '' != idCard">
              and T.ID_CARD = #{idCard, jdbcType=VARCHAR}
          </if>
          and t.CANCEL_FLAG = '0'
      </where>
      order by T.ID DESC
      limit #{start},#{end}
</select>

Oracle (rownum 伪列分页-结合mybatis-xml写法)

    <select id="pageRecords" resultMap="BaseResultMap" databaseId="oracle">
            select * from (select row_.*, rownum rownum_
            from (select t.* from (select
            <include refid="base_column">
                <property name="alias" value="T."/>
            </include>
            from yx_test T
            <where>
                <if test="null != idCard and '' != idCard">
                    and T.ID_CARD = #{idCard, jdbcType=VARCHAR}
                </if>
                and t.CANCEL_FLAG = '0'
            </where>
            order by T.ID DESC)t where rownum <![CDATA[<=]]> #{end}) row_)
            where rownum_ <![CDATA[>=]]> #{start}
    </select>

上述,仅仅给出了部分的分页SQL方言写法,还有,像我们常用的一些日期函数,更多请参考->多数据库适配 | 记一次数据源从Oracle到MySQL兼容切换历程

MySql (date()函数、date_sub()函数)

例:删除一周前创建的历史数据,仅保留最近一周的日志数据
delete from yx_test_log
           where id <= (
           select id from (
           select max(id) as id from yx_test_log
	   where date(create_time) <= date(date_sub(now(), interval 7 day))
           ) as a);

SQL Server (DateDiff()函数、getdate()函数)

例:删除一周前创建的历史数据,仅保留最近一周的日志数据
delete from yx_test_log where DateDiff(dd,create_time,getdate()) > #{day}

SQL方言适配:

通过对比各大DBMS数据库厂商,由此可见各自的函数并不能相互兼容。这里,我们就来给一些多数据库适配的一些CASE:

自定义指定 databaseId:

1685351762480.jpg

自定义SQL拦截器:

image.png

最后:

不论是基于ORM关系映射框架去构造SQL,还是基于Mybatis插件的思想->根据当前数据库databaseId,拦截SQL,加入各自数据库的SQL方言函数兼容,我们需要能够做到支持业务灵活配置-不同环境可走不同配置,并且可插拔式-在需要时开启。

诚然,在技术多元化的今天,多语言并存,多数据库适配,多环境兼容,这已是趋势!这无不都告诉我们各位开发者,在书写SQL不仅需要规范,比较生僻且独有的SQL语法尽量规避,CRUD等操作都尽量基于框架去开发。尤其是在BI报表业务中,很多需要对数据层面的过滤、组装、转换其实可以根据实际情况放在业务代码层面去处理->或许Lambda表达式值得一试。

猜你喜欢

转载自blog.csdn.net/yxd179/article/details/131479890
今日推荐