Quels sont les avantages de l'utilisation de générateurs de requêtes SQL?


17

Y a-t-il des avantages à utiliser un générateur de requêtes, plutôt que d'utiliser du SQL brut?

Par exemple

$q->select('*')
  ->from('posts')
  ->innerJoin('terms', 'post_id')
  ->where(...)

contre:

SELECT * FROM posts WHERE ...

Je vois que de nombreux frameworks utilisent ce type de couches d'abstraction, mais je ne comprends pas les avantages.


Je pense que l'on devrait écrire des requêtes contre des vues et non contre des tables. J'ai tendance à penser que les personnes qui utilisent des générateurs de requêtes n'ont pas tendance à écrire des vues ou à demander aux administrateurs de base de données de les créer pour eux. Ce faisant, ils ne tirent pas parti de toute la puissance du SGBDR.
Tulains Córdova

1
@ user61852: À part éventuellement une certaine sécurité et un filtrage gratuit, que peuvent fournir les requêtes sur les vues que les requêtes sur les tables ne peuvent pas fournir également?
Robert Harvey

4
@RobertHarvey La même chose que la programmation d'interfaces au lieu de classes concrètes. Découplage et flexibilité. La conception des tables sous-jacentes pourrait être aléatoire tant que le «contrat», la vue, reste «simulant» les mêmes colonnes que jamais.
Tulains Córdova

@ user61852 Assez juste.
Robert Harvey

@RobertHarvey J'ai transformé cela en une réponse.
Tulains Córdova

Réponses:


20

L'abstraction de l'écriture du SQL via un framework bien, les résumés.

Écrire SQL à la main n'est pas si mal en soi, mais vous commencez à avoir des problèmes avec l'échappement et la désinfection et cela se transforme en désordre. Une couche d'abstraction peut s'occuper de tout cela en arrière-plan, permettant à votre code d'être propre et exempt de beaucoup d' mysql_real_escape_string()appels ou similaires.

De plus, cela permet de prendre en compte différents dialectes de SQL. Toutes les bases de données ne sont pas construites de la même manière et il peut y avoir des variations dans les mots clés ou la syntaxe d'une certaine fonctionnalité. L'utilisation d'une couche d'abstraction permet de générer dynamiquement la syntaxe correcte pour votre variante.

Bien qu'une couche d'abstraction puisse introduire un impact sur les performances, elle est généralement négligeable par rapport à la propreté et la robustesse du code que vous recevez en retour.


1
Je ne pense pas que les dialectes SQL diffèrent entre les SGBDR. Et en PHP, il y a PDO qui fait la désinfection pour u
Anna K.

12
Les dialectes SQL diffèrent, c'est pourquoi ils sont appelés dialectes. Quant à PDO, la couche d'abstraction nous cache simplement ce gâchis.

@GlennNelson Anna signifiait n'importe quel dialecte, utilisant différents backends (PSQL / MySQL / SQLite ...)
Izkata

2
@AnnaK. Le dialecte peut ne pas changer, mais parfois les caractéristiques sont différentes. Par exemple, MySQL (avec le moteur MyISAM) ne prend pas en charge les restrictions de clé étrangère, contrairement à PostGres. Soit le dialecte devra gérer une telle chose lui-même (ce qui nécessite une connaissance complète de la structure des données, comme le fait l'ORM de Django), soit, plus probablement: l'utilisateur doit être intelligent sur la façon dont il l'utilise, ce qui pourrait lui donner un aspect comme le dialecte change, selon les circonstances.
Izkata

1
+1 pour laisser un outil bien construit faire votre évasion et désinfection pour vous. S'il peut également valider, c'est encore mieux.
Dan Ray

11

Les créateurs de requêtes sont une haine pour moi, à tel point que j'ai écrit mon propre Framework (Apeel) pour éviter de les utiliser!

Si vous utilisez PDO (ce que je vous recommande vraiment de faire), la santisation de l'entrée est gérée pour vous.

Comme quelqu'un l'a dit, bien qu'ils facilitent le basculement entre les bases de données, ils ont tendance à prendre en charge la fonctionnalité "Dénominateur commun le plus bas" et ne prennent pas en charge ou ont de moins bonnes performances pour les fonctionnalités plus avancées.

Je développe des systèmes avec des bases de données depuis environ 1986 et, pendant tout ce temps, j'ai rarement rencontré une entreprise qui modifiait la base de données qu'elle utilise autrement que lorsqu'elle avait besoin de meilleures performances. Si vous modifiez des bases de données pour de meilleures performances, il est beaucoup plus logique de passer votre temps à optimiser manuellement vos requêtes pour tirer le meilleur parti de la nouvelle base de données plutôt que de prendre le coup d'un générateur de requêtes pour des raisons de simplicité.

Le temps passé à maîtriser les qwirks d'un générateur de requêtes (puis à ré-apprendre lorsque vous passez à un meilleur) serait beaucoup plus productif pour apprendre à optimiser votre SQL.

Quoi qu'il en soit, c'est pourquoi NE PAS en utiliser un, certaines personnes les aiment cependant.


4

Théoriquement? Oui. Glenn Nelson a expliqué comment ils vous aideront souvent. (Si c'est un bon générateur de requêtes).

En pratique? Ne respecte pas toujours la théorie et pourrait en fait causer des problèmes. Supposons que vous utilisez un générateur de requêtes contre certains SGBD populaires et que tout est peachy. Ensuite, un client vous demande de frapper son SGBD qui a des bizarreries que votre générateur de requêtes choisi ne peut tout simplement pas gérer. (J'ai rencontré ce problème lorsque j'ai dû travailler avec une ancienne version de Pervasive.)

MAIS! Ce que vous devez absolument faire est de séparer la couche d'accès aux données et de vous assurer que vous pouvez en remplacer une nouvelle si nécessaire. De cette façon, vous pouvez utiliser ce générateur de requêtes sympa avec toutes les fonctionnalités, mais si vous devez en connecter un nouveau qui utilise ce pseudo-sql étrange pour la base de données en question.


2
Est-ce que quelque chose comme la situation de bizarrerie DB ne devrait pas être résolu à l'avance? Je veux dire découvrir quelle base de données votre client utilise et choisir les cadres / bibliothèques appropriés en conséquence est quelque chose qui doit être géré avant d'écrire une seule ligne de code.

3

Je pense que l'avantage pratique et quotidien du générateur de requêtes est la réutilisation du code et la capacité de suivre le principe DRY.

Avec le générateur de requêtes, vous pouvez placer des parties répétitives de SQL dans des méthodes. Et puis utilisez ces méthodes pour composer du SQL complexe. Un exemple serait par exemple la clause JOIN réutilisable:

function joinTaskWithClient($queryBuilder) {
    $queryBuilder->join('task', 'contract', 'task.contract_id = contract.id')
                 ->join('contract', 'client', 'contract.client_id = client.id');
}

Donc, l'utilisation serait:

$queryBuilder->select('client.name')
             ->from('client')
             ->where('task.id=:task')->setParameter('task', 42);
joinTaskWithClient($queryBuilder);

Comme vous pouvez le remarquer - avec le générateur de requêtes, vous pouvez ajouter des parties de SQL dans n'importe quel ordre (par exemple, une partie JOIN après WHERE one) contrairement au cas où vous collectez manuellement la chaîne SQL. En outre, vous pouvez lire sur le modèle de générateur pour voir son intention et ses avantages.

Je suis d'accord concernant l'évasion et la désinfection, mais cela pourrait également être réalisé sans constructeur de requêtes. En ce qui concerne l'abstraction de type DB / dialecte - c'est un avantage assez théorique et discutable, rarement utilisé dans la pratique.


Pour moi, c'est aussi un avantage majeur. Un autre est qu'avec l'abstraction dans les méthodes, vous pouvez donner aux méthodes des noms plus significatifs et même créer un langage spécifique au domaine à partir de cela, ce qui rend l'intention beaucoup plus claire. Vous pouvez également transmettre le générateur de requêtes et laisser différents composants lui ajouter les bits spécifiques. Enfin et surtout, j'ai trouvé que cela me permettait d'encapsuler des modèles derrière des méthodes nommées de manière significative .... J'ai trouvé certains constructeurs de requêtes où l'ajout de colonnes stupidement écrasait les précédentes, ce qui rend beaucoup de ce qui est ci-dessus inutile ...
malte

2

je fournirai une réponse basée sur le fichier Lisez-moi d'un constructeur SQL personnalisé ( Dialect )

(le texte en clair suit, les références spécifiques à la bibliothèque ont été supprimées)

Exigences

  1. Prise en charge de plusieurs fournisseurs de bases de données (par exemple, MySQL, PostgreSQL, SQLite, MS SQL / SQL Server, Oracle, DB2, ..)
  2. Extension facile à de nouvelles bases de données (de préférence via un paramètre de configuration indépendant de l'implémentation)
  3. Modularité et transférabilité indépendante de l'implémentation
  4. API flexible et intuitive

traits

  1. modèles basés sur la grammaire
  2. prise en charge des vues personnalisées personnalisées
  3. abstraction, modularité et transférabilité de db
  4. modèles préparés
  5. fuite de données

je pense que les caractéristiques et les exigences ci-dessus esquissent les raisons pour lesquelles on utiliserait un générateur d'abstraction SQL

La plupart des fonctionnalités ci-dessus sont prises en charge par la plupart des constructeurs SQL (bien que je ne pense pas que toutes les listes soient prises en charge, à ma connaissance)

Exemples de cas d'utilisation:

  1. Plateforme CMS capable de fonctionner (sans changement de code sous-jacent) avec plusieurs fournisseurs de bases de données
  2. Code d'application personnalisé où le fournisseur de base de données est susceptible de changer et / ou les schémas dB sont dynamiques (cela signifie que de nombreuses requêtes ne peuvent pas être codées en dur mais doivent encore être suffisamment abstraites pour que le code soit robuste aux changements)
  3. Prototypage avec une autre base de données que celle utilisée en production (nécessiterait une base de code en double au moins pour une partie du code)
  4. Le code d'application n'est pas étroitement couplé à un fournisseur de base de données spécifique et / ou à une implémentation (même au sein d'un même fournisseur de base de données, par exemple différentes versions de fournisseur de base de données), il est donc plus robuste, flexible et modulaire
  5. De nombreux cas habituels de requêtes et d'échappements de données sont gérés par le framework lui-même et, généralement, c'est à la fois optimal et plus rapide

Enfin, un exemple de cas d'utilisation que j'avais. je construisais une application où le schéma de base de données sous-jacent (wordpress) n'était pas bien adapté au type de requêtes de données qui devaient être faites, en plus de certaines tables WP (par exemple des publications) devaient être utilisées (donc avoir des tables complètement nouvelles pour toutes les données d'application n'était pas une option).

Dans ce cas, la possibilité de créer une application de type MVC dans laquelle le modèle pourrait être interrogé par des conditions personnalisées / dynamiques a rendu le codage en dur des requêtes presque un cauchemar. Imaginez que vous deviez prendre en charge l'interrogation de 2 à 3 tables avec des jointures et le filtrage des conditions pour voir quelle table associer à quoi et également prendre en charge les alias requis, etc.

De toute évidence, il s'agissait d'un cas d'utilisation d'abstraction de requête et, plus encore, il avait besoin (ou du moins grandement bénéficié) d'avoir la possibilité de définir des vues personnalisées personnalisées (un conglomérat de tables jointes comme s'il s'agissait d'une table personnalisée adaptée au modèle) . Ensuite, c'était beaucoup plus facile, plus propre, modulaire et flexible. Dans un autre aspect, l'application (code) a également utilisé la couche d'abstraction de requête comme outil de normalisation (schéma db) . Comme certains le disent, c'était à l'épreuve du temps .

Si, demain, les gens décident qu'ils ont besoin d'options ou de données supplémentaires, il est très facile d'ajouter cela au modèle en quelques lignes et de bien fonctionner. De plus, si, demain, les gens décident qu'ils ne veulent plus utiliser wordpress (comme l'application est couplée de manière lâche à wordpress en tant que plugin), il est également relativement facile de changer ( juste la définition de) les modèles en quelques lignes de code pour s'adapter au nouveau schéma.

Tu vois ce que je veux dire?


1

Assez souvent, certains des arguments pour ces requêtes sont en effet des valeurs plutôt que des constantes. Maintenant, beaucoup d'entre eux proviennent essentiellement de publications de formulaires utilisateur. Et il existe donc de nombreuses possibilités d'attaques par injection SQL. La formation des requêtes par nature nécessite donc une validation complète.

Maintenant, cela ne veut pas dire que nous ne faisons pas confiance au développeur, mais la formation de la requête peut être facile, mais la répétition de toutes les vérifications de validation possibles partout peut simplement impliquer que vous pourriez parfois manquer accidentellement ou modifier la requête mais ne modifiez pas la requête mais ne la modifiez pas 't mettre à jour le contrôle de validation. Certains débutants pourraient même connaître tous les dangers de passer à côté de cela. Par conséquent, l'abstraction du générateur de requêtes est tout à fait essentielle.


0

Je pensais que les générateurs de requêtes étaient des applications GUI qui vous permettaient de sélectionner des tables et de créer des jointures graphiquement tout en générant du SQL sous le capot, mais maintenant je comprends que vous appelez également les générateurs de requêtes les API qui fournissent un moyen de ne pas avoir à créer de requêtes SQL pures , donc abstenez-vous des différences potentielles dans les saveurs SQL.

L'utilisation de tels constructeurs de requêtes est une bonne chose, mais j'ai tendance à penser que les personnes qui comptent beaucoup sur eux ne demandent généralement pas aux administrateurs de base de données: "hé, c'est une requête que j'utilise beaucoup, veuillez en créer une vue".

Ne vous méprenez pas.

Je pense que vous devriez écrire des requêtes sur des vues et non sur des tables. Pas pour la sécurité ou le filtrage, qui sont de bonnes raisons, mais pour la même raison, vous devez coder contre les interfaces et non contre les classes concrètes: le découplage. Les vues sont comme des "contrats", de la même manière que les interfaces sont des "contrats" dans la POO. Vous pouvez modifier les tables sous-jacentes, mais tant que vous forcez les vues à afficher le même «contrat» aux programmeurs, le code ne doit pas se rompre.

Encore une fois, ne vous méprenez pas, vous pouvez utiliser des générateurs de requêtes pour interroger les vues, mais de nombreuses vues existent comme un processus de maduration qui est le produit d'avoir à écrire des requêtes et de demander à votre administrateur de base de données: "mec, crée ceci, s'il te plaît" .

Ai-je tort de penser qu'en n'écrivant pas de requêtes, vous ne détectez pas la nécessité de créer certaines vues?

Une autre chose qui me préoccupe est que les programmeurs débutants ne maîtrisent pas le SQL, l'une des plus belles technologies créées par l'homme, en n'ayant pas à le faire.


Que diriez-vous d'un DBA qui dit: "Cette requête fonctionne mal, travaillons ensemble et améliorons-la." Cela a peut-être bien fonctionné au début, mais il rencontre maintenant des problèmes. Si tout ce qui est nécessaire est un index, pourquoi déranger le développeur avec ça?
JeffO

C'est une situation totalement différente et c'est parfaitement OK.
Tulains Córdova

J'ai juste envie d'impliquer le DBA chaque fois qu'une requête extrait un seul enregistrement d'une table ou d'une vue crée un goulot d'étranglement dans le processus de développement.
JeffO
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.