Tables temporaires

Ce chapitre est consacré aux tables temporaires qui, comme leur nom l'indique, sont des tables ayant une durée de vie très limitée. En effet, tout comme les variables utilisateur ou les requêtes préparées, les tables temporaires n'existent que dans la session qui les a créées. Dès que la session se termine (déconnexion volontaire ou accidentelle), les tables temporaires sont supprimées.

Nous verrons en détail dans ce chapitre comment se comportent ces tables temporaires, et à quoi elles peuvent servir. De plus, nous verrons deux nouvelles manières de créer une table (temporaire ou non), en partant de la structure et/ou des données d'une ou plusieurs autres tables.

Principe, règles et comportement

On l'a dit, une table temporaire est une table qui n'existe que dans la session qui l'a créée. En dehors de ça, c'est une table presque normale. On peut exécuter sur ces tables toutes les opérations que l'on exécute sur une table classique : insérer des données, les modifier, les supprimer, et bien sûr les sélectionner.

Création, modification, suppression d'une table temporaire

Pour créer, modifier et supprimer une table temporaire, on utilise les mêmes commandes que pour les tables normales.

Création

Pour créer une table temporaire, on peut utiliser tout simplement CREATE TABLE en ajoutant TEMPORARY, pour préciser qu'il s'agit d'une table temporaire.

Exemple : création d'une table temporaire TMP_Animal.

1
2
3
4
5
6
7
8
CREATE TEMPORARY TABLE TMP_Animal (
    id INT UNSIGNED PRIMARY KEY,
    nom VARCHAR(30),
    espece_id INT UNSIGNED,
    sexe CHAR(1)
);

DESCRIBE TMP_Animal;

Field

Type

Null

Key

Default

Extra

id

int(10) unsigned

NO

PRI

NULL

nom

varchar(30)

YES

NULL

espece_id

int(10) unsigned

YES

NULL

sexe

char(1)

YES

NULL

Visiblement, la table a bien été créée. Par contre, si l'on tente de vérifier cela en utilisant SHOW TABLES plutôt que DESCRIBE TMP_Animal, on ne trouvera pas la nouvelle table temporaire dans la liste des tables. Et pour cause, seules les tables permanentes (et les vues) sont listées par cette commande.

Modification

Pour la modification, nul besoin du mot-clé TEMPORARY, on utilise directement ALTER TABLE, comme s'il s'agissait d'une table normale.

Exemple : ajout d'une colonne à TMP_Animal.

1
2
ALTER TABLE TMP_Animal
ADD COLUMN date_naissance DATETIME;

Suppression

En ce qui concerne la suppression, on a le choix d'ajouter TEMPORARY, ou non. Si TEMPORARY est précisé, la table mentionnée ne sera supprimée que s'il s'agit bien d'une table temporaire. Sans ce mot-clé, on pourrait supprimer par erreur une table non temporaire, en cas de confusion des noms des tables par exemple.

Exemple : suppression de TMP_Animal, qui n'aura pas fait long feu.

1
DROP TEMPORARY TABLE TMP_Animal;

Utilisation des tables temporaires

Une table temporaire s'utilise comme une table normale. Les commandes d'insertion, modification et suppression de données sont exactement les mêmes.

Notez que l'immense majorité des tables temporaires étant créées pour stocker des données venant d'autres tables, on utilise souvent INSERT INTO ... SELECT pour l'insertion des données.

Cache-cache table

Une table temporaire existe donc uniquement pour la session qui la crée. Par conséquent, deux sessions différentes peuvent parfaitement utiliser chacune une table temporaire ayant le même nom, mais ni la même structure ni les mêmes données.

Il est également possible de créer une table temporaire ayant le même nom qu'une table normale. Toutes les autres sessions éventuelles continueront à travailler sur la table normale comme si de rien n'était.

Et la session qui crée cette fameuse table ?

En cas de conflit de noms entre une table temporaire et une table permanente, la table temporaire va masquer la table permanente. Donc, tant que cette table temporaire existera (c'est-à-dire jusqu'à ce qu'on la supprime explicitement, ou jusqu'à déconnexion de la session), toutes les requêtes faites en utilisant son nom seront exécutées sur la table temporaire, et non sur la table permanente de même nom.

Exemple : création d'une table temporaire nommée Animal.

On commence par sélectionner les perroquets de la table Animal (la table normale, puisqu'on n'a pas encore créé la table temporaire). On obtient quatre résultats.

1
2
3
SELECT id, sexe, nom, commentaires, espece_id 
FROM Animal
WHERE espece_id = 4;

id

sexe

nom

commentaires

espece_id

57

M

Safran

Coco veut un gâteau !

4

58

M

Gingko

Coco veut un gâteau !

4

59

M

Bavard

Coco veut un gâteau !

4

60

F

Parlotte

Coco veut un gâteau !

4

On crée ensuite la table temporaire, et on y insère un animal avec espece_id = 4. On refait la même requête de sélection, et on obtient uniquement l'animal que l'on vient d'insérer, avec la structure de la table temporaire.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
CREATE TEMPORARY TABLE Animal (
    id INT UNSIGNED PRIMARY KEY,
    nom VARCHAR(30),
    espece_id INT UNSIGNED,
    sexe CHAR(1)
);

INSERT INTO Animal
VALUES (1, 'Tempo', 4, 'M');

SELECT * 
FROM Animal
WHERE espece_id = 4;

id

nom

espece_id

sexe

1

Tempo

4

M

Pour terminer, suppression de la table temporaire. La même requête de sélection nous affiche à nouveau les quatre perroquets de départ.

1
2
3
4
5
DROP TEMPORARY TABLE Animal;

SELECT id, sexe, nom, commentaires, espece_id 
FROM Animal
WHERE espece_id = 4;

id

sexe

nom

commentaires

espece_id

57

M

Safran

Coco veut un gâteau !

4

58

M

Gingko

Coco veut un gâteau !

4

59

M

Bavard

Coco veut un gâteau !

4

60

F

Parlotte

Coco veut un gâteau !

4

Dans ce cas de figure, il vaut mieux utiliser le mot-clé TEMPORARY dans la requête de suppression de la table, afin d'être sûr qu'on détruit bien la table temporaire et non la table permanente.

Gardez bien en tête le fait que les tables temporaires sont détruites dès que la connexion prend fin. Dans de nombreuses applications, une nouvelle connexion est créée à chaque nouvelle action. Par exemple, pour un site internet codé en PHP, on crée une nouvelle connexion (donc une nouvelle session) à chaque rechargement de page.

Restrictions des tables temporaires

Deux restrictions importantes à noter lorsque l'on travaille avec des tables temporaires :

  • on ne peut pas mettre de clé étrangère sur une table temporaire ;
  • on ne peut pas faire référence à une table temporaire deux fois dans la même requête.

Quelques explications sur la deuxième restriction : lorsque l'on parle de "faire référence deux fois à la table", il s'agit d'aller chercher des données deux fois dans la table. Le nom de la table temporaire peut apparaître plusieurs fois dans la requête, par exemple pour préfixer le nom des colonnes.

Exemples : on recrée une table TMP_Animal, un peu plus complexe cette fois, qu'on remplit avec les chats de la table Animal.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
CREATE TEMPORARY TABLE TMP_Animal (
    id INT UNSIGNED PRIMARY KEY,
    nom VARCHAR(30),
    espece_id INT UNSIGNED,
    sexe CHAR(1),
    mere_id INT UNSIGNED,
    pere_id INT UNSIGNED
);

INSERT INTO TMP_Animal
SELECT id, nom, espece_id, sexe, mere_id, pere_id 
FROM Animal
WHERE espece_id = 2;

1. Référence n'est pas occurrence

1
2
3
SELECT TMP_Animal.nom, TMP_Animal.sexe
FROM TMP_Animal
WHERE nom LIKE 'B%';

nom

sexe

Bagherra

M

Boucan

M

Boule

F

Bilba

F

Bambi

F

Ici, TMP_Animal apparaît trois fois dans la requête. Cela ne pose aucun problème, puisque la table n'est utilisée qu'une fois pour en extraire des données : dans le FROM.

2. Auto-jointure

On essaye d'afficher le nom des chats, ainsi que le nom de leur père quand on le connaît.

1
2
3
4
SELECT TMP_Animal.nom, TMP_Pere.nom AS pere 
FROM TMP_Animal
INNER JOIN TMP_Animal AS TMP_Pere 
    ON TMP_Animal.pere_id = TMP_Pere.id;
1
ERROR 1137 (HY000): Can't reopen table: 'TMP_Animal'

Cette fois, cela ne fonctionne pas : on extrait en effet des données de TMP_Animal, et de TMP_Animal AS TMP_Pere.

3. Sous-requête

On affiche le nom des animaux référencés comme pères.

1
2
3
SELECT nom
FROM TMP_Animal
WHERE id IN (SELECT pere_id FROM TMP_Animal);
1
ERROR 1137 (HY000): Can't reopen table: 'TMP_Animal'

À nouveau, on extrait des données de TMP_Animal à deux endroits différents : dans la requête et dans la sous-requête. Cela ne peut pas fonctionner.

Interaction avec les transactions

Un comportement assez intéressant lié aux tables temporaires concerne les transactions. On a vu que les commandes de création d'objets en tout genre provoquaient la validation implicite de la transaction dans laquelle la commande était faite. Ainsi, CREATE TABLE provoque une validation implicite.

Mais ce n'est pas le cas pour les tables temporaires : CREATE TEMPORARY TABLE et DROP TEMPORARY TABLE ne valident pas les transactions.

Cependant ces deux commandes ne peuvent pas être annulées par un ROLLBACK.

Exemple

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
START TRANSACTION;

INSERT INTO Espece (nom_courant, nom_latin)
VALUES ('Gerbille de Mongolie', 'Meriones unguiculatus');

CREATE TEMPORARY TABLE TMP_Test (id INT);

ROLLBACK;

SELECT id, nom_courant, nom_latin, prix FROM Espece;

SELECT * FROM TMP_Test;

id

nom_courant

nom_latin

prix

1

Chien

Canis canis

200.00

2

Chat

Felis silvestris

150.00

3

Tortue d'Hermann

Testudo hermanni

140.00

4

Perroquet amazone

Alipiopsitta xanthops

700.00

5

Rat brun

Rattus norvegicus

10.00

6

Perruche terrestre

Pezoporus wallicus

20.00

1
Empty set (0.00 sec)

Il n'y a pas de gerbille dans nos espèces, puisque l'insertion a été annulée. Par contre, la création de la table TMP_Test, bien que faite à l'intérieur d'une transaction annulée, a bel et bien été exécutée. On n'obtient en effet aucune erreur lorsque l'on fait une sélection sur cette table (mais bien un résultat vide, puisqu'il n'y a aucune donnée dans cette table).

Méthodes alternatives de création des tables

Les deux méthodes de création de tables présentées ici sont valables pour créer des tables normales ou des tables temporaires. Elles se basent toutes les deux sur des tables et/ou des données préexistantes. Le choix de présenter ces méthodes dans le cadre des tables temporaires s'explique par le fait qu'en général, celles-ci sont créées pour stocker des données provenant d'autres tables, et par conséquent, sont souvent créées en utilisant une de ces deux méthodes.

Créer une table à partir de la structure d'une autre

Il est possible de créer la copie exacte d'une table, en utilisant la commande suivante :

1
2
CREATE [TEMPORARY] TABLE nouvelle_table
LIKE ancienne_table;

Les types de données, les index, les contraintes, les valeurs par défaut, le moteur de stockage, toutes les caractéristiques de ancienne_table seront reproduites dans nouvelle_table. Par contre, les données ne seront pas copiées : nouvelle_table sera vide.

Exemple : reproduction de la table Espece.

1
2
3
4
5
6
CREATE TABLE Espece_copy
LIKE Espece;

DESCRIBE Espece;

DESCRIBE Espece_copy;

Les deux commandes DESCRIBE renvoient exactement la même chose :

Field

Type

Null

Key

Default

Extra

id

smallint(6) unsigned

NO

PRI

NULL

auto_increment

nom_courant

varchar(40)

NO

NULL

nom_latin

varchar(40)

NO

UNI

NULL

description

text

YES

NULL

prix

decimal(7,2) unsigned

YES

NULL

Ensuite, pour remplir la nouvelle table avec tout ou partie des données de la table d'origine, il suffit d'utiliser la commande INSERT INTO ... SELECT.

Exemple

1
2
3
4
5
6
INSERT INTO Espece_copy
SELECT * FROM Espece
WHERE prix < 100;

SELECT id, nom_courant, prix 
FROM Espece_copy;

id

nom_courant

prix

5

Rat brun

10.00

6

Perruche terrestre

20.00

Tables temporaires

Si l'on crée une table temporaire avec cette commande, tous les attributs de la table d'origine seront conservés, sauf les clés étrangères, puisqu'on ne peut avoir de clé étrangère dans une table temporaire.

Exemple : copie de la table Animal

1
2
3
4
5
6
7
8
CREATE TEMPORARY TABLE Animal_copy
LIKE Animal;

INSERT INTO Animal (nom, sexe, date_naissance, espece_id)
VALUES ('Mutant', 'M', NOW(), 12);

INSERT INTO Animal_copy (nom, sexe, date_naissance, espece_id)
VALUES ('Mutant', 'M', NOW(), 12);

Aucune espèce n'a 12 pour id, l'insertion dans Animal échoue donc à cause de la clé étrangère. Par contre, dans la table temporaire Animal_copy, l'insertion réussit.

Si on crée une table sur la base d'une table temporaire, la nouvelle table n'est pas temporaire par défaut. Pour qu'elle le soit, il faut obligatoirement le préciser à la création avec CREATE TEMPORARY TABLE.

Créer une table à partir de données sélectionnées

Cette seconde méthode ne se base pas sur la structure d'une table, mais sur les données récupérées par une requête SELECT pour construire une table, et y insérer des données. On fait donc ici d'une pierre deux coups : création de la table et insertion de données dans celle-ci.

1
2
CREATE [TEMPORARY] TABLE nouvelle_table
SELECT ...

Le type des colonnes de la nouvelle table sera déduit des colonnes sélectionnées. Par contre, la plupart des caractéristiques des colonnes sélectionnées seront perdues :

  • les index ;
  • les clés (primaires ou étrangères) ;
  • l'auto-incrémentation.

Les valeurs par défaut et les contraintes NOT NULL seront par contre conservées.

Exemple : suppression puis recréation d'une table temporaire Animal_copy contenant tous les rats de la table Animal.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
DROP TABLE Animal_copy;

CREATE TEMPORARY TABLE Animal_copy
SELECT *
FROM Animal
WHERE espece_id = 5;

DESCRIBE Animal;

DESCRIBE Animal_copy;

Field

Type

Null

Key

Default

Extra

id

smallint(6) unsigned

NO

PRI

NULL

auto_increment

sexe

char(1)

YES

NULL

date_naissance

datetime

NO

NULL

nom

varchar(30)

YES

MUL

NULL

commentaires

text

YES

NULL

espece_id

smallint(6) unsigned

NO

MUL

NULL

race_id

smallint(6) unsigned

YES

MUL

NULL

mere_id

smallint(6) unsigned

YES

MUL

NULL

pere_id

smallint(6) unsigned

YES

MUL

NULL

disponible

tinyint(1)

YES

1

Field

Type

Null

Key

Default

Extra

id

smallint(6) unsigned

NO

0

sexe

char(1)

YES

NULL

date_naissance

datetime

NO

NULL

nom

varchar(30)

YES

NULL

commentaires

text

YES

NULL

espece_id

smallint(6) unsigned

NO

NULL

race_id

smallint(6) unsigned

YES

NULL

mere_id

smallint(6) unsigned

YES

NULL

pere_id

smallint(6) unsigned

YES

NULL

disponible

tinyint(1)

YES

1

Les types de colonnes et les contraintes NOT NULL sont les mêmes, mais les index ont disparu, ainsi que l'auto-incrémentation.

Forcer le type des colonnes

On peut laisser MySQL déduire le type des colonnes du SELECT, mais il est également possible de préciser le type que l'on désire, en faisant attention à la compatibilité entre les types que l'on précise et les colonnes sélectionnées. On peut également préciser les index désirés, les clés et l'éventuelle colonne à auto-incrémenter.

La syntaxe est alors similaire à un CREATE [TEMPORARY] TABLE classique, si ce n'est qu'on rajoute une requête de sélection à la suite.

Exemple : recréation d'Animal_copy, en modifiant quelques types et attributs.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
DROP TABLE Animal_copy;

CREATE TEMPORARY TABLE Animal_copy (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    sexe CHAR(1),
    date_naissance DATETIME,
    nom VARCHAR(100),
    commentaires TEXT,
    espece_id INT NOT NULL,
    race_id INT,
    mere_id INT,
    pere_id INT,
    disponible BOOLEAN DEFAULT TRUE,
    INDEX (nom(10))
) ENGINE=InnoDB
SELECT *
FROM Animal
WHERE espece_id = 5;

DESCRIBE Animal_copy;

Field

Type

Null

Key

Default

Extra

id

int(10) unsigned

NO

PRI

NULL

auto_increment

sexe

char(1)

YES

NULL

date_naissance

datetime

YES

NULL

nom

varchar(100)

YES

MUL

NULL

commentaires

text

YES

NULL

espece_id

int(11)

NO

NULL

race_id

int(11)

YES

NULL

mere_id

int(11)

YES

NULL

pere_id

int(11)

YES

NULL

disponible

tinyint(1)

YES

1

Les colonnes id, espece_id, race_id, mere_id et pere_id ne sont plus des SMALLINT mais des INT, et seul id est UNSIGNED. Par contre, on a bien un index sur nom, et une clé primaire auto-incrémentée avec id. On n'a pas précisé de contrainte NOT NULL sur date_naissance, donc il n'y en a pas, bien que cette contrainte existe dans la table d'origine.

Nom des colonnes

Les noms des colonnes de la table créée correspondront aux noms des colonnes dans la requête SELECT. Il est bien sûr possible d'utiliser les alias dans celle-ci pour renommer une colonne. Cela implique que lorsque vous forcez le type des colonnes comme on vient de le voir, il est impératif que vos noms de colonnes correspondent à ceux de la requête SELECT, car l'insertion des données dans leurs colonnes respectives se fera sur la base du nom, et pas sur la base de la position.

Exemple : on recrée Animal_copy, mais les noms des colonnes sont dans le désordre, et certains ne correspondent pas à la requête SELECT.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
DROP TABLE Animal_copy;

CREATE TEMPORARY TABLE Animal_copy (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    nom VARCHAR(100),                            -- Ordre différent de la requête SELECT
    sexe CHAR(1),
    espece_id INT NOT NULL,                      -- Ordre différent de la requête SELECT
    date_naissance DATETIME,
    commentaires TEXT,
    race_id INT,
    maman_id INT,                                -- Nom de colonne différent de la requête SELECT
    papa_id INT,                                 -- Nom de colonne différent de la requête SELECT
    disponible BOOLEAN DEFAULT TRUE,
    INDEX (nom(10))
) ENGINE=InnoDB
SELECT id, sexe, date_naissance, nom, commentaires, espece_id, race_id, mere_id, pere_id, disponible
FROM Animal
WHERE espece_id = 5;

DESCRIBE Animal_copy;

Field

Type

Null

Key

Default

Extra

maman_id

int(11)

YES

NULL

papa_id

int(11)

YES

NULL

id

int(10) unsigned

NO

PRI

NULL

auto_increment

sexe

char(1)

YES

NULL

date_naissance

datetime

YES

NULL

nom

varchar(100)

YES

MUL

NULL

commentaires

text

YES

NULL

espece_id

int(11)

NO

NULL

race_id

int(11)

YES

NULL

mere_id

smallint(6) unsigned

YES

NULL

pere_id

smallint(6) unsigned

YES

NULL

disponible

tinyint(1)

YES

1

Les colonnes mere_id et pere_id de la requête SELECT ne correspondaient à aucune colonne définie par la commande CREATE TABLE. Ces colonnes ont donc été créées dans la nouvelle table, mais leur type a été déduit à partir du SELECT. Quant aux colonnes maman_id et papa_id, elles ont bien été créées bien qu'elles ne correspondent à rien dans la sélection. Elles ne contiendront simplement aucune donnée.

Voyons maintenant le contenu d'Animal_copy.

1
2
SELECT maman_id, papa_id, id, sexe, nom, espece_id, mere_id, pere_id 
FROM Animal_copy;

maman_id

papa_id

id

sexe

nom

espece_id

mere_id

pere_id

NULL

NULL

69

F

Baba

5

NULL

NULL

NULL

NULL

70

M

Bibo

5

72

73

NULL

NULL

72

F

Momy

5

NULL

NULL

NULL

NULL

73

M

Popi

5

NULL

NULL

NULL

NULL

75

F

Mimi

5

NULL

NULL

Les données sont dans les bonnes colonnes, et les colonnes maman_id et papa_id sont vides, contrairement à mere_id et pere_id.

Une conséquence intéressante de ce comportement est qu'il est tout à fait possible de préciser le type et les attributs pour une partie des colonnes uniquement.

Exemple : Recréation d'Animal_copy. Cette fois on ne précise le type et les attributs que de la colonne id et on ajoute un index sur nom.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
DROP TABLE Animal_copy;

CREATE TEMPORARY TABLE Animal_copy (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    INDEX (nom(10))
) ENGINE=InnoDB
SELECT *
FROM Animal
WHERE espece_id = 5;

DESCRIBE Animal_copy;

Field

Type

Null

Key

Default

Extra

id

int(10) unsigned

NO

PRI

NULL

auto_increment

sexe

char(1)

YES

NULL

date_naissance

datetime

NO

NULL

nom

varchar(30)

YES

MUL

NULL

commentaires

text

YES

NULL

espece_id

smallint(6) unsigned

NO

NULL

race_id

smallint(6) unsigned

YES

NULL

mere_id

smallint(6) unsigned

YES

NULL

pere_id

smallint(6) unsigned

YES

NULL

disponible

tinyint(1)

YES

1

Réunir les données de plusieurs tables

Puisque cette méthode de création de table se base sur une requête de sélection, cela signifie qu'on peut très bien créer une table sur la base d'une partie des colonnes d'une table existante. Cela signifie également que l'on peut créer une table à partir de données provenant de plusieurs tables différentes. Bien entendu, une table ne pouvant avoir deux colonnes de même nom, il ne faut pas oublier d'utiliser les alias pour renommer certaines colonnes en cas de noms dupliqués.

Exemple 1 : création de Client_mini, qui correspond à une partie de la table Client.

1
2
3
CREATE TABLE Client_mini
SELECT nom, prenom, date_naissance
FROM Client;

Exemple 2 : création de Race_espece, à partir des tables Espece et Race.

1
2
3
4
CREATE TABLE Race_espece
SELECT Race.id, Race.nom, Espece.nom_courant AS espece, Espece.id AS espece_id
FROM Race
INNER JOIN Espece ON Espece.id = Race.espece_id;

Utilité des tables temporaires

Les tables temporaires n'existant que le temps d'une session, leur usage est limité à des situations précises.

Gain de performance

Si, dans une même session, vous devez effectuer des calculs et/ou des requêtes plusieurs fois sur le même set de données, il peut être intéressant de stocker ce set de données dans une table temporaire, pour travailler sur cette table. En effet, une fois vos données de travail isolées dans une table temporaire, les requêtes vous servant à sélectionner les données qui vous intéressent seront simplifiées, donc plus rapides.

Typiquement, imaginons qu'on désire faire une série de statistiques sur les adoptions de chiens.

  • Quelles races sont les plus demandées ?
  • Y a-t-il une période de l'année pendant laquelle les gens adoptent beaucoup ?
  • Nos clients ayant adopté un chien sont-ils souvent dans la même région ?
  • Les chiens adoptés sont-ils plutôt des mâles ou des femelles ?

On va avoir besoin de données provenant des tables Animal, Race, Client et Adoption, en faisant au minimum une jointure à chaque requête pour n'avoir que les données liées aux chiens. Il peut dès lors être intéressant de stocker toutes les données dont on aura besoin dans une table temporaire.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
CREATE TEMPORARY TABLE TMP_Adoption_chien
SELECT Animal.id AS animal_id, Animal.nom AS animal_nom, Animal.date_naissance AS animal_naissance, Animal.sexe AS animal_sexe, Animal.commentaires AS animal_commentaires,
Race.id AS race_id, Race.nom AS race_nom, 
Client.id AS client_id, Client.nom AS client_nom, Client.prenom AS client_prenom, Client.adresse AS client_adresse, 
Client.code_postal AS client_code_postal, Client.ville AS client_ville, Client.pays AS client_pays, Client.date_naissance AS client_naissance,
Adoption.date_reservation AS adoption_reservation, Adoption.date_adoption AS adoption_adoption, Adoption.prix
FROM Animal
LEFT JOIN Race ON Animal.race_id = Race.id
INNER JOIN Adoption ON Animal.id = Adoption.animal_id
INNER JOIN Client ON Client.id = Adoption.client_id
WHERE Animal.espece_id = 1;

Toutes les requêtes pour obtenir les statistiques et informations demandées pourront donc se faire directement sur TMP_Adoption_chien, ce qui sera plus rapide que de refaire chaque fois une requête avec jointure(s). Il peut bien sûr être intéressant d'ajouter des index sur les colonnes qui serviront souvent dans les requêtes.

Tests

Il arrive qu'on veuille tester l'effet des instructions, avant de les appliquer sur les données. Pour cela, on peut par exemple utiliser les transactions, et annuler ou valider les requêtes selon que l'effet produit correspond à ce qui était attendu ou non. Une autre solution est d'utiliser les tables temporaires. On crée des tables temporaires contenant les données sur lesquelles on veut faire des tests, on effectue les tests sur celles-ci, et une fois qu'on est satisfait du résultat, on applique les mêmes requêtes aux vraies tables. Cette solution permet de ne pas risquer de valider inopinément des requêtes de test. Sans oublier qu'il n'est pas toujours possible d'utiliser les transactions : si les tables sont de type MyISAM, les transactions ne sont pas disponibles. De même, les transactions sont inutilisables si les tests comprennent des requêtes provoquant une validation implicite des transactions.

Petite astuce : pour tester une série d'instructions à partir d'un fichier (en utilisant la commande SOURCE), il est souvent plus simple de créer des tables temporaires ayant le même nom que les tables normales, qui seront ainsi masquées. Il ne sera alors pas nécessaire de modifier le nom des tables dans les requêtes à exécuter par le fichier selon qu'on est en phase de test ou non.

Sets de résultats et procédures stockées

Lorsque l'on crée une procédure stockée, on peut utiliser les paramètres OUT et INOUT pour récupérer les résultats de la procédure. Mais ces paramètres ne peuvent contenir qu'un seul élément.

Que faire si l'on veut récupérer plusieurs lignes de résultats à partir d'une procédure stockée ?

On peut avoir besoin de récupérer le résultat d'une requête SELECT, ou une liste de valeurs calculées dans la procédure. Ou encore, on peut vouloir passer un set de résultats d'une procédure stockée à une autre.

Une solution est d'utiliser une table temporaire pour stocker les résultats qu'on veut utiliser en dehors de la procédure.

Exemple : création par une procédure d'une table temporaire stockant les adoptions qui ne sont pas en ordre de paiement.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
DELIMITER |
CREATE PROCEDURE table_adoption_non_payee()
BEGIN
    DROP TEMPORARY TABLE IF EXISTS Adoption_non_payee;

    CREATE TEMPORARY TABLE Adoption_non_payee
    SELECT Client.id AS client_id, Client.nom AS client_nom, Client.prenom AS client_prenom, Client.email AS client_email,
           Animal.nom AS animal_nom, Espece.nom_courant AS espece, Race.nom AS race, 
           Adoption.date_reservation, Adoption.date_adoption, Adoption.prix
    FROM Adoption
    INNER JOIN Client ON Client.id = Adoption.client_id
    INNER JOIN Animal ON Animal.id = Adoption.animal_id
    INNER JOIN Espece ON Espece.id = Animal.espece_id
    LEFT JOIN Race ON Race.id = Animal.race_id
    WHERE Adoption.paye = FALSE; 
END |
DELIMITER ;

CALL table_adoption_non_payee();

SELECT client_id, client_nom, client_prenom, animal_nom, prix 
FROM Adoption_non_payee;

client_id

client_nom

client_prenom

animal_nom

prix

9

Corduro

Anaelle

Bavard

700.00

10

Faluche

Eline

Dana

140.00

11

Penni

Carine

Pipo

630.00

12

Broussaille

Virginie

Mimi

10.00


En résumé

  • Une table temporaire est une table qui n'existe que pour la session dans laquelle elle a été créée. Dès que la session se termine, les tables temporaires sont supprimées.
  • Une table temporaire est créée de la même manière qu'une table normale. Il suffit d'ajouter le mot-clé TEMPORARY avant TABLE.
  • On peut créer une table (temporaire ou non) à partir de la structure d'une autre table avec CREATE [TEMPORARY] TABLE nouvelle_table LIKE ancienne_table;.
  • On peut créer une table à partir d'une requête SELECT avec CREATE [TEMPORARY] TABLE SELECT ...;.
  • Les tables temporaires permettent de gagner en performance lorsque, dans une session on doit exécuter plusieurs requêtes sur un même set de données.
  • On peut utiliser les tables temporaires pour créer des données de test.
  • Enfin, les tables temporaires peuvent être utilisées pour stocker un set de résultats d'une procédure stockée.