您好,登錄后才能下訂單哦!
這篇文章給大家介紹java中怎么利用正則表達式獲取sql中的表名,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
/** * 表名解析 */ private final static Pattern P = Pattern .compile("\\s+from\\s+(\\w\\.)?(\\w+)(\\s+|,)(\\w*)|\\s+join\\s+(\\w\\.)?(\\w+)\\s+(\\w\\s)*on", Pattern.CASE_INSENSITIVE); /** * 預處理sql * @param sql sql * @return 處理后sql * @throws Exception 異常 */ private static String preHandleSql(String sql,boolean removeBrackets) throws Exception { // 1. 統一換行符 if (sql.contains("\r\n")) { sql = sql.replaceAll("\r\n", "\n"); } else { sql = sql.replaceAll("\r", "\n"); } // 2. 去掉注釋 String[] rows = sql.split("\n"); StringBuilder sb = new StringBuilder(sql.length()); for (String row : rows) { int indexOfComment = row.indexOf("--"); if (indexOfComment == -1) { sb.append(row).append("\n"); } else { sb.append(row, 0, indexOfComment).append("\n"); } } if (removeBrackets) { sql = removeBrackets(sb); } // 4. 找到第一個select和from,其間的字段即是要查詢的字段列表 return sql.toLowerCase(); } /** * 括號消除:消除括號和括號中包含的內容,非貪心模式 * 例如: * 輸入select (ssss(sadf)sdfsdf(sdssf(sssdf)dsssf)dsslf) as a, (asdfsdf) as b, (asdfsdf) as c from dsfdf * a組 b組 a組 c組 d組 b組 c組 d組 m組 m組 x組 x組 * A組 A組 B組 B組 C組 C組 * 去掉select (去 掉 部 分) as a, (去掉部分) as b, (去掉部分) as c from dsfdf * 輸出select as a, as b, as c from dsfdf * * @param str 消除前的字符串 * @return 消除后的字符串 * @throws Exception 括號不匹配 */ private static String removeBrackets(StringBuilder str) throws Exception { // 1. 收集括號組 List<int[]> bracketsContainer = new ArrayList<>(); collectBrackets(str, 0, bracketsContainer); if (bracketsContainer.isEmpty()) { return str.toString(); } // 2. 消除括號組 StringBuilder newStr = new StringBuilder(str.length()); int groupSize = bracketsContainer.size(); for (int i = 0; i < groupSize; i++) { int[] currentBrackets = bracketsContainer.get(i); if (i == 0) { // 剛到第一組 newStr.append(str.subSequence(0, currentBrackets[0])); } if (i + 1 == groupSize) { // 已到最后一組 newStr.append(str.subSequence(currentBrackets[1] + 1, str.length())); } else { // 未到最后一組 int[] nextBrackets = bracketsContainer.get(i + 1); newStr.append(str.subSequence(currentBrackets[1] + 1, nextBrackets[0])); } } return newStr.toString(); } /** * 收集括號組 * * @param str 消除前的字符串 * @param fromIndex 從哪開始找括號 * @param bracketsContainer 括號組容器 * @throws Exception 括號不匹配、括號嵌套層級過多 */ private static void collectBrackets(StringBuilder str, int fromIndex, List<int[]> bracketsContainer) throws Exception { int firstLeftBracket = str.indexOf("(", fromIndex + 1); int nextLeftBracket = firstLeftBracket; // SQL中不包含左括號時,直接返回 if (firstLeftBracket == -1) { return; } // 括號層級(因為前面已經找到一個左括號,所以初始值為1) int level = 1; int nextRightBracket = str.indexOf(")", fromIndex + 1); if (nextRightBracket == -1) { throw new Exception("括號不匹配"); } // 避免死循環 int maxLevel = 1000; do { int tempLeftBracket = str.indexOf("(", nextLeftBracket + 1); if (tempLeftBracket == -1 || tempLeftBracket > nextRightBracket) { // 找不到下一個左括號或者下一個左括號已屬于下一個括號組 break; } else { nextLeftBracket = tempLeftBracket; } nextRightBracket = str.indexOf(")", nextRightBracket + 1); if (nextRightBracket == -1) { throw new Exception("括號不匹配"); } level++; } while (level <= maxLevel); if (level >= maxLevel) { throw new Exception("括號嵌套層級過多"); } // 把收集到的括號組放入容器 bracketsContainer.add(new int[] {firstLeftBracket, nextRightBracket}); // 遞歸 collectBrackets(str, nextRightBracket, bracketsContainer); } /** * 解析sql中的表名 * @param sql sql * @return 表名 * @throws Exception 異常 */ public static List<String> parseSqlRefTables(String sql) throws Exception { List<String> tableNames = Lists.newArrayList(); String newSql = StringUtils.replaceAll(preHandleSql(sql, false),"\n"," "); Matcher m = p.matcher(newSql); while (m.find()) { tableNames.add(m.group()); } List<String> result = Lists.newArrayList(); for (String tableName : tableNames) { String trimTableName = StringUtils.split(tableName, " ")[1].trim(); if (trimTableName.contains(",")) { result.addAll(Arrays.asList(StringUtils.split(trimTableName, ","))); } else { result.add(trimTableName); } } return result.parallelStream().distinct().collect(Collectors.toList()); } public static void main(String[] args) throws Exception { String data1 = "SELECT dma_t.\"id\", dma_t.\"name\", dma_t.area_border, dma_t.lat_lng, dma_t.level, leak_t.lossf, leak_t.\"day\", leak_t.avgf, leak_t.background_loss, leak_t.nmf, leak_t.normal_use, leak_t.supply FROM la_leak_t leak_t, ( SELECT MAX (dma_id) AS dma_id, MAX (\"day\") AS \"day\" FROM la_leak_t WHERE org_id = ${orgId} GROUP BY dma_id ) recent_t, mdm_dmaarea_m_t dma_t WHERE leak_t.dma_id = recent_t.dma_id AND leak_t.\"day\" = recent_t.\"day\" AND leak_t.dma_id = dma_t.\"id\""; List<String> tableNames = parseSqlRefTables(data1); tableNames.forEach(System.out::println); }
關于java中怎么利用正則表達式獲取sql中的表名就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。