Java获取SQL语句中的表名

SqlParser
placeholder image
admin 发布于:2023-07-28 22:43:03
阅读:loading

前面在使用MyBatis Plus实现的动态schema时《MyBatis Plus应用(五)schema的优雅实现》,当时觉得还是非常优雅的,后来经过旁边的小伙伴介绍又有一种使用拦截器的方式来全局实现动态schema,更加的优雅,于是在略微了解一些实现后发现他是使用Mybatis Plus中的工具类来获取SQL语句中的表名来进行替换,比如在Mapper中的SQL中,所有的用户对象(不限于表、试图、同义词之类的对象)均按实际名称书写,待获取到表名后进行动态替换即可。

1.简单介绍

废话不多说,有兴趣可以去MyBatis Plus的源码中查看,它的内部集成了SQL表名称解析器插件《sql-table-name-parser》,项目地址为:https://github.com/mnadeem/sql-table-name-parser。在此之前也曾经想过此类的需求,在一个SQL语句中获取所有的表名,实际由于SQL的复杂多样性导致这类的需求实现并不容易,而且各种复杂的查询场景,不过这款组件既然被MyBatis Plus集成使用了,想必它的可信度应该还是不错的吧,本次主要针对这个组件进行一些SQL范围内的验证,如果好用的话,这个组件将会在写一些底层组件时显得非常有用途。

在这个组件的Github介绍里,作者还介绍了相关的其它的同类实现,如:“https://github.com/JSQLParser/JSqlParser”、“https://www.sqlparser.com/”、“https://zql.sourceforge.net/”,但是正如作者所说的如果仅仅只是想在SQL中获取所有的表名称而已,那么这个组件无疑是不错的实现,这个小型库将帮助您轻松简洁地做到这一点,组件只有一个类,算上注释、空行、花括号等全部的代码也只有265行不到,所以确实是非常轻量级,最后更新与2016年,已是7年前了,难道非常稳定的吗,注意了star数量有些少,或许是出名度没那么广,容我亲测实践一些案例吧。

2.代码实现

(1)maven坐标

<dependencies>
    <dependency>
        <groupId>com.github.mnadeem</groupId>
        <artifactId>sql-table-name-parser</artifactId>
        <version>0.0.5</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

(2)参考代码

/**
 * 1、简单SQL,带查询条件,得到表名称:[User]
 */
@Test
public void testA1() {
    String sql = "select * from User where 1=1 and id = '123' and id like '%abc%'";
    System.out.println(sql);
    Collection<String> tables = new TableNameParser(sql).tables();
    System.out.println(tables);
}

3.更多测试

--1、简单SQL,带查询条件,得到表名称:[User]
select * from User where 1=1 and id = '123' and id like '%abc%'

--2、简单SQL,带查询条件、带schema,得到表名称:[User]
select * from schema.User where 1=1 and id = '123' and id like '%abc%'

--3、简单SQL,带查询条件、带schema、带数据库名称,得到表名称:[database.dbo.User]
select * from database.dbo.User where 1=1 and id = '123' and id like '%abc%'

--4、简单SQL,带查询条件、中文名称、带别名,得到表名称:[User中文表名称]
select * from User中文表名称 t1 where 1=1 and id = '123' and id like '%abc%'

--5、查询多个表,带查询条件、带别名,得到表名称:[Role, User, User_Role]
select t1.*, t2.* , t3.* from User t1 , User_Role t2 , Role t3 where t1.userId = t2.userId and t2.roleId = t3.roleId and id = ? and t1.id = :id

--6、交叉连接,带查询条件、带别名,得到表名称:[Role, User, User_Role]
select t1.*, t2.* , t3.* from User t1 
left join User_Role t2 on t1.userId = t2.userId 
right join Role t3 on t2.roleId = t3.roleId 
where t1.userId = t2.userId and  and id = ? and t1.id = :id

--7、插入查询语句,带交叉连接,带查询条件、带别名,得到表名称:[Role, User, user_temp, User_Role]
inser into user_temp select t1.*, t2.* , t3.* from User t1 
left join User_Role t2 on t1.userId = t2.userId 
right join Role t3 on t2.roleId = t3.roleId 
where t1.userId = t2.userId and  and id = ? and t1.id = :id

--8、子查询:[Role, User, User_Role]
select t1.*, t2.* , (select max(amount) from Role t3 where t2.roleId = t3.roleId) from User t1 
left join User_Role t2 on t1.userId = t2.userId 
where t1.userId = t2.userId and  and id = ? and t1.id = :id

--9、合并查询:[User2, User1, Usert, User3]
select t1.* from User1 t1 where t1.id = '1' 
union select t2.* from User2 t2 where t2.id = '2' 
union all select t3.* from User3 t3 where t3.id = '3' 
minus select tt.* from Usert tt where tt.id = 'tt'

--10、Oracle merge into 合并更新:[User, Usert]
MERGE INTO User u USING (select * FROM Usert t where t.date >= :date) data ON data.name = u.name 
WHEN MATCHED THEN 
    UPDATE SET col_1 = value_1, col_2 = value_2 
WHEN NOT MATCHED THEN 
    INSERT (col_1,col_2) Values(value_1,value_2)
    
--11、MySQL 数据库带特殊字符 查询:[`chendd-blog`.sys_operationlog_module]
SELECT * FROM `chendd-blog`.sys_operationlog_module

如果还有更多复杂场景的应用,自行验证,比如Oracle的with as的写法等。

4.源码下载

源码下载.txt


 点赞


 发表评论

当前回复:作者

 评论列表


留言区