很强大的插件sqlPaser 可以解析sql语句的很多东西,我主要用来解析表名和列名
官网如下:http://www.sqlparser.com/
官网上面有一些现有的例子,这个大家可以自己去官网里找一下。
sqlPaser支持很多数据库,常见的数据库都支持。
sql语句解析出表名和列名
List<String> tables = new ArrayList<>();
List<String> columns = new ArrayList<>();
TGSqlParser sqlparser = null;
switch (StorageTypeEnum.getEnumByType(param.getSqlType())){
case ORACLE:
sqlparser = new TGSqlParser(EDbVendor.dbvoracle);
break;
case MYSQL:
sqlparser = new TGSqlParser(EDbVendor.dbvmysql);
break;
case GREENPLUM:
sqlparser = new TGSqlParser(EDbVendor.dbvgreenplum);
break;
case HIVE:
sqlparser = new TGSqlParser(EDbVendor.dbvhive);
break;
case PRESTO:
sqlparser = new TGSqlParser(EDbVendor.dbvpostgresql);
break;
case LIBRA:
sqlparser = new TGSqlParser(EDbVendor.dbvpostgresql);
break;
}
String sql = "";
sqlparser.sqltext = sql;
int ret = sqlparser.parse(); //sql语句是否合法
TCustomSqlStatement sqlStatement = null;
if (ret == 0){ //sql语句合法则获得解析对象
sqlStatement = (TCustomSqlStatement)sqlparser.sqlstatements.get(0);
}
if(ret != 0){
return Response.buildErrorResult("sql 不合法");
}
analyzeStmt(sqlStatement,tables,columns);
解析方法:
private void analyzeStmt(TCustomSqlStatement stmt,List<String> tables,List<String> columns){
for(int i=0;i<stmt.tables.size();i++){
if (stmt.tables.getTable(i).isBaseTable())
{
if ( (stmt.dbvendor == EDbVendor.dbvmssql)
&&( (stmt.tables.getTable(i).getFullName().equalsIgnoreCase("deleted"))
||(stmt.tables.getTable(i).getFullName().equalsIgnoreCase("inserted"))
)
){
continue;
}
tables.add(stmt.tables.getTable(i).getFullName());
for (int j=0;j<stmt.tables.getTable(i).getObjectNameReferences().size();j++){
columns.add(stmt.tables.getTable(i).getObjectNameReferences().getObjectName(j).getColumnNameOnly());
}
}
}
for (int i=0;i<stmt.getStatements().size();i++){
analyzeStmt(stmt.getStatements().get(i),tables,columns);
}
}
测试类:
@Test
public void test(){
SqlCheckParam param = new SqlCheckParam();
param.setSql("CREATE TABLE \"tb_STUDENTS\" ( \"ID\" NUMBER, \"co_USERNAME\" VARCHAR(10), \"co_USERAGE\" NUMBER)");
List<RegularExpressionParam> regulars = new ArrayList<>();
RegularExpressionParam tableRegular = new RegularExpressionParam();
RegularExpressionParam columnRegular = new RegularExpressionParam();
tableRegular.setType(1); //表名
tableRegular.setRegular(".*tb_.*");
columnRegular.setType(2); //列名
columnRegular.setRegular(".*co_.*");
regulars.add(tableRegular);
regulars.add(columnRegular);
log.info(JSON.toJSON(regulars).toString());
param.setRegulars(regulars);
param.setSqlType(7); //oracle
log.info(JSON.toJSON(param).toString());
log.info(sqlStandardCheckServiceImpl.sqlCheck(param).toString());
}
整个的功能大概是完成了一下几点:
- 获得sql语句的表名列名
- 根据正则表达式去匹配表名和列名,查看是否有问题。