Les bases de données/SQL : Data Description Language

Nous avons vu beaucoup de théorie dans les chapitres précédents. Il est temps de passer à un peu plus de pratique : nous allons aborder les bases du langage SQL. Pour faire simple, ce langage permet de gérer des bases de données. Ce langage permet d'envoyer des ordres à un SGBD, ces ordres permettant de créer des tables, d'y insérer des données, de les consulter, ou de les supprimer. On divise ce langage SQL en deux sous-langages :

  • le SQL Data Description Language, qui permet de créer des tables et de définir comment seront stockées les données dans la base de données ;
  • et le SQL Data Manipulation Language, qui permet de créer, consulter et supprimer le contenu des tables.

Tables, enregistrements et attributs

modifier

Créer une table est possible en utilisant l'expression suivante :

create table nom_de_la_table
(
    /* liste des attributs (colonnes) de la table, séparés par des virgules */
) ;

Pour définir les colonnes des tables, il suffit de préciser quels sont leurs noms et leur type.

Le nom des attributs d'une table est soumis à quelques règles relativement strictes. Premièrement, il ne peut contenir que des lettres, des chiffres, et les signes $, _, et # : pas d'espaces, pas d'accents, etc. De plus, un nom d'attribut ne peut pas commencer par un chiffre. De plus, il faut signaler que les lettres peuvent être écrites en majuscules et minuscules : cela ne change rien : les noms TAUX et taux sont strictement équivalent et référent au même attribut.

En plus de préciser le nom de l'attribut, il faut aussi préciser son type. SQL ne permet de définir que quelques types bien précis, qui sont fréquemment rencontré dans les autres langages de programmation. Cela comprend les booléens, les nombres entiers et à virgule, les chaînes de caractères et quelques autres. À cela, il faut ajouter les données temporelles, comme des dates, des intervalles de temps, etc. Pour simplifier franchement, les types les plus utilisés sont les suivants :

  • BOOLEAN pour les booléens ;
  • INT pour les nombres entiers ;
  • FLOAT pour les nombres à virgule ;
  • VARCHAR pour les chaînes de caractères ;
  • DATE et DATETIME pour les données temporelles.

Pour les curieux, la liste complète des types supportés est donnée dans le tableau ci-dessous.

 
SQLdatatype

Pour préciser le type lors de la déclaration, celui-ci est indiqué à la suite du nom de l'attribut dans la requête CREATE. Un exemple est donné ci-dessous, avec les types des attributs les plus courants.

create table PERSONNE
(
    NOM varchar ,
    PRENOM varchar ,
    ADRESSE varchar ,
    AGE int ,
    CATEGORIE_PROFESSIONNELLE varchar ,
    NOMBRE_ENFANTS int ,
    TAILLE float ,
    DATE_NAISSANCE date
) ;

Entiers

modifier

L'ensemble des types entiers est détaillé dans le tableau ci-dessous.

Type Minimum Maximum
TINYINT -128 127
SMALLINT -32768 32767
MEDIUMINT -8388608 8388607
INT -2147483648 2147483647
BIGINT 9223372036854775808 9223372036854775807

On peut préciser qu'on peut placer le mot-clé UNSIGNED devant ces types pour préciser qu'on ne veut mémoriser que des nombres positifs, et pas des nombres négatifs. Dans ce cas, les bornes des types deviennent celles indiquées dans le tableau ci-dessous.

Type Minimum Maximum
UNSIGNED TINYINT 0 256
UNSIGNED SMALLINT 0 65536
UNSIGNED MEDIUMINT 0 16777216
UNSIGNED INT 0 4294967296
UNSIGNED BIGINT 0 18446744073709551615

Nombres à virgule

modifier

L'ensemble des types pour les nombres à virgules est détaillé dans le tableau ci-dessous.

Type Description
NUMERIC et DECIMAL S'utilise avec deux paramètres : le nombre de chiffres du nombre, et le nombre de chiffres après la virgule. On peut ainsi préciser qu'on souhaite mémoriser un nombre de 16 chiffres, dont maximum 5 après la virgule. DECIMAL fonctionne de la même manière que NUMERIC, mais avec des bornes différentes.
FLOAT, DOUBLE et REAL Mémorisent des nombres à virgule sans qu'on ait à préciser de paramètres. Ces différents types ont des bornes maximales et minimales différentes.

Pour stocker du texte, on peut utiliser les types ci-dessous. Ces types sont équivalents.

Type Description
CHAR On peut préciser en paramètres le nombre d'octets que prendra le texte, maximum 255 octets.
VARCHAR Prend un nombre variable d'octets, le nombre maximal étant précisé en paramètre lors de la définition du type, ce nombre maximal n'allant pas au-delà de 255. Il est plus économe en mémoire que le CHAR pour des textes ou noms de longueur potentiellement inférieure à 255 octets.
TEXT Les limites sont plus grandes que les autres types.

Types temporels

modifier

L'ensemble des types temporels est détaillé dans le tableau ci-dessous.

Type Description
DATE Mémorise une date au format AAAA-MM-JJ
TIME Mémorise une heure ou un intervalle de temps, au format HH:MM:SS
DATETIME Mémorise une date et une heure (une sorte de fusion entre les types DATE et TIME), au format AAAA-MM-JJ HH:MM:SS
YEAR Ne mémorise qu'une année
TIMESTAMP Durée en seconde écoulée depuis une date définie à l'avance (qui dépend du SGBD)

Il est possible de définir si une colonne est obligatoire ou facultative. Par obligatoire ou facultative, on veut dire indiquer si la colonne peut contenir la valeur NULL ou non : une colonne obligatoire ne peut pas contenir de NULL alors qu'une colonne facultative le peut. Pour indiquer qu'une colonne est obligatoire, il suffit d'ajouter le mot-clé not null juste après la définition de la colonne. Dans le cas d'une colonne facultative, il ne faut rien faire.

create table PERSONNE
(
    NOM varchar not null ,
    PRENOM varchar not null ,
    ADRESSE varchar not null ,
    AGE int ,
    CATEGORIE_PROFESSIONNELLE varchar ,
    NOMBRE_ENFANTS int ,
    TAILLE float ,
    DATE_NAISSANCE date
) ;

Clés primaires et étrangères

modifier

On sait donc définir des tables, et dire quels sont les attributs que doivent contenir chaque ligne de cette table. Il nous reste cependant à voir comment dire quels sont les attributs qui servent de clé primaire, et ceux qui servent de clé étrangère. De plus, dans le cas des clés étrangères, il faut aussi préciser quelle est la table parent, celle vers laquelle pointent les lignes de la table courante.

Clé primaire

modifier

Pour indiquer quels sont les attributs qui appartiennent à la clé primaire, il faut ajouter quelque chose aux déclarations de la table. Ce quelque chose est situé à la toute fin de la déclaration : il s’agit du mot-clé primary key (clé primaire en anglais), et des noms des attributs de cette clé entre parenthèses.

create table PERSONNE
(
    ID_PERSONNE int not null ,
    NOM varchar not null ,
    PRENOM varchar not null ,
    ADRESSE varchar not null ,
    DATE_NAISSANCE date not null ,
    AGE int ,
    CATEGORIE_PROFESSIONNELLE varchar ,
    NOMBRE_ENFANTS int ,
    TAILLE float ,

    primary key (ID_PERSONNE) ,
) ;

Pour définir une clé alternative, en plus de la clé primaire, il faut l'indiquer avec le mot-clé unique. On peut déclarer plusieurs clés alternatives, chacune étant définie par un unique séparé des autres. Mais on ne peut définir qu'une seule clé primaire.

create table PERSONNE
(
    ID_PERSONNE int not null ,
    NOM varchar not null ,
    PRENOM varchar not null ,
    ADRESSE varchar not null ,
    DATE_NAISSANCE date not null ,
    AGE int ,
    CATEGORIE_PROFESSIONNELLE varchar ,
    NOMBRE_ENFANTS int ,
    TAILLE float ,

    primary key (ID_PERSONNE) ,
    unique (NOM, PRENOM, ADRESSE)
) ;

On rappelle que les attributs d'une clé primaire ou alternative ne peuvent pas être à NULL.

Clés étrangères

modifier

Pour définir une clé étrangère, on fait comme pour les clés primaires, à ceci près que le mot-clé n'est pas le même : il faut utiliser le mot-clé foreign key (clé étrangère en anglais). De plus, il faut préciser quelle est la table à laquelle cette clé fait référence, ce qui demande d'utiliser le mot-clé reference suivi du nom de la table. Par exemple, voici ce que donnerait une table ENFANT, dont chaque ligne ferait référence à une table MERE et une table PERE.

create table ENFANT
(
    ID_ENFANT int not null ,
    NOM varchar not null ,
    PRENOM varchar not null ,
    ADRESSE varchar not null ,
    DATE_NAISSANCE date not null ,
    AGE int ,
    CATEGORIE_PROFESSIONNELLE varchar ,
    NOMBRE_ENFANTS int ,
    TAILLE float ,

    MAMAN int ,
    PAPA int ,

    primary key (ID_ENFANT) ,
    unique (NOM, PRENOM, ADRESSE) ,
    foreign key (MAMAN) reference MERE ,
    foreign key (PAPA) reference PERE
) ;

Contraintes d'intégrité référentielle

modifier

Maintenant, il nous reste à préciser une dernière chose : que faire en cas de suppression d'une ligne dans la table décrite ? On a vu auparavant que l'on pouvait soit interdire la suppression si des clés étrangères pointent encore sur la ligne, mettre à zéro ces clés étrangères, ou bien tout simplement supprimer les lignes qui pointent sur la ligne à supprimer. Pour cela, il faudra utiliser un mot-clé à la fin de la ligne de code qui définit les clés étrangères :

  • on delete cascade pour une suppression ;
  • on delete no action pour une interdiction de la suppression ;
  • on delete set null pour mettre la clé étrangère à NULL.