dimanche 26 avril 2015

Mise à jour table PostgreSQL

Sur une machine de bureau (appelée rigel), où est installé un serveur PostgreSQL, nous disposons d'une base de données bdtest.
La même base de données existe sur un ordinateur portable (aldebaran).
Au cours d'un voyage, des rangées ont été ajoutées à une table (nommée dépenses) sur l'ordinateur portable.
Il s'agit maintenant, travaillant depuis l'ordinateur portable, de mettre à jour la table dépenses sur l'ordinateur fixe.
Nous allons procéder simplement sans utilisation d'outils de synchronisation.
Evaluons tout d'abord la situation au niveau de l'ordinateur de bureau:

toto@aldebaran:~/SQL/bdtest$ psql bdtest -h rigel -t <<FIN
> SELECT max(référence)
> FROM dépenses
> FIN
Password: 
 2013-0023

2013-0023 n'est pas le mot de passe (celui-ci bien que tapé n’apparaît pas) mais bien le résultat du query.
Copions dans un fichier dépenses les rangées supplémentaires existant sur aldebaran:

toto@aldebaran:~/SQL/bdtest$ psql bdtest <<FIN
> \copy (SELECT * FROM dépenses \
> WHERE référence > '2013-0023') \
> TO dépenses
> FIN

Pour finir, connectons nous de nouveau à rigel pour copier les nouvelles rangées et vérifions ensuite que la mise à jour a bien été effectuée:

toto@aldebaran:~/SQL/bdtest$ psql bdtest -h rigel -t <<FIN
> \copy dépenses FROM dépenses
> SELECT max(référence)
> FROM dépenses
> FIN
Password: 
 2014-0019

En image:


jeudi 23 avril 2015

Meta-commande gset

Dans l'article Variables dans psql nous avons regretté le fait que l'instruction

SELECT ..
INTO ..

utilisée dans un terminal psql, serve à créer une nouvelle table et non à initialiser une variable.
En effet nous aurions aimé pouvoir exécuter quelque chose comme

SELECT code_u
INTO :code
FROM utilisations
WHERE signification = 'Santé';

et ensuite

SELECT *
FROM dépenses
WHERE code_u = :'code';

Mais cela ne fonctionne pas.

Une façon simple de contourner le problème consiste à envoyer l'instruction

SELECT code_u
FROM utilisations
WHERE signification = 'Santé'

vers le serveur avec la méta-commande gset et non avec un point-virgule.
La requête ne doit retourner qu'une rangée et chaque colonne de cette rangée sera stockée dans une variable portant le nom de la colonne.
Testons:



Il nous est loisible de donner à la variable un nom différent de celui prévu par défaut en modifiant l'instruction envoyée comme ceci:

SELECT code_u AS code
FROM utilisations
WHERE signification = 'Santé'

Testons:





Signalons que la deuxième instruction pourrait aussi s'écrire de la sorte:



Rappelons une autre solution présentée dans un billet précédent.
Il s'agit de créer une fonction avec

CREATE FUNCTION fdépenses(text)
RETURNS SETOF dépenses
AS $$
DECLARE
code dépenses.code_u%TYPE;
usage alias for $1;
BEGIN
SELECT code_u
INTO code
FROM utilisations
WHERE signification = usage;
RETURN QUERY SELECT *
FROM dépenses a WHERE code_u =  code  ORDER BY référence;        
END;
$$ LANGUAGE 'plpgsql';

dont l'utilisation conduit au même résultat: