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

时间:2016-12-01 10:23:13

标签: java oracle parsing jsqlparser

我正在寻找Java中的开源API来解析SQL / HQL查询,以便它为我提供列名和它中使用的表名。我尝试使用JSQLParser,它给出了查询中使用的表名。但我没有看到支持获取查询中使用的列名称。有没有其他API可以帮助我这个?我知道通用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();
    }

提前感谢您在这方面的任何帮助。

1 个答案:

答案 0 :(得分:1)

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

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

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

  3. 要完成实施,必须收集所有列并使此列表不同(案例,表格等)

    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。