Получить имена таблиц и типы запросов из оператора SQL в JAVA

Я новичок в jsqlparser и пытаюсь проанализировать оператор sql, чтобы получить имя таблицы и ее тип запроса (в Java).

Для eg1.
INSERT INTO Customers (CustomerName, Country) SELECT SupplierName, Country FROM Suppliers WHERE Country='Germany'
Из этого запроса я хочу получить имя таблицы Suppliers и его тип запроса SELECT,
Аналогично, имя таблицы Suppliers и его тип запросаINSERT,

Для eg2.
UPDATE CUSTOMERS SET SALARY = SALARY * 0.25 WHERE AGE IN (SELECT AGE FROM CUSTOMERS_BKP WHERE AGE >= 27 )
Из этого запроса я хочу получить имя таблицы CUSTOMERS_BKP и его тип запроса SELECT,
Аналогично, имя таблицы CUSTOMERS и его тип запросаUPDATE,

Для eg3.
UPDATE CUSTOMERS SET SALARY = SALARY * 0.25 WHERE AGE IN (SELECT AGE FROM CUSTOMERS WHERE AGE >= 27 )
(Я знал, что этот запрос может быть упрощен, но, например, я вставил сюда.)
Из этого запроса я хочу получить имя таблицы CUSTOMERS и его тип запроса SELECT,
Аналогично, имя таблицы CUSTOMERS и его тип запросаUPDATE,
Примечание: здесь имена таблиц одинаковы, но имеют разные типы запросов.

Точно так же я хочу получить имя таблицы и ее тип запроса для любого сложного запроса SQL.

Не могли бы вы помочь мне в этом?

Пожалуйста, прокомментируйте, если вы хотите, чтобы я предоставил какие-либо детали.

2 ответа

Решение

Заданный вами вопрос сложен, потому что в API JSqlParsers отсутствуют некоторые точки расширения для этого. Чтобы исправить это, я создал несколько проблем на github. Итак, вот небольшой пример, чтобы запустить это. Выход:

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

Ваш основной инструмент здесь - TablesNamesFinder из JSqlParser, который получает все имена таблиц некоторого SQL. Теперь нам нужно изменить его, чтобы раздельно получить все имена таблиц на основе операторов выбора. Это делается с помощью TablesNamesFinderExt, который также исправляет проблему подвыбора, используя оператор Insert.

Короче говоря, искатель распознает подвыборы и устанавливает глобальный флаг inSelect, чтобы заполнить отдельный mySelectTableList для последующих вызовов посещения (Таблица...).

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;
        }

    }
}

Если вам просто нужны имена таблиц из SQL, вам нужен сверхлегкий, сверхбыстрый libray (полный синтаксический анализатор SQL был бы слишком убит)

Просто добавьте следующее в свой pom

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

И используйте следующую инструкцию

new TableNameParser(sql).tables()

Для более подробной информации обратитесь к проекту

Отказ от ответственности: я владелец

Другие вопросы по тегам