[SQL] Do's and don't : les bonnes pratiques en SQL

1 message   •   Page 1 sur 1
Avatar de l’utilisateur
Modérateur PHPfrance
Modérateur PHPfrance | 10410 Messages

14 mars 2007, 12:50

Voici une petite liste de conseils pratiques, de choses à faire ou au contraire ne pas faire lorsque vous écrivez une requête en SQL :

* Majuscules et Minuscules :
Le SQL n'est pas sensible à la casse (je parle uniquement de la syntaxe de la requête, pas des valeurs en base). Une bonne habitude à prendre est donc de mettre en majuscule les mots clés SQL et de garder en minuscule les noms de champ ou de table. La requête est ainsi beaucoup plus claire et lisible :

Code : Tout sélectionner

SELECT champ1, champ2 FROM table1 WHERE champ1 = 1 AND champ2 = 'xxx'
En ce qui concerne les valeurs en revanche, la chaine 'xxx' est différente de la chaine 'XXX'. Notez toutefois que MySQL est également insensible à la casse et que ces deux chaines seront considérées comme identique. Ce n'est pas le cas des autres bases de données.


* Apostrophes (') ou Guillemets (") ? :
En SQL les chaines de caractères sont délimitées par des apostrophes. MySQL tolère les guillemets, mais pas les autres bases de données pour qui elles ont une signification totalement différente. Prenez donc l'habitude d'utiliser les premières :

Code : Tout sélectionner

SELECT ... FROM ... WHERE champ = 'xxx';
Attention : n'utilisez les apostrophes que pour des champs dont le type en base est une chaine de caractère (varchar, text, date, etc.) pas pour les nombres (int, float, ...). MySQL les tolère autour des nombres et fera la conversion pour adapter la donnée que vous lui envoyez au type de champ que vous lui avez spécifié. Evitez-lui des conversions inutiles en lui passant directement le nombre :)


* Quotes Inversées (`) :
Cette syntaxe est propre à MySQL. Elle permet de protéger les noms des champs et des tables afin que le parseur SQL ne les confonde pas avec des mots clés réservés SQL. En effet, dans MySQL, on peut nommer un champ "FROM" et une table "SELECT" et faire la requête suivante :

Code : Tout sélectionner

"SELECT `from` FROM `select` WHERE `from` = 'select'
Pas terrible n'est ce pas ? :)
Il vaut évidemment mieux choisir des libellés qui ne sont pas des mots clés protégés. Il n'y a ainsi aucune confusion possible pour le parseur, et vous n'aurez pas de mauvaise surprise lorsque vous développerez ou migrerez sur un autre SGBD.

Attention : il est très tentant d'utiliser le libellé 'date' pour désigner un champ de ce type. Je rappelle que 'date' est un mot clé SQL (tout comme 'varchar', 'int'). Préférez donc un nom du style 'date_insertion' ou 'date_update' qui sera également plus précis quant à la nature des données.


* Eviter le " SELECT * " :
Précisez le nom des champs que vous souhaitez récupérer pour éviter les risques d'erreur (lorsqu'un même nom se trouve dans plusieurs table), avoir des requêtes plus optimisées et un code php facilement maintenable.
Lister les champs en détail permet d'une part de ne récupérer que ce qui est nécessaire (inutile de ramener 12 champs mediumtext de 500Ko quand tout ce qui nous interesse c'est un id et un titre). De plus, le nombre de colonnes et l'ordre des champs pouvant avoir un impact sur le traitement qui va suivre (si l'on utilise mysql_fetch_row() par exemple), il est préférable de pouvoir les maîtriser.
Cela permet aussi de connaître les noms des colonnes retournés par la requête, et donc le noms des index utilisables.


* Compter les enregistrements
La fonction COUNT(*) qui permet de compter le nombre d'enregistrements d'une table, est la commande SQL la plus optimisée. Elle retourne forcément un résultat et ne ramène pas d'enregistrements inutiles. Si vous souhaitez uniquement connaître le nombre d'enregistrements que ramène une requête, et que vous n'avez pas besoin de récupérer le contenu de ceux-ci préferez le COUNT(*) à un "SELECT * " qui va inutilement charger toutes les valeurs pour ensuite compter le nombre d'enregistrements retournés avec mysql_num_rows() .


* Retour à la ligne
Le langage SQL permet d'insérer des retours à la ligne dans vos instructions, n'hésitez pas à les utiliser pour aérer vos requêtes et augmenter leur lisibilité :

Code : Tout sélectionner

SELECT ... FROM ... WHERE ... ORDER BY ...
* LIKE ou "=" ?
Tout dépend de ce que vous voulez faire. Si vous connaissez la valeur exacte de la chaine que vous recherchez, le "=" s'impose. Le LIKE n'a d'intérêt que si vous ignorez une partie de la chaine recherchée. Il s'utilise alors avec des jokers (caractère "%") qui remplacent la ou les parties de la chaine que vous ne connaissez pas.

Attention : les recherches de chaines commençant par un joker (LIKE '%xxx') sont assez gourmandes en ressources et seront plus longues à exécuter, à utiliser avec parcimonie !


* Utiliser des alias
Les alias permettent de renommer certaines colonnes et ainsi pouvoir les utiliser facilement dans un GROUP BY, ORDER BY ou HAVING (mais pas dans le WHERE) de la requête SQL, ou même en PHP avec la fonction mysql_fetch_assoc()

Code : Tout sélectionner

SELECT champ1, champ2 + champ3 AS cumul, SUM(champ4) AS total FROM table WHERE ... ORDER BY cumul
On peut également donner un alias à une table. Cela permet, lorsque deux tables ont des noms de champ identique (dans le cas de clés étrangères par exemple) de préfixer les champs afin de les distinguer sans ambiguité.

Code : Tout sélectionner

SELECT s.champ1, e.champ1, e.champ2 FROM societe s, employe e WHERE s.champ1 = e.champ1
"S" et "E" sont des alias désignant respectivement les tables "société" et "employé" qui permettent au SGBD de savoir dans quelle table il doit aller chercher le "champ1" spécifié.


* GROUP BY
La clause GROUP BY permet de regrouper par champs les données retournés par une requête. Elle ne s'utilise que lorsque vous faites appel à des fonctions de regroupements (telles que AVG(), COUNT(), SUM() ...). Elle doit porter sur l'ensemble des champs présents dans le select qui n'ont pas été groupés par une fonction.

Code : Tout sélectionner

SELECT idForum, nomForum, COUNT(idSujet) AS nbSujet, MAX(idMessage) AS lastPostId FROM ... WHERE ... GROUP BY idForum, nomForum
MySQL a étendu l'utilisation de la clause GROUP BY et tolère l'omission des champs spécifiés dans le select si ceux-ci sont uniques pour le groupe. Ainsi, dans l'exemple précédent, il serait possible avec MySQL de faire un "GROUP BY idForum", le nom du Forum étant unique pour chaque id du Forum. En SQL standard, vous devez obligatoirement ajouter la colonne nomForum à la clause GROUP BY.

Attention : N'utilisez pas cette spécificité de MySQL si les colonnes que vous omettez dans le GROUP BY ne sont pas unique dans le groupe, vous auriez des résultats inattendus.
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

1 message   •   Page 1 sur 1