Java的SQL解析器库 - 检索SQL语句中存在的表名列表

时间:2011-04-06 20:52:29

标签: java sql parsing

我正在寻找一个SQL库,它将解析SQL语句并返回SQL语句的某种Object表示形式。我的主要目标实际上是能够解析SQL语句并检索SQL语句中存在的表名列表(包括子查询,联接和联合)。

我正在寻找一个商业友好的许可证库(例如Apache许可证)。我正在寻找一个库而不是SQL语法。我不想构建自己的解析器。

到目前为止我能找到的最好的是JSQLParser,而他们提供的example实际上非常接近我要找的东西。然而,它无法解析太多好的查询(DB2数据库),我希望找到一个更可靠的库。

4 个答案:

答案 0 :(得分:5)

我怀疑你会找到任何可以使用的预先写好的东西。问题是ISO / ANSI SQL是一个非常复杂的语法 - 类似于600多条生产规则IIRC。

Terence Parr的ANTLR parser generator(Java,但可以使用多种目标语言中的任何一种生成解析器)有几种可用的SQL语法,包括一对用于PL / SQL,一种用于SQL Server SELECT语句,一种用于SQL Server SELECT语句对于mySQL,一个用于ISO SQL。

不知道它们是多么完整/正确/最新。

http://www.antlr.org/grammar/list

答案 1 :(得分:5)

你不需要重新发明轮子,那里已经存在这样一个可靠的SQL解析器库(它是商业的,而不是免费的),本文展示了如何检索SQL语句中存在的表名列表(包括子查询) ,联接和工会)这正是你要找的。

http://www.dpriver.com/blog/list-of-demos-illustrate-how-to-use-general-sql-parser/get-columns-and-tables-in-sql-script/

此SQL解析器库支持Oracle,SQL Server,DB2,MySQL,Teradata和ACCESS。

答案 2 :(得分:3)

你需要超轻,超快的库从SQL中提取表名(免责声明:我是所有者)

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

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

并执行以下操作

new TableNameParser(sql).tables()

有关详细信息,请参阅project

答案 3 :(得分:0)

旧问题,但我认为这个项目包含您需要的内容:

Data Tools Project - SQL Development Tools

以下是SQL Query Parser的文档。

此外,这是一个小样本程序。我不是Java程序员所以要小心使用。

package org.lala;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;

import org.eclipse.datatools.modelbase.sql.query.QuerySelectStatement;
import org.eclipse.datatools.modelbase.sql.query.QueryStatement;
import org.eclipse.datatools.modelbase.sql.query.TableReference;
import org.eclipse.datatools.modelbase.sql.query.ValueExpressionColumn;
import org.eclipse.datatools.modelbase.sql.query.helper.StatementHelper;
import org.eclipse.datatools.sqltools.parsers.sql.SQLParseErrorInfo;
import org.eclipse.datatools.sqltools.parsers.sql.SQLParserException;
import org.eclipse.datatools.sqltools.parsers.sql.SQLParserInternalException;
import org.eclipse.datatools.sqltools.parsers.sql.query.SQLQueryParseResult;
import org.eclipse.datatools.sqltools.parsers.sql.query.SQLQueryParserManager;
import org.eclipse.datatools.sqltools.parsers.sql.query.SQLQueryParserManagerProvider;

public class SQLTest {

    private static String readFile(String path) throws IOException {
        FileInputStream stream = new FileInputStream(new File(path));
        try {
            FileChannel fc = stream.getChannel();
            MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0,
                    fc.size());
            /* Instead of using default, pass in a decoder. */
            return Charset.defaultCharset().decode(bb).toString();
        } finally {
            stream.close();
        }
    }

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        try {
            // Create an instance the Parser Manager
            // SQLQueryParserManagerProvider.getInstance().getParserManager
            // returns the best compliant SQLQueryParserManager
            // supporting the SQL dialect of the database described by the given
            // database product information. In the code below null is passed
            // for both the database and version
            // in which case a generic parser is returned

            SQLQueryParserManager parserManager = SQLQueryParserManagerProvider
                    .getInstance().getParserManager("DB2 UDB", "v9.1");
            // Sample query
            String sql = readFile("c:\\test.sql");
            // Parse
            SQLQueryParseResult parseResult = parserManager.parseQuery(sql);
            // Get the Query Model object from the result
            QueryStatement resultObject = parseResult.getQueryStatement();
            // Get the SQL text
            String parsedSQL = resultObject.getSQL();
            System.out.println(parsedSQL);

            // Here we have the SQL code parsed!
            QuerySelectStatement querySelect = (QuerySelectStatement) parseResult
                    .getSQLStatement();
            List columnExprList = StatementHelper
                    .getEffectiveResultColumns(querySelect);
            Iterator columnIt = columnExprList.iterator();
            while (columnIt.hasNext()) {
                ValueExpressionColumn colExpr = (ValueExpressionColumn) columnIt
                        .next();
                // DataType dataType = colExpr.getDataType();
                System.out.println("effective result column: "
                        + colExpr.getName());// + " with data type: " +
                                                // dataType.getName());
            }
            List tableList = StatementHelper.getTablesForStatement(resultObject);
            // List tableList = StatementHelper.getTablesForStatement(querySelect);
            for (Object obj : tableList) {
                TableReference t = (TableReference) obj;
                System.out.println(t.getName());
            }
        } catch (SQLParserException spe) {
            // handle the syntax error
            System.out.println(spe.getMessage());
            @SuppressWarnings("unchecked")
            List<SQLParseErrorInfo> syntacticErrors = spe.getErrorInfoList();
            Iterator<SQLParseErrorInfo> itr = syntacticErrors.iterator();
            while (itr.hasNext()) {
                SQLParseErrorInfo errorInfo = (SQLParseErrorInfo) itr.next();
                // Example usage of the SQLParseErrorInfo object
                // the error message
                String errorMessage = errorInfo.getParserErrorMessage();
                String expectedText = errorInfo.getExpectedText();
                String errorSourceText = errorInfo.getErrorSourceText();
                // the line numbers of error
                int errorLine = errorInfo.getLineNumberStart();
                int errorColumn = errorInfo.getColumnNumberStart();
                System.err.println("Error in line " + errorLine + ", column "
                        + errorColumn + ": " + expectedText + " "
                        + errorMessage + " " + errorSourceText);
            }
        } catch (SQLParserInternalException spie) {
            // handle the exception
            System.out.println(spie.getMessage());
        }
        System.exit(0);
    }
}