1

我有一个 SQL 查询:

select 
    t1.name, t2.address 
from 
    Table1 t1 
inner join 
    Table2 t2 on t1.id = t2.id;

和一张地图:

Map<String,String> map = new HashMap<String,String>();
map.put("testTable", "hive.DB1");
map.put("testTable", "mongo.DB2");

我只想使用此映射将上述查询转换为:

select 
    t1.name, t2.address 
from 
    hive.DB1.`Table1` t1 
inner join 
    mongo.DB2.`Table2` t2 on t1.id = t2.id;

哪种开源 SQL 解析器适合此目的。

4

4 回答 4

0

你真的需要 SQL 解析器吗?为什么不只使用 sed ?

例如一张桌子:

sed -e "s/Table1/hive.DB1.TABLE1/g" C:\test.sql > C:\new.sql

于 2015-08-17T10:06:32.887 回答
0

我使用了 JSqlParser

我从 SQL 查询中提取了表名:

Statement statement = CCJSqlParserUtil.parse("select t1.name, t2.address from Table1 t1 inner join Table2 t2 on t1.id = t2.id;");
Select selectStatement = (Select) statement;
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
List<String> tableList = tablesNamesFinder.getTableList(selectStatement); 

然后我根据地图修改了表名。

于 2016-01-19T08:30:09.227 回答
0

需要一个解析器来仅更改“来自”部分的表引用。某些数据库不接受表达式中的完全限定名称。

此代码使用JSqlParser 0.9.5-SNAPSHOT并打印出修改后的 SQL:

public class SimpleTableReplacer {
    public static void main(String args[]) throws JSQLParserException {
        String sql = "select t1.name, t2.address from Table1 t1 inner join Table2 t2 on t1.id = t2.id";
        Select select = (Select)CCJSqlParserUtil.parse(sql);

        //Replace Table1 with hive.DB1.Table1 and Table2 with mongo.DB2.Table2
        StringBuilder buffer = new StringBuilder();
        ExpressionDeParser expressionDeParser = new ExpressionDeParser();
        SelectDeParser deparser = new SelectDeParser(expressionDeParser,buffer ) {
            @Override
            public void visit(Table tableName) {
                switch (tableName.getName()) {
                    case "Table1": getBuffer().append("hive.DB1.Table1").append(' ').append(tableName.getAlias().getName());break;
                    case "Table2": getBuffer().append("mongo.DB2.Table2").append(' ').append(tableName.getAlias().getName());break;
                    default:
                        super.visit(tableName);
                }
            }
        };
        expressionDeParser.setSelectVisitor(deparser);
        expressionDeParser.setBuffer(buffer);
        select.getSelectBody().accept(deparser);
        //End of value modification

        System.out.println(buffer.toString());
    }
}

结果:SELECT t1.name, t2.address FROM hive.DB1.Table1 t1 INNER JOIN mongo.DB2.Table2 t2 ON t1.id = t2.id.

当然,您可以使用此代码来修改类层次结构本身,这意味着更改表 - 对象名称。

此外,您可以使用 JSqlParser 的新功能为 SQL 的某些部分提供 AST 节点。您可以提取 SQL 中表名的确切位置并在那里进行文本替换。这可以这样编码:

SimpleNode node = (SimpleNode) CCJSqlParserUtil.parseAST(sql);
    node.childrenAccept(new CCJSqlParserDefaultVisitor() {
        @Override
        public Object visit(SimpleNode node, Object data) {
            if (node.getId() == CCJSqlParserTreeConstants.JJTTABLE) {
                System.out.println("table name '" + node.jjtGetValue() + "' found at " + node.jjtGetFirstToken().beginColumn + "-" + node.jjtGetLastToken().endColumn);
            }
            return super.visit(node, data); 
        }
    }, null);
于 2016-01-25T11:22:29.647 回答
0

如果您只需要从 SQL 中提取表名并执行一些逻辑,那么您需要超轻、超快速的库来执行此操作

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

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

并使用以下指令

new TableNameParser(sql).tables()

有关详细信息,请参阅项目

免责声明:我是所有者

于 2016-08-27T05:03:15.140 回答