您提出的问题是一个棘手的问题,因为 JSqlParsers API 缺少一些扩展点。为了纠正这个问题,我在 github 上创建了一些问题。所以这里有一个小样本来运行它。输出是:
eg1
INSERT - Customers
SELECT - [Suppliers]
eg2
UPDATE - [CUSTOMERS]
SELECT - [CUSTOMERS_BKP]
eg3
UPDATE - [CUSTOMERS]
SELECT - [CUSTOMERS]
您的主要工具是JSqlParser的TablesNamesFinder,它获取某些 SQL 的所有表名。现在我们必须修改它,以单独的方式获取所有基于选择语句的表名。这是使用TablesNamesFinderExt完成的,它也可以使用Insert语句纠正子选择问题。
简而言之,finder 识别子选择并设置全局标志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;
}
}
}