PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#26 Re : Général » probleme de noob : requete et triggers » 12/01/2012 11:09:27

Merci Marc, grace à ces exemples j'ai pu arranger mon code pour que la fonction et le trigger se créé dans postgres

CREATE FUNCTION fonction_increment_crearticle() RETURNS TRIGGER AS $$
BEGIN
UPDATE LGPUSERNEW 
	SET NBARTICLECREE = NBARTICLECREE+1
	WHERE nom=current_user;
END;
$$ LANGUAGE plpgsql;


CREATE TRIGGER fonction_increment_crearticle AFTER INSERT ON lgpsujet
FOR EACH ROW EXECUTE PROCEDURE fonction_increment_crearticle();

Pour info LGPSUJET est la table réelle, alors que ALLSUJET est une vue sur LGPSUJET

par contre quand je fais un INSERT dans ALLSUJET, j'ai le message d'erreur suivant :
ERREUR:  le contrôle a atteint la fin de la procédure trigger sans RETURN
CONTEXTE : fonction PL/pgsql « fonction_increment_crearticle »


je n'ai toujours pas compris à quoi sert précisément RETURNS. ici j'ai pas besoin de RETURNS mais si j'en met pas la fonction ne veut pas s'enregistrer. j'ai essayé avec RETURNS NULL, mais ça veut pas non plus

#28 Re : Général » probleme de noob : requete et triggers » 10/01/2012 18:32:11

gleu a écrit :

Marchera pas smile

Je parierais plutôt sur quelque chose comme ça :

UPDATE LGPUSERNEW SET NBARTICLECREE = tmp.count
FROM
(
  SELECT auteur, count(*)
  FROM ALLSUJET
  GROUP BY auteur
) tmp
WHERE tmp.auteur = nom;

je n'avais pas pensé à cette façon de procéder
ça fonctionne impeccablement, merci

------------------------------------------

par contre concernant les trigger, je suis toujours au point mort, j'ai pas compris grand chose aux explications qui ont été données ci-dessus. un exemple de code qui fonctionne me serait vraiment d'un grand secours, sachant que je dois faire d'autres triggers, dont un bcp plus complexe

revoici mon code :

CREATE FUNCTION fonction_increment_crearticle()
BEGIN
UPDATE LGPUTILS
    SET NBARTICLECREE = NBARTICLECREE+1
    WHERE nom=current_user;
END;

CREATE TRIGGER fonction_increment_crearticle AFERT INSERT ON allsujet
FOR EACH ROW EXECUTE PROCEDURE fonction_increment_crearticle();

#29 Re : Général » probleme de noob : requete et triggers » 10/01/2012 16:05:38

ma requête est sensée :
- lire la vue ALLSUJET groupée par auteur
- compter le nombre de sujets pour chacun d'eux
- et updater la colonne NBARTICLECREE de la vue LGPUSERNEW pour chacun d'eux

#30 Re : Général » probleme de noob : requete et triggers » 10/01/2012 01:59:41

j'ai modifié ma requête en suivant vos conseils et maintenant j'ai une autre erreur:

UPDATE LGPUSERNEW SET NBARTICLECREE =
    (SELECT count(numsujet)
    FROM ALLSUJET
    WHERE auteur =
    (SELECT distinct auteur
    FROM ALLSUJET,LGPUSERNEW
    WHERE nom=auteur)
    GROUP BY auteur) ;

ERREUR:  plus d'une ligne renvoyée par une sous-requête utilisée comme une expression

autre tentative :

UPDATE LGPUSERNEW SET NBARTICLECREE =
    (SELECT count(numsujet)
    FROM ALLSUJET
    WHERE auteur =
    (SELECT distinct nom
    from LGPUSERNEW)
    GROUP BY auteur );

ERREUR:  plus d'une ligne renvoyée par une sous-requête utilisée comme une expression

je craque....

-----------------------------------

et pour le trigger, voila ce que j'ai essayé de faire :
incrémentation automatique du compteur NBARTICLECREE d'un utilisateur à chaque fois qu'il fait un nouvel insert dans la vue ALLSUJET

CREATE FUNCTION fonction_increment_crearticle() RETURNS ????
BEGIN
UPDATE LGPUSERNEW
    SET NBARTICLECREE = NBARTICLECREE+1
    WHERE nom=current_user;
END;

CREATE TRIGGER fonction_increment_crearticle AFERT INSERT ON allsujet
FOR EACH ROW EXECUTE PROCEDURE fonction_increment_crearticle();

je n'ai pas trouvé de doc suffisamment explicite (en français) qui explique si je dois mettre un returns ou pas... je suis en plein brouillard !
merci pour votre aide

#31 Général » probleme de noob : requete et triggers » 09/01/2012 22:33:19

Morby
Réponses : 16

toujours sur mon projet scolaire "réalisez la BD pour un mini-wiki" j'approche du bout mais je bloque.... voici mes tables

table des utilisateurs

DROP TABLE LGPUTILS CASCADE;
CREATE TABLE LGPUTILS
       (NUMUSER SERIAL,
        NOM VARCHAR(25) PRIMARY KEY,
    PASSWORD VARCHAR(25) NOT NULL,
    NBARTICLECREE INTEGER DEFAULT '0'
    );

-- droits d'accès pour la séquence (SERIAL)
GRANT USAGE on lgputils_numuser_seq to public;

--création d'une vue qui permet de voir tous les attributs de la table
DROP VIEW LGPUSERNEW;
CREATE VIEW LGPUSERNEW AS SELECT * FROM LGPUTILS;

grant select on LGPUSERNEW to public;
grant insert on LGPUSERNEW to public;
grant update on LGPUSERNEW to public;

-- création d'une règle sur la vue "LGPUSERNEW"
-- permettant l'insertion de nouveaux utilisateurs avec automatisme : nom = compte utilisateur
DROP RULE usernew_insert on LGPUSERNEW CASCADE;
CREATE RULE usernew_insert AS ON INSERT TO LGPUSERNEW DO INSTEAD
    INSERT INTO LGPUTILS VALUES
    (default,
    current_user,
    NEW.PASSWORD);

table des sujets publiés :

DROP TABLE LGPSUJET CASCADE;
CREATE TABLE LGPSUJET
       (NUMSUJET SERIAL PRIMARY KEY,
    AUTEUR VARCHAR(25) REFERENCES LGPUTILS (NOM),
    TITRE VARCHAR NOT NULL,
    DATEPARUTION DATE DEFAULT current_date,
    DATEMODIF DATE DEFAULT current_date,
    AUTEURMODIF VARCHAR(25) REFERENCES LGPUTILS (NOM),
    NUMBACKUP INTEGER DEFAULT '1',
    NBVUE INTEGER DEFAULT '0',
    TEXTE VARCHAR NOT NULL,
    PROTECTION INTEGER DEFAULT '1'    );

-- droits d'accès pour la séquence (SERIAL)
GRANT USAGE on lgpsujet_numsujet_seq to public;

-- création d'une vue qui permet de voir tous les sujets de la table
CREATE VIEW ALLSUJET AS SELECT * FROM LGPSUJET;
grant select on ALLSUJET to public;
grant insert on ALLSUJET to public;

-- création d'une règle qui permet l'insertion de nouveaux sujets à travers la vue ALLSUJET
DROP RULE sujet_insert ON ALLSUJET;
CREATE RULE sujet_insert AS ON INSERT TO ALLSUJET DO INSTEAD
    INSERT INTO LGPSUJET (auteur, titre, texte) VALUES
    (current_user,
    NEW.TITRE,
    NEW.TEXTE);

-- règle pour update du compteur "nbre d'article créés"
DROP RULE cpt_update on LGPUSER CASCADE;
CREATE RULE cpt_update AS ON UPDATE TO LGPUSERNEW
    DO INSTEAD
    UPDATE LGPUTILS
    SET nbarticlecree= NEW.nbarticlecree
    WHERE nom = old.nom;

______________________________________

Problème n°1 :
impossible de faire foncitonne ma requete ci-dessous, j'ai une erreur sur le WHERE de la ligne n°5 et je ne comprend pas pourquoi...

-- requete de mise à jour générale du compteur "nbre d'article créés"
-- en cas de suppression d'article
-- vues utilisées : LGPUSERNEW + ALLSUJET
UPDATE LGPUSERNEW SET NBARTICLECREE =
    (SELECT count(auteur), nom
    FROM ALLSUJET
    GROUP BY auteur
    WHERE auteur =
    (SELECT distinct auteur
    FROM ALLSUJET,LGPUSERNEW
    WHERE nom=auteur) ) ;

Problème n°2 :
j'ai un trigger à faire dans lequel je dois mettre la requête ci-dessous

-- requete d'incrémentation du compteur "nbre d'article créés"
-- a insérer dans un trigger de type "after" se déclenchant après nouvel INSERT dans ALLSUJET
UPDATE LGPUSERNEW
    SET NBARTICLECREE = NBARTICLECREE+1
    WHERE nom=current_user;

Le soucis est qu'on a fait 2h sur les triggers sous Oracle, mais pas du tout sous Postgres, d'après ce que j'ai vu sur les forums la syntaxe est radicalement différente (fonction + trigger), j'ai essayé de le faire mais j'arrive à rien... suite à ça j'ai 2 autres triggers plus complexes à faire, un modèle serait bienvenu pcq là, je patauge royalement et la date de remise du projet avance à grand pas sad

merci d'avance pour votre aide

#32 Re : Général » Prb avec fonction current_date dans une règle » 08/01/2012 02:58:50

merci bcp pour cette lumineuse explication, j'essayerais ça demain car là, j'ai les paupières qui tombent ^^

EDIT : ça fonctionne nickel, encore merci
sujet clos

#33 Général » Prb avec fonction current_date dans une règle » 07/01/2012 22:46:16

Morby
Réponses : 2

suite de mon mini-wiki sous postgres

table des utilisateurs :

DROP TABLE LGPUTILS CASCADE;
CREATE TABLE LGPUTILS
       (NUMUSER SERIAL,
        NOM VARCHAR(25) PRIMARY KEY,
    PASSWORD VARCHAR(25) NOT NULL,
    NBARTICLECREE INTEGER DEFAULT '0'
    );

-- droits d'accès pour la séquence (SERIAL)
GRANT USAGE on lgputils_numuser_seq to public;

--création d'une vue qui permet de voir tous les attributs de la table
DROP VIEW LGPUSERNEW;
CREATE VIEW LGPUSERNEW AS SELECT * FROM LGPUTILS;

grant select on LGPUSERNEW to public;
grant insert on LGPUSERNEW to public;
grant update on LGPUSERNEW to public;

-- création d'une règle sur la vue "LGPUSERNEW"
-- permettant l'insertion de nouveaux utilisateurs avec automatisme : nom = compte utilisateur
DROP RULE usernew_insert on LGPUSERNEW CASCADE;
CREATE RULE usernew_insert AS ON INSERT TO LGPUSERNEW DO INSTEAD
    INSERT INTO LGPUTILS VALUES
    (default,
    current_user,
    NEW.PASSWORD);

table des sujets

DROP TABLE LGPSUJET CASCADE;
CREATE TABLE LGPSUJET
       (NUMSUJET SERIAL PRIMARY KEY,
    AUTEUR VARCHAR(25) REFERENCES LGPUTILS (NOM),
    TITRE VARCHAR NOT NULL,
    DATEPARUTION DATE DEFAULT current_date,
    DATEMODIF DATE DEFAULT current_date,
    AUTEURMODIF VARCHAR(25) REFERENCES LGPUTILS (NOM),
    NUMBACKUP INTEGER DEFAULT '1',
    NBVUE INTEGER DEFAULT '0',
    TEXTE VARCHAR NOT NULL,
    PROTECTION INTEGER DEFAULT '1'
    );

-- droits d'accès pour la séquence (SERIAL)
GRANT USAGE on lgpsujet_numsujet_seq to public;

-- création d'une vue qui permet de voir tous les sujets de la table
CREATE VIEW ALLSUJET AS SELECT * FROM LGPSUJET;

grant select on ALLSUJET to public;
grant insert on ALLSUJET to public;

l'idée est que lorsque un utilisateur créé un sujet l'insert se fait à travers une vue "ALLSUJET", la requete se présente sous cette forme :
INSERT INTO LGPSUJET (TITRE,TEXTE)
    VALUES  ('test-creation','texte muet');
- le n° de sujet est automatique avec la fonction "serial"
- le nom de l'auteur est automatique avec la fonction "current_user"
- les dates de parution et de modification prennent automatiquement la date du jour (DEFAULT current_date)

j'essaye donc de créer ma vue "ALLSUJET" :

DROP RULE sujet_insert ON ALLSUJET;
CREATE RULE sujet_insert AS ON INSERT TO ALLSUJET DO INSTEAD
    INSERT INTO LGPSUJET VALUES
    (default,
    current_user,
    NEW.TITRE,
    NEW.TEXTE);

et là, c'est le drame :

ERREUR:  la colonne « dateparution » est de type date mais l'expression est de type character varying
LIGNE 6 : NEW.TEXTE);
          ^
ASTUCE : Vous devez réécrire l'expression ou lui appliquer une transformation de type.

je ne comprend pas du tout l'erreur...

par acquis de conscience j'ai fait un test d'insert directement dans la table et ça fonctionne très bien :

INSERT INTO LGPSUJET (TITRE,TEXTE) VALUES  ('test-creation','texte muet');

select * from lgpsujet;
numsujet | auteur |     titre     | dateparution | datemodif  | auteurmodif | numbackup | nbvue |   texte    | protection
----------+--------+---------------+--------------+------------+-------------+-----------+-------+------------+------------
        1 |        | test-creation | 2012-01-07   | 2012-01-07 |             |         1 |     0 | texte muet |          1

galère galère... sad

#34 Re : Général » Prb d'insertion sur une table avec un SERIAL PRIMARY KEY » 07/01/2012 19:45:06

yesss, super, ça fonctionne, problème 2 résolu
un grand merci à toi smile

#35 Re : Général » Prb d'insertion sur une table avec un SERIAL PRIMARY KEY » 07/01/2012 18:41:16

Pour mon projet je suis sensé passer à 100% par des vues pour toutes actions insert/update sur mes tables, ça fait parti du cahier des charges sad

j'ai suivi tes conseils et supprimé le doublon de règle, maintenant j'ai uniquement :

DROP RULE usernew_insert on LGPUSERNEW CASCADE;

CREATE RULE usernew_insert AS ON INSERT TO LGPUSERNEW DO INSTEAD
    INSERT INTO LGPUTILS VALUES
    (default,
    current_user,
    NEW.PASSWORD);

- Avec compte admin créateur des tables -
INSERT INTO LGPUSERNEW (password) VALUES ('testSansNom');
insert à travers la vue LGPUSERNEW sans préciser ni le n° d'utilisateur (incrémentation auto avec SERIAL) ni le nom d'utilisateur
ça marche, merci, un premier prb de réglé wink


- Avec compte userA -
INSERT INTO LGPUSERNEW (password) VALUES ('testSansNom');
ERREUR:  droit refusé pour la séquence lgputils_numuser_seq
ça refuse de marcher, il semble que l'incrémentation automatique de numuser pose problème.... je ne comprend tjrs pas pourquoi

- Avec compte userA -
INSERT INTO LGPUSERNEW (nom,password) VALUES ('userA','PASS');
ERREUR:  droit refusé pour la séquence lgputils_numuser_seq
même en précisant le nom d'utilisateur dans la requete, pas moyen de faire un insert

- Avec compte userA -
INSERT INTO LGPUSERNEW VALUES (1,'userA','PASS');
ERREUR:  droit refusé pour la séquence lgputils_numuser_seq
même en précisant le numuser, pas moyen que ça marche

#36 Général » Prb d'insertion sur une table avec un SERIAL PRIMARY KEY » 07/01/2012 15:35:30

Morby
Réponses : 4

Bonjour à tous et meilleurs voeux

j'ai un projet à réaliser : un mini-wiki sans application, juste les tables à créer, faire les vues et les grants

voici ma table "comptes utilisateurs" créée avec le compte administrateur, sachant qu'après elle est sensée être utilisée par 3 comptes userA, userB et userC :

DROP TABLE LGPUTILS CASCADE;

CREATE TABLE LGPUTILS
       (NUMUSER SERIAL PRIMARY KEY,
        NOM VARCHAR(25) NOT NULL,
    PASSWORD VARCHAR(25) NOT NULL,
    NBARTICLECREE INTEGER DEFAULT '0'
    );

-- droits d'accès
grant select on LGPUTILS to public;
grant insert on LGPUTILS to public;
grant update on LGPUTILS to public;


--création d'une vue qui permet de voir tous les attributs de la table
DROP VIEW LGPUSERNEW;
CREATE VIEW LGPUSERNEW AS SELECT * FROM LGPUTILS;
select * from LGPUSERNEW;

grant select on LGPUSERNEW to public;
grant insert on LGPUSERNEW to public;
grant update on LGPUSERNEW to public;


-- EDIT : doublon de règles supprimé suite à l'intervention de dverite
-- création d'une règle sur la vue "LGPUSERNEW" permettant l'insertion de nouveaux utilisateurs
-- avec attribut "nom" automatique en fonction du compte utilisateur qui fait l'insertion
DROP RULE usernew_insert2 on LGPUSERNEW CASCADE;
CREATE RULE usernew_insert2 AS ON INSERT TO LGPUSERNEW DO INSTEAD
    INSERT INTO LGPUTILS VALUES
    (default,
    current_user,
    NEW.PASSWORD);

**********************

EDIT : problème 1 résolu
Probleme 1:
avec le compte admin, pas de souci pour insérer dans la table les nouveaux "utilisateurs", du moment que je précise la colonne "nom"
ex : INSERT INTO LGPUTILS (nom,password) VALUES ('user1','PASS');

par contre ma règle usernew_insert2 refuse de fonctionner. pourtant la règle a bien été crée sans erreur.
ex : INSERT INTO LGPUSERNEW (password) VALUES ('pass');
>> ERREUR:  une valeur NULL viole la contrainte NOT NULL de la colonne « nom »

**********************

Probleme 2:
à partir du compte utilisateur "userA", je parviens sans soucis à faire un select sur la table LGPUTILS et la vue LGPUSERNEW.
par contre quand j'essaye de faire un INSERT dans la table LGPUTILS ou dans la vue LGPUSERNEW ça ne marche qu'à moitié :

- si j'insère dans la table LGPUTILS en précisant le "numuser" ça marche :
INSERT INTO LGPUTILS VALUES (1,'userA','PASS');

- si j'insère dans la vue LGPUSERNEW  en précisant le "numuser" ça ne marche pas :
INSERT INTO LGPUSERNEW VALUES (1,'userA','PASS');
ERREUR:  droit refusé pour la séquence lgputils_numuser_seq

- si je ne précise pas le numuser (il est sensé se mettre tout seul avec la fonction SERIAL), ça ne marche pas non plus :
INSERT INTO LGPUTILS (nom,password) VALUES ('userA','PASS');
ERREUR:  droit refusé pour la séquence lgputils_numuser_seq


je ne comprend pas, un petit coup de main serait bienvenu.

#37 Re : Installation » Serveur sous Win7, comment s'y connecter depuis Linux sous Virtualbox » 29/12/2011 23:58:17

super, ça fonctionne, un grand merci ^^


depuis ma chambre d'étudiant, je passe par une Livebox en DHCP.
je doit déclarer donc déclarer l'adresse IP internet de la box dans mon fichier pg_hba.conf ?
comme ceci ? :
host    all             all            IP-de-la-box-de-ma-chambre-etudiant            md5

est-ce que je devrais aussi paramétrer la box de ma chambre d'étudiant pour router le port 5432 ?

#38 Re : Installation » Serveur sous Win7, comment s'y connecter depuis Linux sous Virtualbox » 29/12/2011 19:58:13

effectivement, je n'ai pas créé d'utilisateurs et quand je me suis connecté sous windows j'ai utilisé le log postgres
je n'ai pas non plus créé de base spécifique, ya juste une base nommée postgres dont voici le détail :
CREATE DATABASE postgres
  WITH OWNER = postgres
       ENCODING = 'UTF8'
       TABLESPACE = pg_default
       LC_COLLATE = 'French, France'
       LC_CTYPE = 'French, France'
       CONNECTION LIMIT = -1;

COMMENT ON DATABASE postgres
  IS 'default administrative connection database';

------------------

voila ce que donne le code que vous m'avez indiqué sur ma VM-Fedora :

[morby@VM-Fedora ~]$ psql -h 192.168.1.11 -U postgres
psql: FATAL:  aucune entre dans pg_hba.conf pour l'hte  192.168.1.11 , utilisateur  postgres ,
base de donnes  postgres , SSL inactif

ou encore :
[morby@VM-Fedora ~]$ psql -h 192.168.1.11 -U postgres postgres
psql: FATAL:  aucune entre dans pg_hba.conf pour l'hte  192.168.1.11 , utilisateur  postgres ,
base de donnes  postgres , SSL inactif


sad

#39 Re : Installation » Serveur sous Win7, comment s'y connecter depuis Linux sous Virtualbox » 29/12/2011 18:38:25

merci pour cette réponse rapide, adresse IP masquée smile

au niveau local, mon Win7 arrive à pinger l'adresse IP virtuelle de la VM en 127.0.0.1
de meme ma VM arrive à pinger l'IP locale de mon win7 en 192.3168.1.11

pour ce qui est de l'ouverture de ports sur mon routeur/firewall pour permettre la connexion extérieure, je suppose que je dois ouvrir en UDP+TCP le port 5432 ?


par contre je ne sais tjrs pas ce que je dois taper sous linux pour tenter d'établir la connexion à la base !

quand je veux me connecter sur le serveur de l'université je tape :
> ssh u0@bambou.xxxxxxxxxxxxxxxx.fr
ensuite on me demande un password et j'ai un prompt de type : u0@db:~$

ensuite je tape :
> psql template1
on me redemande un password, et là je peux commencer à bosser....

quelle adresse dois-je rentrer pour me connecter en locale, ou bien depuis l'extérieur ?

#40 Installation » Serveur sous Win7, comment s'y connecter depuis Linux sous Virtualbox » 29/12/2011 17:53:56

Morby
Réponses : 7

bonjour à tous, je suis étudiant (formation de reconversion), débutant complet en SGBD. D'habitude je travaille sur le serveur de l'université, mais pas mal de fonctions sont verrouillées, et pour les besoins d'un projet j'ai besoin d'avoir mon propre serveur afin de pouvoir créer des utilisateurs, faire des grant, etc...

Chez moi j'ai installé Postgres 9.1 (pgAdmin 1.14.1) sur mon PC fixe Windows 7, je peux m'y connecter avec l'outil SQL Shell, créer une table etc... ça fonctionne.  Pour mes cours je travaille sous Linux Fedora (15), lequel tourne sous Virtualbox 4.1.8 sur ce même ordi, mais aussi sur un ordi portable

MON PROBLEME : sur mon PC fixe, pas moyen depuis ma VM-Fedora de me connecter à la base qui, elle, tourne sous le Windows natif.
Quelle adresse dois-je taper en console linux pour me connecter ?

ma config Windows 7 :
IP Internet : xxxxxxxxxx
IP locale 192.168.1.11
masque : 255.255.255.0


ma config pg_hba.conf :
# TYPE  DATABASE        USER            ADDRESS                 METHOD

# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
#host    replication     postgres        127.0.0.1/32            md5
#host    replication     postgres        ::1/128                 md5


sur ce même PC, ma config Fedora 15 qui tourne en parallèle sous virtualbox :
IP : 127.0.0.1
masque : 255.0.0.0
paquet "psql" installé


Autre cas de figure : la semaine je bosse sur un PC portable depuis ma chambre d'étudiant, lui aussi sous Win7 avec une Fedora15 qui tourne sous virtualbox. Quelle adresse devrais-je rentrer pour me connecter à ma base qui tournera chez moi ?

j'ai conscience que ces question peuvent paraitre hautement stupides, mais quand on débute et qu'on est pas anglophone, c'est pas facile de trouver l'info, surtout sur des prbs aussi basiques...

Pied de page des forums

Propulsé par FluxBB