Base de données (suite)
III) SGBD
1) Généralités
Certains logiciels ont comme fonctionnalité première le stockage et le repérage d'information. Ces logiciels permettent la création, la gestion et l'exploitation d'ensembles structurés de données appelés bases de données. On les appelle donc SGBD, pour systèmes de gestion de bases de données.
Certains logiciels ont comme fonctionnalité première le stockage et le repérage d'information. Ces logiciels permettent la création, la gestion et l'exploitation d'ensembles structurés de données appelés bases de données. On les appelle donc SGBD, pour systèmes de gestion de bases de données.
Pour décrire la structure des bases données qu'un SGBD peut créer, gérer et exploiter, de même que les différentes opérations qu'on peut effectuer sur ces bases, on utilise un modèle de données. Un modèle de données est donc un modèle abstrait représentant les deux aspects suivants d'un SGBD: la structure des bases données qu'il peut créer, gérer et exploiter, et les opérations de stockage et de repérage qu'on peut effectuer sur ces bases.
Deux des plus importants modèles de données sont le modèle textuel et le modèle relationnel. Le premier est ainsi appelé parce qu'il est particulièrement bien adapté aux données textuelles, c'est-à-dire composées surtout des phrases ou des mots. Le second est ainsi appelé parce qu'il est basé sur le concept mathématique de relation. Comme on peut s'y attendre, un SGBD permettant de créer, gérer et exploiter des bases de données selon le modèle textuel s'appelle un SGBD textuel; un SGBD permettant la création, la gestion et l'exploitation de bases de données selon le modèle relationnel est dit relationnel. Le modèle textuel est parfois aussi appelé « fichier plat ».
Deux des plus importants modèles de données sont le modèle textuel et le modèle relationnel. Le premier est ainsi appelé parce qu'il est particulièrement bien adapté aux données textuelles, c'est-à-dire composées surtout des phrases ou des mots. Le second est ainsi appelé parce qu'il est basé sur le concept mathématique de relation. Comme on peut s'y attendre, un SGBD permettant de créer, gérer et exploiter des bases de données selon le modèle textuel s'appelle un SGBD textuel; un SGBD permettant la création, la gestion et l'exploitation de bases de données selon le modèle relationnel est dit relationnel. Le modèle textuel est parfois aussi appelé « fichier plat ».
2) Modèle relationnel
2.1 Généralités
Nous allons ici nous concentrer sur la présentation du modèle relationnel, correspondant aux SGBD relationnels. MySQL, Oracle, Access et SQL Server sont des exemples de SGBD relationnels. Le modèle relationnel est un modèle abstrait et, à ce titre, il n'est parfaitement conforme à aucun SGBD relationnel spécifique. Cependant, ses caractéristiques générales se retrouvent dans tous les SGBD relationnels, et il peut donc servir de point de référence pour l'étude ou l'apprentissage de SGBD relationnels réels.
Nous allons ici nous concentrer sur la présentation du modèle relationnel, correspondant aux SGBD relationnels. MySQL, Oracle, Access et SQL Server sont des exemples de SGBD relationnels. Le modèle relationnel est un modèle abstrait et, à ce titre, il n'est parfaitement conforme à aucun SGBD relationnel spécifique. Cependant, ses caractéristiques générales se retrouvent dans tous les SGBD relationnels, et il peut donc servir de point de référence pour l'étude ou l'apprentissage de SGBD relationnels réels.
Les aspects d'un SGBD, comme par exemple son interface avec l'usager, ou la façon précise de déclencher telle ou telle opération, ne font pas partie de son modèle de données. De même, les caractéristiques reliées à l'utilisation concrète du SGBD, comme le type de matériel requis, ou la quantité de mémoire requise, sont entièrement exclues du modèle de données. En conséquence, les caractéristiques des SGBD relationnels qui sont modélisées par le modèle relationnel se résument à la structure des informations traitées, et aux opérations de recherche que l'on peut effectuer sur les informations stockées. Elles n'incluent pas les autres fonctionnalités, comme par exemple la production de rapports imprimés.
2.2 Scénario type d'utilisation d'un SGBD
Le scénario type d'utilisation d'un SGBD est le suivant:
On crée d'abord une base de données en donnant au SGBD une description de la structure désirée pour celle-ci. Cette description s'appelle la définition de la base dans le SGBD. Une fois la création faite, on utilise le SGBD pour alimenter la base, c'est-à-dire y placer de l'information. Une fois cela fait, on soumet au SGBD des requêtes de recherche, dont le but est d'extraire certaines parties de l'information contenue dans la base. La possibilité de faire de telles recherches est la finalité même d'une base de données.
Le scénario type d'utilisation d'un SGBD est le suivant:
On crée d'abord une base de données en donnant au SGBD une description de la structure désirée pour celle-ci. Cette description s'appelle la définition de la base dans le SGBD. Une fois la création faite, on utilise le SGBD pour alimenter la base, c'est-à-dire y placer de l'information. Une fois cela fait, on soumet au SGBD des requêtes de recherche, dont le but est d'extraire certaines parties de l'information contenue dans la base. La possibilité de faire de telles recherches est la finalité même d'une base de données.
La création d'une base de données n'a lieu en général qu'une seule fois. Autrement dit, on ne donne qu'une fois la définition de la base au SGBD (bien que, dans plusieurs SGBD réels, on puisse modifier la définition d'une base même après sa création). Typiquement, la création d'une base de données est effectuée par un professionnel responsable de la base, alors que son alimentation et la recherche sont faites par des usagers de différentes catégories. L'alimentation ne se fait pas nécessairement en une seule opération, mais peut être effectuée sur une longue période, et dans le cas des bases qu'il faut constamment maintenir à jour, elle n'arrête jamais.
2.3 La structure élémentaire: la table de données
Les deux modèles (textuel et relationnel) partagent une même structure élémentaire de données: la table de données. Une table de données est une structure rectangulaire à deux dimensions, constituée de lignes et de colonnes. Les lignes de la table sont appelées les fiches de la table; les colonnes sont appelées ses champs.
Les deux modèles (textuel et relationnel) partagent une même structure élémentaire de données: la table de données. Une table de données est une structure rectangulaire à deux dimensions, constituée de lignes et de colonnes. Les lignes de la table sont appelées les fiches de la table; les colonnes sont appelées ses champs.
Une table doit avoir au moins un champ (c'est-à-dire au moins une colonne); chaque champ doit avoir un nom distinct. Le nombre de champs d'une table et leur nom sont fixés à la création de la table et ne varient pas au cours de sa vie. Le nombre de fiches est zéro à la création de la table, mais change au cours de la vie de la table, selon les opérations de mise-à-jour effectuées sur la table.
Il n'y a aucune limite supérieure à priori sur le nombre de lignes ou sur le nombre de colonnes d'une table (étant bien entendu que ces nombres sont toujours finis). La table elle-même doit aussi avoir un nom.
Il n'y a aucune limite supérieure à priori sur le nombre de lignes ou sur le nombre de colonnes d'une table (étant bien entendu que ces nombres sont toujours finis). La table elle-même doit aussi avoir un nom.
On peut visualiser une table de données comme un tableau. On place les noms de champ en en-têtes des colonnes et le nom de la table au-dessus de la ligne d'en-têtes. Voici une table de données sur des personnes-contacts présentée sous cette forme:
Table de données Contacts
Numéro | Prénom | Nom | Téléphone |
1 | Jeanne | Tremblay | 555-1212 |
2 | Roger | Drapeau | 555-1213 |
3 | Bernard | Larue | 555-1214 |
Dans cet exemple, la table s'appelle "Contacts" et elle possède quatre champs ("Numéro", "Prénom", "Nom" et "Téléphone") et trois fiches.
À l'intersection d'une ligne et d'une colonne se trouve une cellule. Une fiche est donc constituée de plusieurs cellules, une pour chacun des champs de la table. On appellera d'ailleurs souvent, par un léger abus de langage, ces différentes cellules les champs de la fiche.
Intuitivement, un champ d'une fiche est un certain élément d'information concernant l'« objet » auquel se rapporte la fiche. Par exemple, le champ "AU" d'une fiche de livre pourrait correspondre à l'élément d'information « auteur » pour ce livre. Le champ "Téléphone" d'une fiche de personne pourrait correspondre au numéro de téléphone de la personne.
À l'intersection d'une ligne et d'une colonne se trouve une cellule. Une fiche est donc constituée de plusieurs cellules, une pour chacun des champs de la table. On appellera d'ailleurs souvent, par un léger abus de langage, ces différentes cellules les champs de la fiche.
Intuitivement, un champ d'une fiche est un certain élément d'information concernant l'« objet » auquel se rapporte la fiche. Par exemple, le champ "AU" d'une fiche de livre pourrait correspondre à l'élément d'information « auteur » pour ce livre. Le champ "Téléphone" d'une fiche de personne pourrait correspondre au numéro de téléphone de la personne.
3. Hypothèses sur les SGBD
Concrètement, les opérations de mise-à-jour sur les tables de données (ajout, retrait, modification de fiches) s'effectueront via une interface dépendante du SGBD spécifique utilisé. Cette interface pourrait par exemple utiliser une présentation graphique de la table, comme dans l'exemple ci-dessus, et permettre la saisie et la manipulation d'information directement dans celle-ci. Dans la présente discussion du modèle, cependant, ces détails nous importent peu. Nous supposons simplement qu'il est possible, après la création de la table, d'effectuer toutes les opérations requises pour que le contenu de la table devienne (ou demeure) conforme à la réalité qu'elle représente (par exemple, une collection de livres ou une liste de contacts).
Également, nous verrons plus loin que le concepteur d'une base de données peut appliquer des restrictions sur les contenus admissibles d'une table de données. Nous adopterons des notations nous permettant d'indiquer ces restrictions dans la représentation visuelle de nos exemples, mais la façon concrète de spécifier ces restrictions dans l'interface de définition d'une table dépendra du SGBD spécifique utilisé et nous importe peu; l'important est qu'il y aura toujours une façon de le faire.
Concernant ces restrictions, nous tenons aussi pour acquis qu'un SGBD refusera d'enregistrer une fiche dont le contenu contreviendrait aux restrictions, peu importe comment ce refus se manifeste concrètement dans l'interface-utilisateur. L'important est que le système refuse d'enregistrer des données non conformes aux restrictions applicables. Nous tenons donc pour acquis qu'il est impossible de nous retrouver dans une situation où le contenu enregistré dans une table de données ne respecte pas les restrictions applicables. (En réalité, certains SGBD—notamment Access—acceptent de modifier les restrictions applicables à une table de données même après que l'on ait commencé à saisir des données. Dans ce cas, il serait possible de se retrouver avec des données non conformes aux restrictions. Nous ne tenons pas compte ici de ces cas pathologiques.)
Il sera aussi parfois question de transformations appliquées automatiquement à certaines données d'une table au moment où elles sont saisies. Nous tenons pour acquis que ces transformations sont « incontournables », c'est-à-dire qu'il est impossible que des données se retrouvent dans une table sans avoir préalablement subi ces transformations.
4) Opérations sur les bases de données relationnelles
Rappelons qu'un modèle de données est un modèle abstrait représentant les deux aspects suivants d'une classe de SGBD:
la structure des données que ces SGBD peuvent traiter et les opérations de stockage et de repérage que l'on peut effectuer sur ces données structurées. Jusqu'ici, à part formuler quelques hypothèses sur la saisie des données (par exemple, l'hypothèse que le SGBD refuse d'enregistrer dans une table toute fiche dont le contenu d'au moins un champ contrevient aux restrictions spécifiées dans la définition de la table), nous n'avons traité que de l'aspect structurel du modèle relationnel. (En fait, nous avons pratiquement terminé ce volet; il ne nous manque qu'un élément, les conditions de validité, que nous gardons pour plus tard, puisqu'il est basé sur les expressions du langage de recherche, qu'il est beaucoup plus naturel de présenter en même temps que le langage de recherche lui-même.) Nous passons maintenant aux opérations que l'on peut effectuer sur les données structurées selon ce que nous avons présenté jusqu'ici du modèle relationnel.
la structure des données que ces SGBD peuvent traiter et les opérations de stockage et de repérage que l'on peut effectuer sur ces données structurées. Jusqu'ici, à part formuler quelques hypothèses sur la saisie des données (par exemple, l'hypothèse que le SGBD refuse d'enregistrer dans une table toute fiche dont le contenu d'au moins un champ contrevient aux restrictions spécifiées dans la définition de la table), nous n'avons traité que de l'aspect structurel du modèle relationnel. (En fait, nous avons pratiquement terminé ce volet; il ne nous manque qu'un élément, les conditions de validité, que nous gardons pour plus tard, puisqu'il est basé sur les expressions du langage de recherche, qu'il est beaucoup plus naturel de présenter en même temps que le langage de recherche lui-même.) Nous passons maintenant aux opérations que l'on peut effectuer sur les données structurées selon ce que nous avons présenté jusqu'ici du modèle relationnel.
Quels genres d'opérations sont possibles sur une base de données relationnelle?
On distingue en général les opérations de recherche (ou extraction), qui produisent de l'information à partir de ce qui est stocké dans les différentes tables de la base, mais sans rien y modifier, et les opérations de modification, qui ont le potentiel de changer quelque chose dans le contenu de la base. Nous ne parlons ici que d'opérations de recherche.
On distingue en général les opérations de recherche (ou extraction), qui produisent de l'information à partir de ce qui est stocké dans les différentes tables de la base, mais sans rien y modifier, et les opérations de modification, qui ont le potentiel de changer quelque chose dans le contenu de la base. Nous ne parlons ici que d'opérations de recherche.
Dans le modèle relationnel, les opérations de recherche s'expriment le plus souvent dans un langage (normalisé) appelé SQL (pour Structured Query Language). Il faut savoir que SQL inclut d'autres volets que les opérations de recherche. En particulier, il inclut non seulement des opérations de modification, mais même des opérations qui permettent de définir un base de données et ses différentes tables.
5) Langage SQL
Globalement, SQL peut être découpé comme suit:
Langage de définition de données (ou DDL, pour Data Definition Language)
Langage de manipulation de données (ou DML, pour Data Manipulation Language)
Opérations de recherche
Opérations de modification
Nous ne parlons donc ici que d'une petite partie de SQL (les opérations de recherche). Nous justifions notre approche par le fait que, dans le monde des bases de données documentaires, les opérations de recherche sont énormément plus fréquentes que les opérations de modification (qui se résument essentiellement à la saisie de nouvelles informations, à la correction d'erreurs et à un élagage périodique).
Langage de définition de données (ou DDL, pour Data Definition Language)
Langage de manipulation de données (ou DML, pour Data Manipulation Language)
Opérations de recherche
Opérations de modification
Nous ne parlons donc ici que d'une petite partie de SQL (les opérations de recherche). Nous justifions notre approche par le fait que, dans le monde des bases de données documentaires, les opérations de recherche sont énormément plus fréquentes que les opérations de modification (qui se résument essentiellement à la saisie de nouvelles informations, à la correction d'erreurs et à un élagage périodique).
Le scénario de travail sur une base de données relationnelle est le suivant:
On démarre (ou ouvre) d'abord une « session de travail » auprès d'un SGBD, en identifiant sur quelle base on désire travailler au cours de la session (on ne peut travailler que sur une base à la fois au cours de la même session). Une fois la session ouverte, on soumet au SGBD une première requête. Le SGBD exécute la requête et nous informe du résultat. On peut alors soumettre une deuxième requête, dont le SGBD nous transmet le résultat, et ainsi de suite, jusqu'à ce que l'on mette fin à (ou ferme) la session.
Bien qu'il existe souvent plusieurs façons d'exprimer les requêtes que l'on soumet au SGBD, la plus universelle est de les exprimer dans le langage SQL, et nous ne parlerons que de celle-là.
On démarre (ou ouvre) d'abord une « session de travail » auprès d'un SGBD, en identifiant sur quelle base on désire travailler au cours de la session (on ne peut travailler que sur une base à la fois au cours de la même session). Une fois la session ouverte, on soumet au SGBD une première requête. Le SGBD exécute la requête et nous informe du résultat. On peut alors soumettre une deuxième requête, dont le SGBD nous transmet le résultat, et ainsi de suite, jusqu'à ce que l'on mette fin à (ou ferme) la session.
Bien qu'il existe souvent plusieurs façons d'exprimer les requêtes que l'on soumet au SGBD, la plus universelle est de les exprimer dans le langage SQL, et nous ne parlerons que de celle-là.
5.1 SELECT restreints: la syntaxe
Les requêtes SQL qui correspondent aux opérations de recherche sont appelées des « requêtes SELECT » (ou simplement des « SELECT »), pour la simple raison qu'elles débutent toutes par le mot « SELECT ». (Nous écrirons tous les mots-clés du langage SQL en majuscules, mais la plupart des SGBD les acceptent sans égard à la casse.)
Les requêtes SELECT incarnent toute la puissance du modèle relationnel et leur forme peut être très variée. Nous n'en verrons pour débuter qu'une forme très spécifique, qui nous permettra cependant de discuter d'aspects fondamentaux de la recherche d'information dans une base de données relationnelle. Nous appellerons cette forme de requêtes les SELECT restreints.
Les requêtes SQL qui correspondent aux opérations de recherche sont appelées des « requêtes SELECT » (ou simplement des « SELECT »), pour la simple raison qu'elles débutent toutes par le mot « SELECT ». (Nous écrirons tous les mots-clés du langage SQL en majuscules, mais la plupart des SGBD les acceptent sans égard à la casse.)
Les requêtes SELECT incarnent toute la puissance du modèle relationnel et leur forme peut être très variée. Nous n'en verrons pour débuter qu'une forme très spécifique, qui nous permettra cependant de discuter d'aspects fondamentaux de la recherche d'information dans une base de données relationnelle. Nous appellerons cette forme de requêtes les SELECT restreints.
Voici la forme générale d'un SELECT restreint:
Donnons tout de suite un exemple; la requête suivante est un SELECT restreint qui pourrait être exécuté sur la base "Contacts15" ci-dessus:
SELECT * FROM nom-de-table WHERE nom-de-champ opérateur-de-comparaison constante ;
SELECT * FROM Personnes3 WHERE Nom = "drapeau" ;
Mentionnons d'emblée que les sauts de ligne et le retrait des différentes lignes importent peu dans une requête SQL (pas seulement dans les SELECT restreints); ces éléments peuvent donc être utilisés librement pour améliorer la lisibilité des requêtes.Tout ce qu'on a souligné, à la fois dans la forme générale et dans l'exemple, est fixe et doit figurer tel quel dans un SELECT restreint. Le reste de la forme générale, à savoir les symboles nom-de-table, nom-de-champ, opérateur-de-comparaison et constante, doivent être remplacés pour obtenir un SELECT restreint valide. Le découpage suivant met en évidence la correspondance entre la forme générale et l'exemple:
5.2 La forme générale:
Les encadrés de même numéro correspondent. On constate que le nom-de-table est "Personne3", que le nom-de-champ est "Nom", que l'opérateur-de-comparaison est "=" et que la constante est "drapeau". Les éléments variables de la forme générale (nom-de-table, nom-de-champ, opérateur-de-comparaison et constante) ne peuvent évidemment pas être substitués n'importe comment: L'élément nom-de-table doit être remplacé par le nom d'une des tables de la base de données. L'élément nom-de-champ doit être remplacé par le nom d'un des champs de la table identifiée par nom-de-table. L'élément opérateur-de-comparaison doit être remplacé par l'un des opérateurs "=", "<=", ">=" et "<>". L'élément constante doit être remplacé par une « constante » du même type que le champ identifié par nom-de-champ.
SELECT * FROM nom-de-table1 WHERE nom-de-champ2 opérateur-de-comparaison3 constante4 ; L'exemple: SELECT * FROM Personnes31 WHERE Nom2 =3 "drapeau"4;
Qu'est-ce qu'un « constante » d'un certain type? Pour le moment, disons simplement qu'une constante de type "text" est une chaîne de caractères, écrite selon les conventions exposées précédemment, mais obligatoirement délimitée par des guillemets doubles. Nous reviendrons sous peu aux constantes des autres types. Comme on peut constater, notre exemple rencontre toutes les exigences mentionnées. Les trois éléments nom-de-champ, opérateur-de-comparaison et constante forment ce qu'on appelle la condition de sélection du SELECT restreint. Dans notre exemple, la condition de sélection est donc:
Nom = "drapeau"
Nom = "drapeau"
5.3 Comparaisons de chaînes
Nous nous apprêtons à parler de comparaison de chaînes de caractères, notamment à nous demander dans quelles circonstances deux chaînes, de provenances diverses, peuvent être considérées comme égales. Contrairement à ce qu'on pourrait penser de prime abord, la forme la plus utile de comparaison n'est pas l'égalité stricte des chaînes (exactement les mêmes caractères, dans le même ordre). En fait, la forme la plus courante de comparaison est définie différemment; pour éviter la confusion avec l'égalité stricte, nous l'appelons quasi-égalité. La quasi-égalité est définie comme suit:
Deux chaînes de caractères sont quasi-égales si elles ne diffèrent que par des espaces finales et/ou par la casse des lettres. Donc, en particulier, deux chaînes quasi-égales ne sont pas forcément de la même longueur. En effet, les espaces finales qui pourraient se trouver dans les chaînes comparées ne sont pas prises en compte. Ainsi, par exemple, "Faite" est quasi-égale à "faite", de même qu'à "Faite_" et à "faite___". Par contre, elle n'est pas quasi-égale à "_Faite", ni à "Faîte" (les signes diacritiques ne sont pas ignorés). Lorsque deux chaînes a et b sont quasi-égales, on écrit a = b; autrement, on écrit a <> b. Ainsi, on écrirait:
Profitons-en pour noter que
Un autre type de comparaison de chaînes est la préséance dans l'ordre alphabétique. Si a vient avant b dans l'ordre alphabétique, alors on écrira a < b; si elle vient après, on écrira a>b. Notons que, si a < b ou a>b, alors forcément, a <> b.
Le lecteur aguerri se demandera de quel « ordre alphabétique » exactement il s'agit. La réponse dépend en fait du système utilisé. Il s'agit habituellement d'une comparaison caractère par caractère, qui traite les signes diacritiques selon les règles de la langue active spécifiée dans la configuration du système d'exploitation actif. Dans nos exemples, nous supposerons les règles du français. Ainsi, par exemple:
Notons également que, même pour des chaînes consitutées exclusivement de chiffres, l'ordre alphabétique ne correspond pas à l'ordre numérique; par exemple:
Finalement, notons que la chaîne vide (ou toute chaîne constituée exclusivement d'espaces) est "plus petite" que n'importe quelle autre chaîne. Ainsi, a > "" est toujours vrai, sauf si a est vide (ou constituée exclusivement d'espaces).
Nous nous apprêtons à parler de comparaison de chaînes de caractères, notamment à nous demander dans quelles circonstances deux chaînes, de provenances diverses, peuvent être considérées comme égales. Contrairement à ce qu'on pourrait penser de prime abord, la forme la plus utile de comparaison n'est pas l'égalité stricte des chaînes (exactement les mêmes caractères, dans le même ordre). En fait, la forme la plus courante de comparaison est définie différemment; pour éviter la confusion avec l'égalité stricte, nous l'appelons quasi-égalité. La quasi-égalité est définie comme suit:
Deux chaînes de caractères sont quasi-égales si elles ne diffèrent que par des espaces finales et/ou par la casse des lettres. Donc, en particulier, deux chaînes quasi-égales ne sont pas forcément de la même longueur. En effet, les espaces finales qui pourraient se trouver dans les chaînes comparées ne sont pas prises en compte. Ainsi, par exemple, "Faite" est quasi-égale à "faite", de même qu'à "Faite_" et à "faite___". Par contre, elle n'est pas quasi-égale à "_Faite", ni à "Faîte" (les signes diacritiques ne sont pas ignorés). Lorsque deux chaînes a et b sont quasi-égales, on écrit a = b; autrement, on écrit a <> b. Ainsi, on écrirait:
"Faite_" = "faite" "fut" <> "fût"
" " = "_" = "___" .
Le lecteur aguerri se demandera de quel « ordre alphabétique » exactement il s'agit. La réponse dépend en fait du système utilisé. Il s'agit habituellement d'une comparaison caractère par caractère, qui traite les signes diacritiques selon les règles de la langue active spécifiée dans la configuration du système d'exploitation actif. Dans nos exemples, nous supposerons les règles du français. Ainsi, par exemple:
"0" < "9"< "A" = "a" < "à" = "À" < "â" < "e" < "é" < "è" < "ê" < "ë" = "Ë" "faite" <"faîte" < "faites" < "faîtes"
"0" < "00" "20" < "3"
La notation a <= b signifie que a < b ou a = b; la notation a >= b signifie que a > b ou a = b.
5.4 SELECT restreints: la sémantique
Que fait donc un SELECT restreint?
Eu égard au scénario d'interrogation exposé ci-dessus, la question revient à demander: qu'est-ce qu'un SGBD me retournera comme résultat si je lui soumets un SELECT restreint valide? La réponse s'avère en fait extrêmement naturelle. À preuve, on peut pratiquement « deviner » que la requête suivante, exécutée sur la base "Contacts15", repêchera les fiches 2 et 4 de la table "Personnes3":
qui inclut bel et bien les fiches 2 et 4. Mais comment, exactement, le SGBD arrive-t-il à ce résultat?
D'abord, profitons-en pour faire un énoncé universel sur les requêtes SELECT (pas seulement les SELECT restreints):
le résultat d'un SELECT est toujours une table relationnelle. Ou presque. En fait, il s'agit d'une table relationnelle qui ne porte pas de nom et ne comporte ni clé primaire ni clés externes. Le fait que la table ne porte pas de nom n'est pas gênant, parce que la table résultat d'un SELECT est temporaire: elle n'existe que le temps de présenter les résultats et est ensuite détruite. Le résultat d'un SELECT ne devient donc pas une table additionnelle dans la base de données.
Une première chose que l'on peut dire par rapport à la table résultat d'un SELECT restreint, c'est qu'elle a exactement la même définition que la table mentionnée dans la requête (la table « nom-de-table »), mais sans le nom de table, et sans la clé primaire et les clés externes. La table mentionnée dans notre requête exemple est "Personnes3", et le résultat a donc la définition suivante:
qui est exactement la définition de "Personnes3", clés primaire et externe en moins. Maintenant, quelles fiches contient cette table? Réponse: exactement les fiches de la table nom-de-table (ici "Personnes3") pour lesquelles la condition de sélection est vraie.
Que fait donc un SELECT restreint?
Eu égard au scénario d'interrogation exposé ci-dessus, la question revient à demander: qu'est-ce qu'un SGBD me retournera comme résultat si je lui soumets un SELECT restreint valide? La réponse s'avère en fait extrêmement naturelle. À preuve, on peut pratiquement « deviner » que la requête suivante, exécutée sur la base "Contacts15", repêchera les fiches 2 et 4 de la table "Personnes3":
SELECT * FROM Personnes3 WHERE Nom = "drapeau" ;
Et, effectivement, le résultat obtenu est le suivant:
Numéro Prénom Nom Téléphone Organisation integer, N text(30), N, V text(50), N, V text(8), V, mask:"000-0000" integer 2 Roger Drapeau 2 4 Sylvie Drapeau
D'abord, profitons-en pour faire un énoncé universel sur les requêtes SELECT (pas seulement les SELECT restreints):
le résultat d'un SELECT est toujours une table relationnelle. Ou presque. En fait, il s'agit d'une table relationnelle qui ne porte pas de nom et ne comporte ni clé primaire ni clés externes. Le fait que la table ne porte pas de nom n'est pas gênant, parce que la table résultat d'un SELECT est temporaire: elle n'existe que le temps de présenter les résultats et est ensuite détruite. Le résultat d'un SELECT ne devient donc pas une table additionnelle dans la base de données.
Une première chose que l'on peut dire par rapport à la table résultat d'un SELECT restreint, c'est qu'elle a exactement la même définition que la table mentionnée dans la requête (la table « nom-de-table »), mais sans le nom de table, et sans la clé primaire et les clés externes. La table mentionnée dans notre requête exemple est "Personnes3", et le résultat a donc la définition suivante:
Numéro Prénom Nom Téléphone Organisation integer, N text(30), N, V text(50), N, V text(8), V, mask:"000-0000" integer
Rappelons-nous que, dans notre exemple, la condition de sélection est:
Nom = "drapeau"
Cela veut dire que le résultat de la requête contient exactement les fiches de "Personnes3" pour lesquelles le champ "Nom" contient la valeur "drapeau".
De façon générale, dire que la « condition de sélection est vraie pour une fiche » veut dire que, si l'on remplace le nom de champ (dans la condition de sélection) par la valeur de ce champ dans la fiche, on obtient une expression vraie. Par exemple, pour la fiche 1 de "Personnes3", l'expression obtenue en remplaçant le nom de champ par la valeur de ce champ est:
"Tremblay" = "drapeau"
qui est évidemment fausse. C'est pour cette raison que la fiche 1 ne fait pas partie du résultat. Pour la fiche 2, cependant, on obtient l'expression:
"Drapeau" = "drapeau"
qui est vraie; c'est pour cela que la fiche 2 fait partie du résultat retourné. Et ainsi de suite. Toutes les fiches de la table mentionnée dans la requête sont passées, l'une après l'autre, et celles pour lesquelles la condition de sélection est vraie sont incluses dans le résultat.
On voit donc que le contenu du résultat d'un SELECT restreint est toujours un sous-ensemble des fiches de la table mentionnée dans la requête. Il pourrait arriver que ce sous-ensemble soit vide (si la condition de sélection n'est vraie pour aucune fiche), ce qui ne constituerait aucunement une erreur. Il se pourrait aussi que le résultat contienne toutes les fiches de la table mentionnée (si la condition de sélection est vraie pour toutes les fiches), ce qui ne serait pas non plus une erreur.
Nom = "drapeau"
Cela veut dire que le résultat de la requête contient exactement les fiches de "Personnes3" pour lesquelles le champ "Nom" contient la valeur "drapeau".
De façon générale, dire que la « condition de sélection est vraie pour une fiche » veut dire que, si l'on remplace le nom de champ (dans la condition de sélection) par la valeur de ce champ dans la fiche, on obtient une expression vraie. Par exemple, pour la fiche 1 de "Personnes3", l'expression obtenue en remplaçant le nom de champ par la valeur de ce champ est:
"Tremblay" = "drapeau"
qui est évidemment fausse. C'est pour cette raison que la fiche 1 ne fait pas partie du résultat. Pour la fiche 2, cependant, on obtient l'expression:
"Drapeau" = "drapeau"
qui est vraie; c'est pour cela que la fiche 2 fait partie du résultat retourné. Et ainsi de suite. Toutes les fiches de la table mentionnée dans la requête sont passées, l'une après l'autre, et celles pour lesquelles la condition de sélection est vraie sont incluses dans le résultat.
On voit donc que le contenu du résultat d'un SELECT restreint est toujours un sous-ensemble des fiches de la table mentionnée dans la requête. Il pourrait arriver que ce sous-ensemble soit vide (si la condition de sélection n'est vraie pour aucune fiche), ce qui ne constituerait aucunement une erreur. Il se pourrait aussi que le résultat contienne toutes les fiches de la table mentionnée (si la condition de sélection est vraie pour toutes les fiches), ce qui ne serait pas non plus une erreur.
Testons notre compréhension sur d'autres SELECT restreints. Par exemple:
SELECT * FROM Personnes3 WHERE Nom <> "drapeau" ; donnera: Numéro Prénom Nom Téléphone Organisation integer, N text(30), N, V text(50), N, V text(8), V, mask:"000-0000" integer 1 Jeanne Tremblay 555-1212 1 3 Bernard Larue 555-1214 1 Et la requête: SELECT * FROM Personnes3 WHERE Prénom > "jeanne" ; donnera: Numéro Prénom Nom Téléphone Organisation integer, N text(30), N, V text(50), N, V text(8), V, mask:"000-0000" integer 2 Roger Drapeau 2 4 Sylvie Drapeau
5.5 Constantes de types autres que "text"
La constante présente dans un SELECT restreint doit être du même type que le champ mentionné. De quoi a l'air une constante de type "integer", "date" ou "logical"? Sans surprise, la réponse réside dans la transformation de saisie du type en question, assaisonnée d'un soupçon de conventions d'écriture:
Une constante de type "integer" est toute chaîne acceptée par la transformation de saisie du type "integer", sans doubles guillemets ni autre délimitation. Par exemple, 23, 007 et -12 sont des constantes "integer". La valeur représentée par une telle constante est la valeur résultant de la transformation de saisie appliquée à la constante. Une constante de type "date" est toute chaîne acceptée par la transformation de saisie du type "date", précédée et suivie du caractère "#". La valeur représentée par une telle constante est la valeur résultant de la transformation de saisie appliquée à ce qui est entre les deux "#". Par exemple, #2009-12-31# représente la date dont la représentation interne est "2009-12-31", soit le 31 décembre 2009.
Une constante de type "logical" est toute chaîne acceptée par la transformation de saisie du type "logical", soit "true", "yes", "false" ou "no" (sans les guillemets). La valeur représentée par une telle constante est la valeur résultant de la transformation de saisie appliquée à la constante.
La constante présente dans un SELECT restreint doit être du même type que le champ mentionné. De quoi a l'air une constante de type "integer", "date" ou "logical"? Sans surprise, la réponse réside dans la transformation de saisie du type en question, assaisonnée d'un soupçon de conventions d'écriture:
Une constante de type "integer" est toute chaîne acceptée par la transformation de saisie du type "integer", sans doubles guillemets ni autre délimitation. Par exemple, 23, 007 et -12 sont des constantes "integer". La valeur représentée par une telle constante est la valeur résultant de la transformation de saisie appliquée à la constante. Une constante de type "date" est toute chaîne acceptée par la transformation de saisie du type "date", précédée et suivie du caractère "#". La valeur représentée par une telle constante est la valeur résultant de la transformation de saisie appliquée à ce qui est entre les deux "#". Par exemple, #2009-12-31# représente la date dont la représentation interne est "2009-12-31", soit le 31 décembre 2009.
Une constante de type "logical" est toute chaîne acceptée par la transformation de saisie du type "logical", soit "true", "yes", "false" ou "no" (sans les guillemets). La valeur représentée par une telle constante est la valeur résultant de la transformation de saisie appliquée à la constante.
Les comparaisons de valeurs entières (de type "integer") suivent les règles habituelles de l'arithmétique; par exemple, 3 >= 1 est vraie. Les comparaisons de valeurs "date" correspondent à l'ordre chronologique; par exemple, #2011-12-31# < #2012-01-01# est vraie.
Ce nouveau vocabulaire peut être mis en pratique dans des SELECT restreints. Par exemple:
Ce nouveau vocabulaire peut être mis en pratique dans des SELECT restreints. Par exemple:
SELECT * FROM Personnes3 WHERE Numéro >= 3 ; donne: Numéro Prénom Nom Téléphone Organisation integer, N text(30), N, V text(50), N, V text(8), V, mask:"000-0000" integer 3 Bernard Larue 555-1214 1 4 Sylvie Drapeau Et la requête: SELECT * FROM Personnes3 WHERE Organisation = 1 ; donne: Numéro Prénom Nom Téléphone Organisation integer, N text(30), N, V text(50), N, V text(8), V, mask:"000-0000" integer 1 Jeanne Tremblay 555-1212 1 3 Bernard Larue 555-1214 1
5.6 Comparaisons avec la valeur NULL
La valeur NULL se comporte d'une manière particulière dans les comparaisons. En l'occurrence, une comparaison avec la valeur NULL n'est jamais vraie, quels que soient l'opérateur de comparaison et la valeur comparée! Plus précisément, une expression de la forme:
NULL opérateur-de-comparaison constante
n'est jamais vraie. (Techniquement, l'expression retourne la valeur NULL.) Ainsi, aucune des expressions suivantes n'est vraie:
Ceci amène parfois des résultats à première vue surprenants. Par exemple, nous venons juste de voir que:
On pourrait penser qu'en inversant l'opérateur de comparaison, on inverse les fiches repêchées, c'est-à-dire qu'on repêche maintenant les fiches 2 et 4. Or:
En effet, pour la fiche 4, le remplacement du nom de champ par sa valeur dans la condition de sélection donne:
NULL <> 1
expression qui n'est pas vraie. La fiche 4 n'est donc pas repêchée.
La valeur NULL se comporte d'une manière particulière dans les comparaisons. En l'occurrence, une comparaison avec la valeur NULL n'est jamais vraie, quels que soient l'opérateur de comparaison et la valeur comparée! Plus précisément, une expression de la forme:
NULL opérateur-de-comparaison constante
n'est jamais vraie. (Techniquement, l'expression retourne la valeur NULL.) Ainsi, aucune des expressions suivantes n'est vraie:
NULL = 1 NULL <> 1 NULL = "abc" NULL <> "abc"
SELECT * FROM Personnes3 WHERE Organisation = 1 ; donne le résultat :Numéro Prénom Nom Téléphone Organisation integer, N text(30), N, V text(50), N, V text(8), V, mask:"000-0000" integer 1 Jeanne Tremblay 555-1212 1 3 Bernard Larue 555-1214 1
SELECT * FROM Personnes3 WHERE Organisation <> 1 ;
ne repêche que la fiche 2:
Numéro Prénom Nom Téléphone Organisation integer, N text(30), N, V text(50), N, V text(8), V, mask:"000-0000" integer 2 Roger Drapeau 2
NULL <> 1
expression qui n'est pas vraie. La fiche 4 n'est donc pas repêchée.
5.7 SELECT non restreints
Comme nous avons dit précédemment, les requêtes SELECT non restreintes peuvent prendre des formes très variées et offrent énormément de flexibilité et de possibilités pour l'extration et la recherche d'information dans une base de données. Les deux ressources suivantes (associées au cours BLT6306 Création de bases de données documentaires) permettront au lecteur de se familiariser avec la syntaxe et la sémantique des requêtes SELECT non restreintes: Exemples de jointures Exemples de requêtes SQL avec explications (base INSCRIP)
Comme nous avons dit précédemment, les requêtes SELECT non restreintes peuvent prendre des formes très variées et offrent énormément de flexibilité et de possibilités pour l'extration et la recherche d'information dans une base de données. Les deux ressources suivantes (associées au cours BLT6306 Création de bases de données documentaires) permettront au lecteur de se familiariser avec la syntaxe et la sémantique des requêtes SELECT non restreintes: Exemples de jointures Exemples de requêtes SQL avec explications (base INSCRIP)
5.8 Conditions de validité
La section 3 (Les expressions dans Access) de la ressource Exemples de requêtes SQL avec explications (base INSCRIP) introduit la notion d'expression SQL et, en particulier, de condition, qui est une expression donnant comme résultat une valeur logique (ou booléenne). Une valeur logique (ou booléenne) correspond pour nous à une valeur de type "logical". Les conditions de sélection des SELECT restreints vues ci-dessus sont un cas particulier de conditions et d'expressions SQL.
La section 3 (Les expressions dans Access) de la ressource Exemples de requêtes SQL avec explications (base INSCRIP) introduit la notion d'expression SQL et, en particulier, de condition, qui est une expression donnant comme résultat une valeur logique (ou booléenne). Une valeur logique (ou booléenne) correspond pour nous à une valeur de type "logical". Les conditions de sélection des SELECT restreints vues ci-dessus sont un cas particulier de conditions et d'expressions SQL.
La plupart des SGBD relationnels offrent la possibilité d'associer à chaque champ une condition de validité, qui est une condition qui doit obligatoirement s'évaluer à "true" au moment d'enregistrer une valeur dans le champ (donc, à la saisie). Par exemple, si dans un champ "Durée" de type "integer" on ne voulait stocker que des nombres pairs, on pourrait associer au champ la condition de validité suivante: (Durée mod 2) = 0
En effet, dans le langage des expressions de SQL, mod représente l'opération arithmétique "modulo", qui calcule le reste de la division d'un nombre (celui de gauche) par un autre (celui de droite). Si on essayait d'inscrire 27 dans ce champ, la condition de validité s'évaluerait à "false", puisque le reste de la division de 27 par 2 est 1, et la fiche serait rejetée (non enregistrée dans la table).
La condition de validité associée à un champ est vérifiée après les vérifications associées au type et au masque de saisie. Elle constitue un mécanisme de validation de plus à la disposition du concepteur d'une base de données relationnelle.
Nous n'en dirons pas plus sur les conditions de validité; nous voulions simplement en mentionner l'existence. En particulier, nous ne prendrons pas la peine d'adopter une convention particulière pour l'inscription d'une convention de validité dans la définition d'une table relationnelle.
Nous n'en dirons pas plus sur les conditions de validité; nous voulions simplement en mentionner l'existence. En particulier, nous ne prendrons pas la peine d'adopter une convention particulière pour l'inscription d'une convention de validité dans la définition d'une table relationnelle.
5.9 Conditions de validité globales
Certains SGBD permettent de spécifier une condition de validité globale associée à une table au complet (et non à un champ précis). Ce genre de conditions de validité permet, par exemple, de s'assurer que la valeur inscrite dans un certain champ (par exemple, une date de fin) est supérieure à celle inscrite dans un autre champ (par exemple, une date de début). La condition de validité globale associée à une table est évaluée après les conditions de validité spécifiques à chaque champ, au moment de l'inscription d'une nouvelle fiche dans un table. Si la condition de validité globale n'est pas satisfaite (c'est-à-dire si elle ne s'évalue pas à "true"), alors la fiche est rejetée (non enregistrée dans la table).
Certains SGBD permettent de spécifier une condition de validité globale associée à une table au complet (et non à un champ précis). Ce genre de conditions de validité permet, par exemple, de s'assurer que la valeur inscrite dans un certain champ (par exemple, une date de fin) est supérieure à celle inscrite dans un autre champ (par exemple, une date de début). La condition de validité globale associée à une table est évaluée après les conditions de validité spécifiques à chaque champ, au moment de l'inscription d'une nouvelle fiche dans un table. Si la condition de validité globale n'est pas satisfaite (c'est-à-dire si elle ne s'évalue pas à "true"), alors la fiche est rejetée (non enregistrée dans la table).