从 JAVA 中的 sql 语句获取 Table 名称和查询类型

Get Table names and Query types from sql statement in JAVA

我是 jsqlparser 的新手,正在尝试解析 sql 语句以获取 table 名称及其查询类型(在 Java 中)。

例如1.
INSERT INTO Customers (CustomerName, Country) SELECT SupplierName, Country FROM Suppliers WHERE Country='Germany'
从此查询中,我想获取 table 名称 Suppliers 及其查询类型 SELECT.
同样,table名称Suppliers及其查询类型INSERT.

例如2.
UPDATE CUSTOMERS SET SALARY = SALARY * 0.25 WHERE AGE IN (SELECT AGE FROM CUSTOMERS_BKP WHERE AGE >= 27 )
从此查询中,我想获取 table 名称 CUSTOMERS_BKP 及其查询类型 SELECT.
同样,table名称CUSTOMERS及其查询类型UPDATE.

例如3.
UPDATE CUSTOMERS SET SALARY = SALARY * 0.25 WHERE AGE IN (SELECT AGE FROM CUSTOMERS WHERE AGE >= 27 )
(我知道这个查询可以简化,但是我在这里粘贴了示例。)
从此查询中,我想获取 table 名称 CUSTOMERS 及其查询类型 SELECT.
同样,table名称CUSTOMERS及其查询类型UPDATE
注:此处table名称相同,但查询类型不同。

同样,我想为任何复杂的 sql 查询获取 table 名称及其查询类型。

你能帮我解决这个问题吗?

如果您希望我提供任何详细信息,请发表评论。

您提出的问题很棘手,因为 JSqlParsers API 缺少一些扩展点。为了纠正这个问题,我在 github 上创建了一些问题。所以这里有一个小示例来获得这个 运行。输出为:

eg1
INSERT - Customers
SELECT - [Suppliers]
eg2
UPDATE - [CUSTOMERS]
SELECT - [CUSTOMERS_BKP]
eg3
UPDATE - [CUSTOMERS]
SELECT - [CUSTOMERS]

你这里的主要工具是 TablesNamesFinder of JSqlParser,它获取所有 table 的名称一些 SQL。现在我们必须修改它,以单独的方式获取所有 select - 基于语句的 table 名称。这是使用 TablesNamesFinderExt 完成的,它也使用 Insert 语句更正了 subselect 问题。

简而言之,查找器识别 subselects 并设置一个全局标志 inSelect 来填充单独的 mySelectTableList 用于后续调用 visit(Table ...).

import java.util.ArrayList;
import java.util.List;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.SubSelect;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.util.TablesNamesFinder;

public class SimpleSqlParserTableNames2 {

    public static void main(String args[]) throws JSQLParserException {
        System.out.println("eg1");
        Insert insert = (Insert)CCJSqlParserUtil.parse("INSERT INTO Customers (CustomerName, Country) SELECT SupplierName, Country FROM Suppliers WHERE Country='Germany'");
        TablesNamesFinderExt finder = new TablesNamesFinderExt();

        System.out.println("INSERT - " + insert.getTable());
        finder.getTableList(insert.getSelect());
        System.out.println("SELECT - " + finder.getSelectTableList());

        System.out.println("eg2");
        Update update = (Update)CCJSqlParserUtil.parse("UPDATE CUSTOMERS SET SALARY = SALARY * 0.25\n" +
                    "  WHERE AGE IN (SELECT AGE FROM CUSTOMERS_BKP WHERE AGE >= 27 )");
        finder = new TablesNamesFinderExt();
        System.out.println("UPDATE - " + update.getTables());
        finder.getTableList(update);
        System.out.println("SELECT - " + finder.getSelectTableList());

        System.out.println("eg3");
        update = (Update)CCJSqlParserUtil.parse("UPDATE CUSTOMERS SET SALARY = SALARY * 0.25\n" +
                    "WHERE AGE IN (SELECT AGE FROM CUSTOMERS WHERE AGE >= 27 )");
        finder = new TablesNamesFinderExt();
        System.out.println("UPDATE - " + update.getTables());
        finder.getTableList(update);
        System.out.println("SELECT - " + finder.getSelectTableList());
    }

    static class TablesNamesFinderExt extends TablesNamesFinder {
        List<String> mySelectTableList = new ArrayList<>();
        boolean inSelect = true;
        /**
         * To solve JSqlParsers Problem in getting tablenames from subselect using an Insert
         * statement.
         *
         * @param insert
         * @return
         */
        @Override
        public List<String> getTableList(Insert insert) {
            List<String> list = super.getTableList(insert);
            if (insert.getSelect() != null) {
                insert.getSelect().getSelectBody().accept(this);
            }
            return list;
        }

        @Override
        public void visit(SubSelect subSelect) {
            inSelect = true;
            super.visit(subSelect);
        }

        @Override
        public void visit(Table tableName) {
            super.visit(tableName); 
            if (inSelect && !mySelectTableList.contains(tableName.getFullyQualifiedName()))
                mySelectTableList.add(tableName.getFullyQualifiedName());
        }

        public List<String> getSelectTableList() {
            return mySelectTableList;
        }

    }
}

如果你只需要 table 形式的名字 SQLs,你需要一个超轻、超快的库(完整的 SQL 解析器会被杀死)

只需在您的 pom 中添加以下内容

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

并使用以下指令

new TableNameParser(sql).tables()

有关详细信息,请参阅 project

免责声明:我是所有者