11
votes

Comment citer / échapper à des identificateurs tels que les noms de colonne avec JDBC?

Différents serveurs de base de données utilisent différentes façons de citer et d'échapper à des identificateurs.

E.g. "FOO BAR" vs `foo bar` vs [foo bar] ou" 10 "" "" VS "10 \" ", ou des identificateurs tels que Foobar ou une matrice doivent être cités pour certaines bases de données, mais pas pour les autres.

existe-t-il une méthode API qui effectue la citation / l'échappement correctement pour une connexion de base de données donnée? Ou toute solution alternative?


0 commentaires

3 Réponses :


1
votes

Je pense que la réponse à votre question est que si vous écrivez une application neutre de base de données à l'aide de JDBC, vous devez utiliser des noms neutres de base de données, et non des éléments qui nécessitent une échappée spéciale par fournisseur de base de données.

Il n'y a rien que je connaisse dans le JDBC qui soutient cela. Un produit ORM traitera de telles choses.

Edit: Si vous écrivez un orj, je penserais alors avoir besoin d'une classe de génération SQL séparée pour chaque base de données prise en charge, juste pour gérer les différentes syntaxes impliquées, vous devez donc l'écrire. Vous pouvez certainement regarder le code source des différentes orm open source et voir comment ils le gèrent.


6 commentaires

Bon point sur les noms neutres de la base de données, mais les surprises peuvent encore apparaître (par exemple, un certain identifiant peut ne pas être acceptable dans une autre base de données). Aussi, que si je suis .. réellement écrit un ormes? Cela nécessiterait-il une mise en œuvre distincte de citation / évasion codée à la main pour chaque base de données prise en charge?


Collez sur les règles de nommage de l'identifiant dans la norme SQL. Ceux-ci travailleront n'importe où.


@Paultomblin heh, ouais, la "standard". Il y a beaucoup de flexibilité dans les spécifications et les fournisseurs ajoutez leurs propres mots-clés et leurs mots réservés, qui doivent être cités si l'application doit les utiliser. Je suis d'accord que l'essai de rester à la spécification est l'option la moins douloureuse, mais suce que JDBC n'expose pas un java.sql.connection.quoteIndiifier (...) ou DatabasemetaData.quiécepteur (...) méthode et support SPI, car cela signifie que vous faites toujours la danse du mot réservé. GetIdentifIntifierQuestring ne fait pas le travail, il n'exprime pas les règles de cotation.


@CRAIGringer je modifiais mon commentaire précédent pour "coller à la norme et perdre les mauvaises habitudes que vous avez ramassées à partir de MySQL - c'est une abomination et ce n'est pas SQL". Je n'ai jamais eu à citer un identifiant dans plus de 20 ans de faire SQL sur Oracle, Sybase, Postgres, même Sqllite.


@Paultomblin Heh, utilisateur dédié PostgreSQL ici. Il y a le temps étrange qu'il ait été nécessaire pour moi dans des contextes où l'analyseur de PG se lance de différencier entre un mot clé sans réserve et un identifiant d'utilisateur, mais en général, ce n'est pas trop problématique. Je suis simplement irrité que la spécification JDBC le rend plus difficile qu'il ne devrait être que pour les applications de citer de manière défensive des identifiants, et que le pilote JDBC exposera ses connaissances sur la cotisation correcte. (Qui, sauf si vous êtes MySQL ou MS SQL Server, est ANSI SQL citant quand même)


-1, parce que: (1) il n'existe pas de "noms neutres" dans la réalité - des implémentations spécifiques à la réalité, réservent des mots supplémentaires en plus de la liste commune; (2) SQL Standard définit un moyen de citer les identificateurs, mais des implémentations particulières peuvent avoir une syntaxe alternative pour cela , (3) Ce n'est certainement pas le niveau de l'ORM, beaucoup plus bas (théoriquement, il peut être plus élevé que JDBC, mais ensuite JDBC devrait fournir des détails spécifiques au conducteur (comme ces , mais même ceux-ci peuvent être insuffisants) pour le faire à des leviers plus élevés ; Happinement JDBC maintenant peut le faire par lui-même ).



15
votes

regarder xxx

je ne l'ai jamais utilisé mais ça sonne bien :-)

getExtranamautacters () pourrait aussi être de certains aident


5 commentaires

Pas une solution complète, mais certainement utile!


@Aditsu Je ne comprends pas comment ce n'est pas une solution complète.


@Raven Eh bien, par exemple, cela n'aide pas du tout à s'échapper


@Raven, avec ces méthodes, un programmeur doit toujours faire le travail manuellement.


Depuis Java 9, le Déclaration CODE> L'interface fournit diverses méthodes spécifiques au moteur:

  • EnquoteIdentifier code> pour identificateurs SQL (schéma, table, noms de colonne) li>
  • Enquoteliteral code> pour littéraux strings (par exemple, char, varchar, littéraux texte) li>
  • enquotencharliteral code> pour le personnage national littéraux li> ul> xxx pré>

    Cependant, dans la mesure du possible (c'est-à-dire pour les valeurs des requêtes de CRUD), utilisez des instructions préparées à la place. P>

    Statement stmtFormat = connection.createStatement();
    String query = String.format(
            "SELECT id FROM %s WHERE name = ?", 
            stmtFormat.enquoteIdentifier("table", false);
    PreparedStatement stmt = connection.prepareStatement(query);
    stmt.setString(1, "it's");
    ResultSet resultSet = stmt.executeQuery();
    


1 commentaires

Cela devrait être la réponse acceptée.