java - 从 SQL/HQL Java 解析表名和列名

标签 java oracle parsing jsqlparser

我正在寻找 Java 中的开源 API 来解析 SQL/HQL 查询,以便它为我提供其中使用的列名称和表名称。我尝试使用 JSQLParser,它为我提供了查询中使用的表名称。但我没有看到支持获取查询中使用的列名。有没有其他 API 可以帮助我解决这个问题?我知道 General SQL 解析器,但它似乎是付费的。

这是使用 JSQLParser 的代码片段,它为我提供了查询中的表名称:

Statement statement;
    try
    {
        statement = CCJSqlParserUtil.parse( " SELECT * FROM  ( ( SELECT TBL.ID AS rRowId, TBL.NAME AS name, TBL.DESCRIPTION as description, TBL.TYPE AS type, TBL1.SHORT_NAME AS shortName  FROM ROLE_TBL TBL WHERE ( TBL.TYPE = 'CORE' OR  TBL1.SHORT_NAME = 'TNG' AND  TBL.IS_DELETED <> 1  ) ) MINUS ( SELECT TBL.ID AS rRowId, TBL.NAME AS name, TBL.DESCRIPTION as description, TBL.TYPE AS type, TBL3.SHORT_NAME AS shortName,TBL3.NAME AS tenantName FROM ROLE_TBL TBL INNER JOIN TYPE_ROLE_TBL TBL1 ON TBL.ID=TBL1.ROLE_FK LEFT OUTER JOIN TNT_TBL TBL3 ON TBL3.ID = TBL.TENANT_FK LEFT OUTER JOIN USER_TBL TBL4 ON TBL4.ID = TBL1.USER_FK WHERE ( TBL4.ID =771100 AND  TBL.IS_DELETED <> 1  ) ) ) ORDER BY name ASC" );
        Select selectStatement = (Select) statement;
        TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
        List<String> tableList = tablesNamesFinder.getTableList( selectStatement );
        System.out.println( tableList.size() );
        for( String s : tableList )
            System.out.println( s );
    }
    catch( JSQLParserException e )
    {
        e.printStackTrace();
    }

预先感谢您在这方面的任何帮助。

最佳答案

使用 JSqlParser ( https://github.com/JSQLParser/JSqlParser ) 有多种方法可以实现此目的:

  1. 您也可以通过 TableNamesFinder 来遍历所有列。正如您在结果列表中看到的,TableNamesFinder 不会遍历所有出现的Columns,因为它没有必要。所以这里也必须完成遍历的实现,而我没有完成。

  2. 您可以使用JSqlParser AST - 节点功能来获取所有列。对于特定的产生式,JSqlParser 为解析树生成节点。 就是其中之一。

要完成实现,必须收集所有列并使该列表不同(案例、表格等)

String sql = "SELECT * FROM  ( ( SELECT TBL.ID AS rRowId, TBL.NAME AS name, TBL.DESCRIPTION as description, TBL.TYPE AS type, TBL1.SHORT_NAME AS shortName  FROM ROLE_TBL TBL WHERE ( TBL.TYPE = 'CORE' OR  TBL1.SHORT_NAME = 'TNG' AND  TBL.IS_DELETED <> 1  ) ) MINUS ( SELECT TBL.ID AS rRowId, TBL.NAME AS name, TBL.DESCRIPTION as description, TBL.TYPE AS type, TBL3.SHORT_NAME AS shortName,TBL3.NAME AS tenantName FROM ROLE_TBL TBL INNER JOIN TYPE_ROLE_TBL TBL1 ON TBL.ID=TBL1.ROLE_FK LEFT OUTER JOIN TNT_TBL TBL3 ON TBL3.ID = TBL.TENANT_FK LEFT OUTER JOIN USER_TBL TBL4 ON TBL4.ID = TBL1.USER_FK WHERE ( TBL4.ID =771100 AND  TBL.IS_DELETED <> 1  ) ) ) ORDER BY name ASC";

    System.out.println("using TableNamesFinder to get column names");
    Statement statement = CCJSqlParserUtil.parse(sql);
    Select selectStatement = (Select) statement;
    TablesNamesFinder tablesNamesFinder = new TablesNamesFinder() {
        @Override
        public void visit(Column tableColumn) {
            System.out.println(tableColumn);
        }
    };
    tablesNamesFinder.getTableList(selectStatement);

    System.out.println("-------------------------------------------");
    System.out.println("using ast nodes to get column names");
    SimpleNode node = (SimpleNode) CCJSqlParserUtil.parseAST(sql);

    node.jjtAccept(new CCJSqlParserDefaultVisitor() {
        @Override
        public Object visit(SimpleNode node, Object data) {
            if (node.getId() == CCJSqlParserTreeConstants.JJTCOLUMN) {
                System.out.println(node.jjtGetValue());
                return super.visit(node, data);
            } else {
                return super.visit(node, data);
            }
        }
    }, null);

必须记住,JSqlParser 只是一个解析器。因此,如果不像 (table.column) 中那样指定列表名称,就不可能获取列表名称。为了做到这一点,数据库模式必须可用。如果您查看以下内容,这一点就会变得清楚:

select a from table1, table2

这是一个有效的 SQL。

关于java - 从 SQL/HQL Java 解析表名和列名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40908062/

相关文章:

c++ - 如何使用 Boost::Spirit 解析复杂的字符串文件

parsing - 英语有正式的语法吗?

java - 分解出出现在许多枚举中的方法

oracle - 在 SQL Developer 的单元测试框架中验证 PL/SQL 存储过程 OUT REF CURSOR

parsing - Excel vba解析公式

sql - 从 SQL 中的匹配列派生列的数据

sql - 如何使用 Oracle SQL 中的 SUM 函数生成以下输出?

java - Spring/Hibernate 中的链式 DAO 方法用于延迟初始化

java - 如何对 XML 标签进行分组

java - 使用 GAE(Google App Engine)的免费域名托管