Transfert vers une nouvelle table
On peut envisager de créer une nouvelle table destinée à contenir les données qui sont à la fois relatives à l'employé et à l'entreprise :
CREATE TABLE gestion (
matricule INTEGER PRIMARY KEY REFERENCES employés,
service CHAR(2) REFERENCES services,
projet CHAR(4) REFERENCES projets,
barème CHAR(4),
ancienneté SMALLINT
);
matricule INTEGER PRIMARY KEY REFERENCES employés,
service CHAR(2) REFERENCES services,
projet CHAR(4) REFERENCES projets,
barème CHAR(4),
ancienneté SMALLINT
);
Étant donné les relations d'intégrité référentielle qui figurent dans l'instruction ci-dessus, la table "projets" destinée à contenir en clair le nom des projets doit bien sûr avoir été préalablement créée:
CREATE TABLE projets (
projet_id CHAR(4) PRIMARY KEY,
dénomination CHAR VARYING(25)
);
projet_id CHAR(4) PRIMARY KEY,
dénomination CHAR VARYING(25)
);
Avant de supprimer la colonne "service" de la table employés, il faut d'abord en transférer les données vers la nouvelle table gestion.
Nous pouvons procéder avec cette instruction SQL:
insert into gestion (matricule, service)
select matricule, service
from employés
order by matricule
;
select matricule, service
from employés
order by matricule
;
ou dans un terminal psql (nous utilisons PostgreSQL) avec la méta-commande \copy:
\copy employés (matricule, service) to matr-serv
\copy gestion (matricule, service) from matr-serv
\copy gestion (matricule, service) from matr-serv
Se connectant en tant que super-utilisateur postgresql, nous pouvons utiliser la commande COPY:
Notons que le fichier de destination sera créé sur le serveur (même si sur la machine client existe un /var/lib/postgresql).
Ce fichier aura comme propriétaire postgres: il faut donc indiquer un chemin conduisant là où postgres a le droit d'écrire.
Si le volume de données à traiter est très important, cette solution est à privilégier puisqu'elle évite qu'un nombre de données important ne transite par la connexion client/serveur.
Transfert vers une table existante
Nous avons transféré le contenu de la colonne "service" depuis la table "employés" vers une table nouvellement créée.
Nous pouvons aussi considérer que la table cible (gestion) existe déjà.
Ajoutons-y la colonne service:
ALTER TABLE gestion
ADD COLUMN service CHAR(2) REFERENCES services
;
ADD COLUMN service CHAR(2) REFERENCES services
;
Les relations d'intégrité référentielle existantes impliquent que tous les matricules de la table "gestion" correspondent à des matricules de la table "employés", mais l'inverse n'est pas nécessairement vrai.
Il convient tout d'abord d'insérer dans "gestion" les matricules qui n'y existent pas:
insert into gestion (matricule, service)
select matricule, service
from employés
where not exists
(select *
from gestion
where gestion.matricule = employés.matricule)
order by matricule
;
select matricule, service
from employés
where not exists
(select *
from gestion
where gestion.matricule = employés.matricule)
order by matricule
;
Les rangées nouvellement insérées dans la table gestion possèdent la bonne valeur de "service" (celle de la table employés). Pour toutes les autres rangées, "service" a la valeur NULL.
Il faut donc effectuer une mise à jour, avec par exemple l'instruction SQL:
UPDATE gestion
SET service = (SELECT service
FROM employés
WHERE employés.matricule = gestion.matricule)
;
SET service = (SELECT service
FROM employés
WHERE employés.matricule = gestion.matricule)
;
Mais alors toutes les rangées (dont les nouvelles) seraient concernées par la mise à jour.
Aussi nous préférons agir plus finement avec cette instruction:
UPDATE gestion
SET service = employés.service
FROM employés
WHERE employés.matricule = gestion.matricule
AND employés.service <> gestion.service
;
SET service = employés.service
FROM employés
WHERE employés.matricule = gestion.matricule
AND employés.service <> gestion.service
;
(Remarque: l'utilisation de la clause FROM dans une instruction UPDATE n'est pas autorisée dans le langage SQL standard)
Procédons (après avoir mis l'instruction SQL dans le fichier update-gestion.sql):
Une seule rangée mise à jour! Il y a un problème: nous sommes tombés dans le piège du null.
La seule mise à jour effectuée est due certainement à ce que "service" a changé dans la table "employés" pour une des rangées insérées.
Recommençons après avoir modifié l'instruction pour éviter le piège:
Tout est maintenant en ordre: il reste à supprimer la colonne "service" de la table "employés":
ALTER TABLE employés
DROP service
;
DROP service
;
Adaptation des formulaires libreoffice
Évidemment dès cet instant le nom du service ne s'affiche plus dans les formulaires que nous avons considérés ici et là:
C'est normal puisque la zone de liste (listbox) qui fournit en clair le nom du service dépend du sous-formulaire "Employés" dont la source de données est la table "employés":
Nous allons régler le problème en cliquant droit sur l'icône du formulaire "Employés", en vue d'y rattacher un nouveau formulaire
que nous appellerons "Gestion"
La source de données en sera la table "gestion" et le lien avec "Employés" sera basé sur "matricule"
Il reste à effectuer un glisser-déposer des icônes qui conviennent vers le formulaire "Gestion":