OVH Cloud OVH Cloud

[postgres] Contrainte d'intégrité sur nombre de tuples

7 réponses
Avatar
Christophe CLEMENT
Bonjour,

Imaginons qu'on ait la table :

CREATE TABLE bidon(
ref INTEGER,
a INTEGER
);

Comment faire - en postgreSQL - pour ajouter une contrainte qui vérifie
qu'il y a au plus 3 tuples (lignes) dans la table qui ont la même
valeur de ref ?

J'ai essayé avec une assertion mais ça n'est pas encore implémenté :-(


Christophe

7 réponses

Avatar
Jean-Paul Argudo
Christophe CLEMENT wrote:
Bonjour,



Bonjour!

Imaginons qu'on ait la table :

CREATE TABLE bidon(
ref INTEGER,
a INTEGER
);

Comment faire - en postgreSQL - pour ajouter une contrainte qui vérifie
qu'il y a au plus 3 tuples (lignes) dans la table qui ont la même
valeur de ref ?



Je pense qu'en PostgreSQL comme dans d'autres SGBDR qui se respectent, vous
pouvez faire cela avec un trigger.

Voilà comment je ferais pour ma part (v.8.x.x à cause des $ dans le
plpgsql):

CREATE TABLE test (
ref integer,
b integer
);

CREATE FUNCTION test_tripl() RETURNS trigger AS $test_stamp$
DECLARE
compte integer;
BEGIN

select count(*) into compte
from test
where ref = NEW.ref;

-- vous êtes en trigger BEFORE soit =3 ou plus...
if compte>=3 then
RAISE EXCEPTION 'pas plus de 3 tuples avec ref= %', NEW.ref;
END IF;

RETURN NEW;
END;
$test_stamp$ LANGUAGE plpgsql;


CREATE TRIGGER test_stamp BEFORE INSERT OR UPDATE ON test
FOR EACH ROW EXECUTE PROCEDURE test_tripl();


tests=# insert into test values (1,1);
INSERT 2665136 1
tests=# insert into test values (1,2);
INSERT 2665137 1
tests=# insert into test values (1,3);
INSERT 2665138 1
tests=# insert into test values (1,4);
ERROR: pas plus de 3 tuples avec ref= 1



Voilà... :-)

NB: ne me remerciez pas trop, mais plutôt les gens qui se cassent la tête à
écrire de docs, et à ceux qui font pareil pour les traduire

(cf
http://traduc.postgresqlfr.org/pgsql-8.0.2-fr/plpgsql-trigger.html#PLPGSQL-TRIGGER-EXAMPLE)

Merci d'utiliser PostgreSQL !

--
Jean-Paul Argudo
www.PostgreSQLFr.org
Avatar
Christophe CLEMENT
Le 05/05/2005 vers 21h34, Jean-Paul Argudo a écrit :


> Comment faire - en postgreSQL - pour ajouter une contrainte qui vérifie

$test_stamp$ LANGUAGE plpgsql;




Merci, mais là tu utilises du pl/pgsql et je veux faire ça qu'avec du
postgres standart.


Merci d'utiliser PostgreSQL !



Mais de rien :o)


Christophe
--
Pour me répondre, mon email en rot13 : hfrarg [ng] 75018 [qbg] bet
Avatar
Sébastien Lardière
Le Fri, 06 May 2005 08:46:02 +0000, Christophe CLEMENT a écrit :

Le 05/05/2005 vers 21h34, Jean-Paul Argudo a écrit :


> Comment faire - en postgreSQL - pour ajouter une contrainte qui vérifie



$test_stamp$ LANGUAGE plpgsql;




Merci, mais là tu utilises du pl/pgsql et je veux faire ça qu'avec du
postgres standart.



Tu veux dire en SQL seul, non ? parce que plpgsql fais parti par défaut
de PostgreSQL. Donc la proposition de JP était bonne.

Je ne vois pas comment faire ça sans procédure stockée.

--
Sébastien
Avatar
Christophe CLEMENT
Le 06/05/2005 vers 17h24, Sébastien_Lardière a
écrit :

Tu veux dire en SQL seul, non ? parce que plpgsql fais parti par défaut
de PostgreSQL. Donc la proposition de JP était bonne.



Admettons, mais quand je lance la fonction de JP dans mon terminal,
j'ai l'erreur :
ERROR: language "plpgsql" does not exist
HINT: You need to use "createlang" to load the language into the
database.

Donc même si dans la distribution standard du logiciel il y a ce
module, il n'est pas chargé par défaut, et comme je doit faire la base
de donnée en question dans le cadre d'un projet pour mes études il faut
que ça puisse tourner sur les machines de la FAC sans avoir à faire
trop de manipulation préalable...

Je ne vois pas comment faire ça sans procédure stockée.



Moi non plus :o) Sinon j'ai toujours la possibilité d'implémenter celà
dans mon programme qui interragit avec la base de données (php), donc
au pire je fais ça...


Christophe
--
Pour me répondre, mon email en rot13 : hfrarg [ng] 75018 [qbg] bet
Avatar
Sébastien Lardière
Le Fri, 06 May 2005 15:58:57 +0000, Christophe CLEMENT a écrit :

Le 06/05/2005 vers 17h24, Sébastien_Lardière a
écrit :

Tu veux dire en SQL seul, non ? parce que plpgsql fais parti par défaut
de PostgreSQL. Donc la proposition de JP était bonne.



Admettons, mais quand je lance la fonction de JP dans mon terminal,
j'ai l'erreur :
ERROR: language "plpgsql" does not exist
HINT: You need to use "createlang" to load the language into the
database.

Donc même si dans la distribution standard du logiciel il y a ce
module, il n'est pas chargé par défaut, et comme je doit faire la base
de donnée en question dans le cadre d'un projet pour mes études il faut
que ça puisse tourner sur les machines de la FAC sans avoir à faire
trop de manipulation préalable...



Exact, il n'est pas chargé par défaut.

Voir cette page :

http://traduc.postgresqlfr.org/pgsql-fr/xplang.html

Tu n'auras probablement pas les droits nécessaire, demande à un DBA de
ta FAC.

--
Sébastien
Avatar
Christophe CLEMENT
Le 07/05/2005 vers 11h49, Sébastien_Lardière a
écrit :

Exact, il n'est pas chargé par défaut.

Voir cette page :

http://traduc.postgresqlfr.org/pgsql-fr/xplang.html

Tu n'auras probablement pas les droits nécessaire, demande à un DBA de
ta FAC.



Ça m'a étonné mais il était déjà activé sur le serveur de la Fac ! Donc
je l'ai activé aussi sur ma machine ce matin, je vais utiliser cette
solution finalement. Si j'ai des soucis pour recoder la fonction ou le
trigger je reviens vous voir ;-)

Merci pour tout.


Christophe
--
Pour me répondre, mon email en rot13 : hfrarg [ng] 75018 [qbg] bet
Avatar
J.Pierre Pourrez
Le Mon, 09 May 2005 06:37:03 +0000, Christophe CLEMENT a écrit :

Le 07/05/2005 vers 11h49, Sébastien_Lardière a
écrit :

Exact, il n'est pas chargé par défaut.



Voir cette page :



http://traduc.postgresqlfr.org/pgsql-fr/xplang.html



Tu n'auras probablement pas les droits nécessaire, demande à un DBA de
ta FAC.



Ça m'a étonné mais il était déjà activé sur le serveur de la Fac !
Donc je l'ai activé aussi sur ma machine ce matin, je vais utiliser cette
solution finalement. Si j'ai des soucis pour recoder la fonction ou le
trigger je reviens vous voir ;-)



Tu peux faire la requête suivante dans ta base de données pour voir de
quels sont les langages procéduraux disponibles:
select * from pg_language;

Si plpgsql n'est pas disponible, essaie dans un xterm sur le serveur:
createlang plpgsql ton_sgbdr

En principe, être propriétaire de son sgbdr devrait suffire.

Cordialement
Jean-Pierre