7 votes

Bibliothèque d'analyseur SQL pour Java - Récupérer la liste des noms de table présents dans une instruction SQL

Je suis à la recherche d'une bibliothèque SQL qui analysera une déclaration SQL et renverra une sorte de représentation d'objet de la déclaration SQL. Mon objectif principal est en fait de pouvoir analyser la déclaration SQL et de récupérer la liste des noms de table présents dans la déclaration SQL (y compris les sous-requêtes, les jointures et les unions).

Je recherche une bibliothèque gratuite avec une licence adaptée aux entreprises (par exemple, la licence Apache). Je recherche une bibliothèque et non une grammaire SQL. Je ne veux pas construire mon propre analyseur.

Le meilleur que j'ai pu trouver jusqu'à présent était JSQLParser, et l'exemple qu'ils donnent est en fait assez proche de ce que je recherche. Cependant, il échoue à analyser trop de bonnes requêtes (base de données DB2) et j'espère trouver une bibliothèque plus fiable.

6voto

Nicholas Carey Points 24614

Je doute que vous trouviez quelque chose de préécrit que vous puissiez simplement utiliser. Le problème est que le langage SQL ISO/ANSI est une grammaire très compliquée - quelque chose comme plus de 600 règles de production si je me souviens bien.

Le générateur d'analyseur syntaxique de Terence Parr ANTLR (en Java, mais capable de générer des analyseurs dans plusieurs langages cibles) propose plusieurs grammaires SQL, y compris quelques-unes pour PL/SQL, une pour une requête SELECT SQL Server, une pour mySQL et une pour SQL ISO.

Aucune idée de leur degré de complétude/correction/mise à jour.

http://www.antlr.org/grammar/list

5voto

James Points 51

Vous n'avez pas besoin de réinventer la roue, il existe déjà une bibliothèque de parseurs SQL fiables (commerciale, pas gratuite), et cet article montre comment récupérer la liste des noms de table présents dans l'instruction SQL (y compris les sous-requêtes, les joints et les unions) qui est exactement ce que vous recherchez.

http://www.dpriver.com/blog/list-of-demos-illustrate-how-to-use-general-sql-parser/get-columns-and-tables-in-sql-script/

Cette bibliothèque de parseurs SQL prend en charge Oracle, SQL Server, DB2, MySQL, Teradata et ACCESS.

4voto

craftsmannadeem Points 21

Vous avez besoin de la bibliothèque ultra légère et ultra rapide pour extraire les noms de table à partir de SQL (Avis de non-responsabilité : je suis le propriétaire)

Il suffit d'ajouter ce qui suit dans votre pom

 com.github.mnadeem
 sql-table-name-parser
 0.0.1

Et faites ce qui suit

new TableNameParser(sql).tables()

Pour plus de détails, consultez le projet

0voto

Leonardo Herrera Points 4079

Ancienne question, mais je pense que ce projet contient ce dont vous avez besoin :

Projet Data Tools - Outils de développement SQL

Voici la documentation pour le Analyseur de Requêtes SQL.

Aussi, voici un petit programme d'exemple. Je ne suis pas programmeur Java alors utilisez avec précaution.

package org.lala;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;

import org.eclipse.datatools.modelbase.sql.query.QuerySelectStatement;
import org.eclipse.datatools.modelbase.sql.query.QueryStatement;
import org.eclipse.datatools.modelbase.sql.query.TableReference;
import org.eclipse.datatools.modelbase.sql.query.ValueExpressionColumn;
import org.eclipse.datatools.modelbase.sql.query.helper.StatementHelper;
import org.eclipse.datatools.sqltools.parsers.sql.SQLParseErrorInfo;
import org.eclipse.datatools.sqltools.parsers.sql.SQLParserException;
import org.eclipse.datatools.sqltools.parsers.sql.SQLParserInternalException;
import org.eclipse.datatools.sqltools.parsers.sql.query.SQLQueryParseResult;
import org.eclipse.datatools.sqltools.parsers.sql.query.SQLQueryParserManager;
import org.eclipse.datatools.sqltools.parsers.sql.query.SQLQueryParserManagerProvider;

public class SQLTest {

    private static String readFile(String path) throws IOException {
        FileInputStream stream = new FileInputStream(new File(path));
        try {
            FileChannel fc = stream.getChannel();
            MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0,
                    fc.size());
            /* Au lieu d'utiliser la valeur par défaut, passez un décodeur. */
            return Charset.defaultCharset().decode(bb).toString();
        } finally {
            stream.close();
        }
    }

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        try {
            // Créez une instance du gestionnaire d'analyse
            // SQLQueryParserManagerProvider.getInstance().getParserManager
            // renvoie le meilleur SQLQueryParserManager conforme
            // prenant en charge le dialecte SQL de la base de données décrit par
            // les informations sur le produit de base de données données. Dans le code ci-dessous, null est passé
            // pour la base de données et la version
            // auquel cas un analyseur générique est renvoyé

            SQLQueryParserManager parserManager = SQLQueryParserManagerProvider
                    .getInstance().getParserManager("DB2 UDB", "v9.1");
            // Requête d'exemple
            String sql = readFile("c:\\test.sql");
            // Analyser
            SQLQueryParseResult parseResult = parserManager.parseQuery(sql);
            // Obtenir l'objet modèle de requête depuis le résultat
            QueryStatement resultObject = parseResult.getQueryStatement();
            // Obtenez le texte SQL
            String parsedSQL = resultObject.getSQL();
            System.out.println(parsedSQL);

            // Ici, nous avons le code SQL analysé !
            QuerySelectStatement querySelect = (QuerySelectStatement) parseResult
                    .getSQLStatement();
            List columnExprList = StatementHelper
                    .getEffectiveResultColumns(querySelect);
            Iterator columnIt = columnExprList.iterator();
            while (columnIt.hasNext()) {
                ValueExpressionColumn colExpr = (ValueExpressionColumn) columnIt
                        .next();
                // DataType dataType = colExpr.getDataType();
                System.out.println("colonne de résultat effective : "
                        + colExpr.getName());// + " with data type: " +
                                                // dataType.getName());
            }
            List tableList = StatementHelper.getTablesForStatement(resultObject);
            // List tableList = StatementHelper.getTablesForStatement(querySelect);
            for (Object obj : tableList) {
                TableReference t = (TableReference) obj;
                System.out.println(t.getName());
            }
        } catch (SQLParserException spe) {
            // gérer l'erreur de syntaxe
            System.out.println(spe.getMessage());
            @SuppressWarnings("unchecked")
            List syntacticErrors = spe.getErrorInfoList();
            Iterator itr = syntacticErrors.iterator();
            while (itr.hasNext()) {
                SQLParseErrorInfo errorInfo = (SQLParseErrorInfo) itr.next();
                // Exemple d'utilisation de l'objet SQLParseErrorInfo
                // le message d'erreur
                String errorMessage = errorInfo.getParserErrorMessage();
                String expectedText = errorInfo.getExpectedText();
                String errorSourceText = errorInfo.getErrorSourceText();
                // les numéros de ligne d'erreur
                int errorLine = errorInfo.getLineNumberStart();
                int errorColumn = errorInfo.getColumnNumberStart();
                System.err.println("Erreur à la ligne " + errorLine + ", colonne "
                        + errorColumn + ": " + expectedText + " "
                        + errorMessage + " " + errorSourceText);
            }
        } catch (SQLParserInternalException spie) {
            // gérer l'exception
            System.out.println(spie.getMessage());
        }
        System.exit(0);
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X