364 visites

V) Requêtes SQL

mercredi 7 novembre 2012

Version imprimable de cet article Version imprimable

La base citée en exemple, à savoir une gestion de bibliothèque, est un exemple "bateau" récurrent dans l’apprentissage du php/sql.
La gestion de bases plus complexes sera évoquée ultérieurement.

Lecture

Une requête est généralement constituée des 4 éléments suivants.

  • la liste des champs à sélectionner : SELECT champ1, champ2...
  • la liste des tables dans lesquelles récupérer ces champs : FROM table1, table2...
  • une clause de filtrage : WHERE condition
  • une clause de tri et/ou de groupage : ORDER BY/GROUP BY/HAVING

clause SELECT

On y liste les champs à sélectionner dans la base.
Les champs accessibles sont ceux des tables listées dans la clause FROM.
Si des champs de tables différentes ont le même nom, on mettra le nom de leur table suivi du nom du champ, séparés par un point : .
Par exemple select livre.nom,adherent.nom from livre, adherent

Cette requête n’a aucune utilité et va combiner tous les noms d’adhérents de la bibliothèque avec tous les noms de livres.
Le nombre de lignes de résultat sera donc égal au nombre de lignes de la table adhérent multiplié par le nombre de lignes de la table livre.

Il existe des champs spéciaux, qui correspondent à des fonctions, dont :

  • count(nom_champ) qui compte le nombre d’occurrence du champ nom_champ.
  • max(nom_champ) qui retourne la valeur maximale prise par le champ nom_champ
  • min(nom_champ) qui renvoie la valeur minimale
  • avg(champ) qui renvoie la moyenne
  • sum(champ) pour additionner
  • ...
  • distinct(nom_champ) qui sélectionne les valeurs différentes. Par exemple, un count(distinct(nom_champ)) comptera le nombre d’occurrences différentes de nom_champ, donc sans compter les doublons.
  • * est un champ spécial signifiant que l’on prend tous les champs de toutes les tables listées dans la clause FROM.

Dans le cas de champs spéciaux, il sera préférable d’utiliser des alias afin de faciliter la récupération des données, via le mot clé as.
Par exemple
select count(identifiant) as nblivre from livre

clause FROM

On y liste les tables sur lesquelles s’effectuent la sélection, séparées par des virgules.

Bien que la connexion initiale se fasse sur une base unique, on peut faire une sélection sur plusieurs bases en précisant le nom de la base avant celui de la table, les deux étant séparés par un ".".
Il est là aussi possible d’utiliser des alias par le mot clé as
select champ1 from table1 as t1

En cas de sélection sur plusieurs tables, il est préférable d’opérer une jonction sur leurs points communs.
Le cas échéant, le système de gestion va tester la combinaison de chaque ligne de chaque table avec toutes les autres lignes de toutes les tables listées.
Cela multiplie inutilement les tests par la suite.

Il y a plusieurs types de jonctions, mais la plus courante est la jonction interne.

Par exemple, si la table des emprunts fait référence à un utilisateur et un livre, alors on va opérer une jonction sur l’identifiant utilisateur (utilisateur + emprunt) et sur l’identifiant livre (livre + emprunt).

select livre.titre,nom,date_emprunt from livre inner join emprunt on (emprunt.livre=livre.id) inner join adherent on (emprunt.adherent=adherent.id)

A noter, une sous-requête peut servir de table. Cela consommera plus de ressources, mais parfois c’est le seul moyen.

Pour reprendre l’exemple de la bibliothèque, on pourrait compter le nombre de fois par personne où les livres ont été rendus en retard, puis prendre ceux dont le nombre de fois .... est supérieur ou égal à 3.

On fera alors quelque chose comme

  • SELECT nom_personne from (SELECT count(*) as nombre_retard,nom_personne from emprunts inner join personnes on (emprunts.id_personne=personnes.id_personnes) where (date_rendu-date_pret)>=X group by id_personne) where nombre_retard>=3

Cela est également faisable avec une clause HAVING, ce qui allégerait la requête.

clause WHERE

La clause WHERE permet d’effectuer un filtre sur les lignes créées par les clauses SELECT ... FROM ..

Ce filtre est exécuté après le calcul de ces lignes. C’est pourquoi il est préférable de passer par une jonction dans la clause FROM lorsque cela est possible pour effectuer une correspondance entre deux (ou plus) tables.

Ce filtre est constitué d’une ou plusieurs conditions

  • séparées par les mots-clés :
  • "and" (et) si toutes les conditions doivent être remplies
  • "or" (ou) si une seule des conditions suffit
  • segmentées par des parenthèses "(" et ")" si besoin.

Une condition peut être :

  • comparaison de deux champs avec signes "=", ">", ">=", "<", "<=" et "<>" (différence) ainsi que le mot-clé LIKE, pour comparaison de texte
  • présence ou nom de la valeur d’un champ dans une sous-requête grâce au mot clé "in" ou "not in".

Par exemple, les personnes qui n’ont pas emprunté de livres sont celles qui ne sont pas présentes dans la table des emprunts.

SELECT nom_personne FROM personnes WHERE id_personne NOT IN (select distinct(id_personne) from emprunts);

Pour le texte, la comparaison avec le mot-clé LIKE s’effectue généralement sur une partie du contenu : WHERE champ LIKE '%valeur%' filtrera les lignes dont le champ texte "champ" contient (entre autre) le texte "valeur".

ORDER BY/GROUP BY/HAVING

  • ORDER BY est une clause de tri.

On peut trier selon un ou deux champs, dans l’ordre ascendant (ASC) ou descendant (DESC)
Par exemple, tri sur une date, du plus ancien au plus récent donc de la plus petite date à la plus grande = ASC

select ... order by champ1 ASC

  • GROUP BY est une clause de regroupement selon une égalité d’un champ.

Par exemple, pour avoir le nombre d’emprunts de chaque personne :
select count(*) as nbemprunts, id_personne from emprunts GROUP BY id_personne

  • HAVING permet de filtrer sur les fonctions d’agrégat (et non de "simples" champs contrairement à la clause WHERE).

Par exemple, pour récupérer les personnes ayant plus de 50 emprunts.
select nom, count(emprunts.date_emprunt) as nbemprunts from personne inner join emprunts on (personne.id_personne=emprunts.id_personne) group by emprunts.id_personne having count(emprunts.date_emprunt)>=50

LIMIT

Cette clause permet de limiter le nombre de résultats renvoyés.
Cela peut être utile pour un système de pagination.

select ..... LIMIT debut,nombre
où début correspond à la première réponse récupérée (le tableau des réponses commence à zéro) et nombre... le nombre de réponses à prendre.

Par exemple, pour récupérer les 10 plus gros emprunteurs (non pas sur leur masse pondérale mais sur leur nombre d’emprunts) :
SELECT nbemprunts,nom_personne from (select max(count(*)) as nbemprunts, id_personne from emprunts group by id_personne) t1 inner join personne on (t1.id_personne=personne.id_personne) order by nbemprunts DESC LIMIT 0,10

Modification de la base de données

Mise à jour

La clause principale de la requête n’est plus SELECT mais UPDATE.

Les clauses secondaires (de filtre et choix de table) sont toujours valables.

On met à jour un champ d’une ou plusieurs lignes d’une table, en fonction de la valeur d’autres champs de ces mêmes lignes (ou pas).

Comme toujours, on commence par mettre la requête SQL dans une variable chaîne de caractères.
$reku="update operation_type set nom=\"$nom\" where id=$id" ;

puis on l’exécute, tout simplement
$resu=mysql_query($reku) ;

la syntaxe de la requête est de type UPDATE table SET CHAMP=nouvelle_valeur WHERE condition

Suppression

La clause principale de la requête n’est plus SELECT mais DELETE.

Les clauses secondaires (de filtre et choix de table) sont toujours valables.

On efface des lignes d’une table en fonction de la valeur de champs ce ces mêmes lignes.

Comme toujours, on commence par mettre la requête SQL dans une variable chaîne de caractères.
$rekd1="delete from operation_type where parent=$id" ;

puis on l’exécute, tout simplement
$resd1=mysql_query($rekd1) ;

la syntaxe de la requête est de type DELETE FROM table WHERE condition

Répondre à cet article

Total 121372 visites depuis 2149 jours | Site réalisé par Vader[FR] | SPIP | | Plan du site | Suivre la vie du site RSS 2.0 | contact mail