溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java中怎么利用正則表達式獲取sql中的表名

發(fā)布時間:2021-08-03 14:44:52 來源:億速云 閱讀:819 作者:Leah 欄目:編程語言

這篇文章給大家介紹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. 統(tǒng)一換行符
        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("括號不匹配");
        }
        // 避免死循環(huán)
        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中的表名就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI