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).

#1 Re : PL/pgSQL » Fonction concatenation » 15/02/2011 15:49:50

Impeccable, que dire de + sinon merci smile

J'ai pris la première solution.

Carole

#2 Re : PL/pgSQL » Fonction concatenation » 15/02/2011 14:52:46

Re,
J'ai fait la modif comme ceci

CREATE OR REPLACE FUNCTION lower_username()
  RETURNS trigger AS
$BODY$DECLARE
  tmp VARCHAR;
  cont integer;
BEGIN
  NEW."firstName" := initcap(NEW."firstName");
  NEW."lastName" := initcap(NEW."lastName");
  NEW.username := lower(NEW."firstName"||'.'||NEW."lastName");
  SELECT max(username) into tmp FROM users where "firstName" = NEW."firstName" and "lastName" = NEW."lastName";
  IF tmp IS NULL THEN
  -- ne rien faire
  ELSIF tmp = NEW.username THEN
    NEW.username :=lower(NEW."firstName"||'.'||NEW."lastName"||'1');
  ELSE
    SELECT MAX(TRIM(username,(NEW."firstName"||'.'||NEW."lastName"))::INT)+1 INTO cont FROM users where "firstName" = NEW."firstName" and "lastName" = NEW."lastName" and username != NEW.username;
    NEW.username := NEW."firstName"||'.'||NEW."lastName"||cont::TEXT;
  END IF;
  RETURN NEW;
END;

$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION concat_username() OWNER TO nuxeodm;

mais cela me génère cette erreur à l'execution du trigger insert

[WARNING  ] INSERT INTO users(
                        corps, section, article, n_emploi, type_candidature, civilite, "lastName", nom_matrimonial, "firstName", n_candidat, email)
            SELECT * FROM users_test
            WHERE not exists (
              SELECT n_candidat FROM users where users.n_candidat=users_test.n_candidat
            )
            ERREUR:  syntaxe en entrée invalide pour l'entier : « zap.zop1 »
            CONTEXT:  instruction SQL « SELECT MAX(TRIM(username,(NEW."firstName"||'.'||NEW."lastName"))::INT)+1           FROM users where "firstName" = NEW."firstName" and "lastName" = NEW."lastName" and username != NEW.username »
            PL/pgSQL function "lower_username" line 14 at instruction SQL

#3 Re : PL/pgSQL » Fonction concatenation » 15/02/2011 12:55:10

Me revoilou avec encore une petite question.
Comme vous me l'aviez conseillé, il faudrait que le username généré soit tout le temps un minuscule, peut importe si le lastname et le firstname est en majuscule ou pas.

j'ai essayé ceci avec la fonction lower():

CREATE OR REPLACE FUNCTION plip()
RETURNS TRIGGER AS
$$
DECLARE
  tmp VARCHAR;
  cont integer;
BEGIN
  NEW.firstname := initcap(NEW.firstname);
  NEW.lastname := initcap(NEW.lastname);
  NEW.lower(username) := NEW.firstname||'.'||NEW.lastname;
  SELECT max(username) into tmp FROM plop where firstname = NEW.firstname and lastname = NEW.lastname;
  IF tmp IS NULL THEN
  -- ne rien faire
  ELSIF tmp = NEW.username THEN
    NEW.lower(username) := NEW.firstname||'.'||NEW.lastname||1;
  ELSE
    SELECT MAX(TRIM(username,(NEW.firstname||'.'||NEW.lastname))::INT)+1 INTO cont FROM plop where firstname = NEW.firstname and lastname = NEW.lastname and username != NEW.username;
    NEW.lower(username) := NEW.firstname||'.'||NEW.lastname||cont;
  END IF;
  RETURN NEW;
END
$$
LANGUAGE PLPGSQL;

entre autres choses mais cela ne fonctionne pas. Où dois je insérer la fonction svp?

Carole

#4 Re : PSQL » chemin fichier csv » 14/02/2011 14:44:19

Merci pour votre réponse.
J'ai effectué la modif et j'obtiens l'erreur

ERREUR:  n'a pas pu ouvrir le fichier « Z:/1Commun/NUXEO 2011/users.csv » pour
une lecture : No such file or directory


en fait je pense que cela ne fonctionne pas du fait qu'il s'agit d'un lecteur réseau.

#5 PSQL » chemin fichier csv » 14/02/2011 13:03:07

carole_31
Réponses : 3

Bonjour,

Je rencontre un soucis avec psql dans une fenetre dos.

Je veux utiliser la commande "copy from" lorsque le chemin du fichier csv que je souhaite pointer est sur le disque C: cela fonctionne, par contre j'ai besoin de copier les données d' un csv situé sur un lecteur que j'ai monté (Z:) avec un connecteur réseau et je n'arrive pas à faire fonctionner le copy from.
COPY users_temp from 'Z:1Commun\\NUXEO 2011\\users.csv' using delimiters ',' WITH CSV HEADER;

J'obtiens cette erreur:
ATTENTION:  utilisation non standard de \\ dans une chaîne littérale
LIGNE 1 : COPY users_temp from 'Z:\\1Commun\\NUXEO 2011\\users.csv' us...
                               ^
ASTUCE : Utilisez la syntaxe de chaîne d'échappement pour les antislashs, c'es
t-Ã -dire E'\\'.
ERREUR:  n'a pas pu ouvrir le fichier « Z:\1Commun\NUXEO 2011\users.csv » pour
une lecture : No such file or directory

Pourriez vous m'aider svp?

Cordialement
Carole

#6 Re : Général » Faire "copy from csv" qui effectue un "insert or ignore + update" » 07/02/2011 12:59:40

Oui dans la table users, il peut y avoir des doublons sur le nom, prenom et c'est pour cela que le trigger générant des logins unique de type 'prenom.nom[1234...]' est nécessaire. Par contre dans les tables users et users_tampon il y a d'autres champs aussi, dont un 'n_candidat' qui est unique, donc je pensais que comme ce n° etait different, lors de l'insert un doublon de login ne sera pas généré.
Voici l'insert que je fais:
Oui dans la table users, il peut y avoir des doublons sur le nom, prenom et c'est pour cela que le trigger générant des logins unique de type 'prenom.nom[1234...]' est nécessaire. Par contre dans les tables users et users_tampon il y a d'autres champs aussi, dont un 'n_candidat' qui est unique, donc je pensais que comme ce n° etait different, lors de l'insert un doublon de login ne sera pas généré.
Lors de l'insert dans la table users je mets une condition 'WHERE not exists users.n_candidat=users_tampon.n_candidat'

Par contre je n'ai pas pu encore le tester en situation car mon trigger faisant le "truncate before copy" ne fonctionne pas.
voici ce que j'ai mis:

CREATE TRIGGER suppression
 BEFORE INSERT OR UPDATE
 ON users_tampon
 FOR EACH STATEMENT
 EXECUTE PROCEDURE vider_table(E'\\x');

CREATE OR REPLACE FUNCTION vider_table()
  RETURNS trigger AS
$BODY$
BEGIN 
   delete from users_tampon;
END;

J'ai essaye du coup en faisant un "delete from " à la place du truncate mais sans succès.

#7 Re : Général » Faire "copy from csv" qui effectue un "insert or ignore + update" » 07/02/2011 10:09:35

Bonjour,
Tout d'abord je vous remercie pour votre aide.

En fait il n'y pas pas d'écriture sur le csv directement. Le secrétariat possède le fichier sur un espace propre et en effectue une copie sur un espace partagé avec le serveur nuxeo à la fin de la journée. Ensuite dans la soirée, je lancerais un batch effectuant la "copy" des données du csv sur la base, dans une table tampon. Suivant vos conseils je vais faire un truncate de la table tampon avant que les données soient copiées (before copy c'est bien celà non?) et ensuite faire un "insert or ignore" de la table tampon vers la table "users" (où j'inclue 2 triggers qui génèrent un username + un password lors de l'insert).
Cela parait pas mal non?

Carole

#8 Général » Faire "copy from csv" qui effectue un "insert or ignore + update" » 04/02/2011 17:18:16

carole_31
Réponses : 13

Bonjour,

J'ai besoin d'alimenter une des tables de ma bdd via un fichier csv qui est alimenté au fur et à mesure.
Lorsque j'effectue la commande

 COPY users_test from 'C://users.csv' using delimiters ','  WITH CSV HEADER;

l'insertion des données dans la table users_test s'effectue mais mon soucis est que les données se rajoutent dans la table à chaque "copy", effectuant donc des doublons.
Si je rajoute une contrainte unique sur un champ de la table "users_test", alors la copy ne s'effectue pas car elle n'effectue pas un "insert or ignore".

sauriez vous comment je pourrais arriver à résoudre ce problème svp?
Je n'ai pas trouvé dans l'aide sur la commande "copy" pour l'instant. Si cela n'est pas possible avec cette commande, est ce qu'il existe une autre commande qui me permet d'obtenir le résultat souhaité?

amicalement
Carole

#9 Re : PL/pgSQL » Fonction concatenation » 04/02/2011 15:36:48

en local je teste sur la version p de postgres.
sur le serveur c'est la version 8.4 qui est installée.

J'ai testé le nouveau code et c'est tout simplement parfait. Merci beaucoup de tout coeur.

Carole

#10 Re : PL/pgSQL » Fonction concatenation » 04/02/2011 15:06:33

Re,
J'ai essayé le nouveau code amélioré mais l'exécution me génère l'erreur:
ERREUR:  l'opérateur n'est pas unique : text || integer
LINE 1: SELECT NEW.firstName||'.'||NEW.lastName || 1
                                                    ^
HINT:  N'a pas pu choisir un meilleur candidat pour l'opérateur. Vous devez ajouter une
conversion explicite de type.

#11 Re : PL/pgSQL » Fonction concatenation » 04/02/2011 12:40:23

Rholalalal MERCI vraiment beaucoup. C'est extra.
Pour un premier trigger tu assures smile .

Avec la commande copy cela ne marchait pas puisque dans le csv il n'y a pas de colonne "username" mais du coup je le fais en 2 fois : d'abord
- copy csv to users_temp
puis insertion des données de users_temp dans users (et génération auto du username donc)

Trop contente

Carole

#12 Re : PL/pgSQL » Fonction concatenation » 04/02/2011 10:45:53

Bonjour et merci à vous 2 pour votre aide. grace à vous je commence à voir le bout du tunnel.
J'ai inséré le code en rajoutant un

group by firstName, lastName

après le select car cela me renvoyait une erreur lors de l'exécution.

Lorsque je fait un

INSERT INTO users(lastName, firstName)  VALUES ('DUPON','TOTO');

Lors du premier insert, le username se génère parfaitement avec la valeur TOTO.DUPON

Par contre si je retente une autre insertion avec les memes valeurs, je n'obtiens pas TOTO.DUPON1 , TOTO.DUPON2, TOTO.DUPON3 ... mais cette erreur :
ERREUR:  syntaxe en entrée invalide pour l'entier : «  »

Carole

#13 Re : PL/pgSQL » Fonction concatenation » 03/02/2011 19:25:44

Oui le username est stocké dans la table plop.
Il permet aux utilisateurs de s'authentifier sur l'appli web en l'occurence Nuxeo.

Carole

#14 Re : PL/pgSQL » Fonction concatenation » 03/02/2011 17:32:19

tout d'abord merci pour m'aider à résoudre mon souci. Je ne sais pas si j'ai mal expliqué, ce qui est fort possible, ou si je ne comprends pas comment mettre en application ton exemple pour mon cas.
En fait la valeur username n'est pas inséré par ma requête d'insert. Le username est généré automatiquement via la fonction trigger.

CREATE TABLE plop( firstname VARCHAR, lastname VARCHAR, username VARCHAR);
INSERT INTO plop VALUES ('Jean','Dupont'),('Jean','Dupont'),('Jean','Dupont');

en fait j'insère les données via un fichier csv où le username ne figure pas. Et donc le fait de faire générer automatiquement le username via le trigger serait super pour çà.
du coup je ne suis pas arrivée à adapter ton script. Désolée d'être pénible et de t'embêter encore.

Désolée aussi pour le code dans l'image mais je n'ai pas eu le choix car le pare feu de ma boite bloquait l'envoi du code sur le forum.

Carole

#15 Re : PL/pgSQL » Fonction concatenation » 03/02/2011 16:03:40

Oui en fait il faudrait que jean.dupont2 soit crée et que l'incrément soit fait automatiquement par rapport au dernier chiffre inséré.... c'est encore + galère que ce que ce que je pensais.

#16 PL/pgSQL » Fonction concatenation » 03/02/2011 15:24:38

carole_31
Réponses : 21

Bonjour,
Je bloque sur un problème que je me permets de vous soumettre.
J'ai une table 'users' dans laquelle j'ai un champ 'username' avec un trigger "before insert" dont le résultat concatène la valeur de 2 autre champs  'firstname' et 'lastname'.

 BEGIN
    NEW.username=NEW.firstName ||'.' ||NEW.lastName ;
    RETURN NEW;
END;

Ceci fonctionne bien. Par contre je souhaite que avant chaque insert soit testé dans la table l'existance d'un meme champ 'lastname' et 'firstname' afin qu'il n'y ait pas de doublon pour les username. Il faudrait donc que si une ligne possède déja les mêmes valeurs 'lastname' et 'firstname' que celles qui vont être insérées, le username généré soit 'firstname'.'lastname'+ un chiffre incrémenté (exemple : toto.dupont1).

J'ai essayé ce genre de code ci dessous mais cela ne fonctionne pas, pourriez vous m'aider svp ?
texte.jpg

carole

Pied de page des forums

Propulsé par FluxBB