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 15/10/2008 16:05:11

Katagoto
Membre

Fonctions variables et arguments

Bonjour à toutes et à tous,

Je suis nouveau, j'ai tenter de crrée une fonction, mais je ne sais pas comment utiliser les arguments :
CREATE FUNCTION ri_ajoute_fils(IN tabletype character, IN pk_parent integer, IN nom character) RETURNS void AS
$BODY$
SELECT * FROM $NomTable AS C WHERE C.pk_categorie=$PkParent;

UPDATE $NomTable
SET BordDroit = BordDroit + 2
WHERE BordDroit >= C.BordDroit;

UPDATE $NomTable
SET BordGauche = BordGauche + 2
WHERE B.BordGauche >= C.BordGauche;

INSERT INTO $NomTable (BordDroit, BordGauche, nom) VALUES (C.BordDroit, C.BordDroit+1, $nom);$BODY$
LANGUAGE 'sql' VOLATILE;

Comment faire ?

Par avance merci de votre aide

PS : J'ai la V8.3.4 de PostGreSQL et j'ai fait cette fonction avec PgAdmin III

Hors ligne

#2 18/10/2008 11:23:12

Katagoto
Membre

Re : Fonctions variables et arguments

Bon,

J'ai tenté autre chose, quelqu'un peut m'expliquer pourquoi ça plante ?

Par avance merci de votre aide :

CREATE FUNCTION ri_ajoute_fils(IN character, IN integer, IN character) RETURNS void AS
$BODY$SELECT * FROM $1 AS C WHERE C.pk_categorie=$2;

UPDATE $1
SET BordDroit = BordDroit + 2
WHERE BordDroit >= C.BordDroit;

UPDATE $1
SET BordGauche = BordGauche + 2
WHERE B.BordGauche >= C.BordGauche;

INSERT INTO $1 (BordDroit, BordGauche, nom) VALUES (C.BordDroit, C.BordDroit+1, $3);$BODY$
LANGUAGE 'sql' VOLATILE;

Hors ligne

#3 18/10/2008 11:43:43

gleu
Administrateur

Re : Fonctions variables et arguments

Donner le message d'erreur pourrait aider.


Guillaume.

Hors ligne

#4 18/10/2008 12:00:00

Katagoto
Membre

Re : Fonctions variables et arguments

Oui, ça peut servir :


ERREUR:  erreur de syntaxe sur ou près de « $1 »
LIGNE 2 : $BODY$SELECT * FROM $1 AS C WHERE C.pk_categorie=$2;
                              ^

********** Erreur **********

ERREUR: erreur de syntaxe sur ou près de « $1 »
État SQL :42601
Caractère : 108

Hors ligne

#5 18/10/2008 12:08:01

gleu
Administrateur

Re : Fonctions variables et arguments

Les paramètres de la fonction ne peuvent pas figurer au niveau de la clause FROM. En fait, ils ne sont pas utilisables pour remplacer un nom d'objet (nom de table, nom de colonne, etc.).

Le seul moyen pour faire cela est d'utiliser le langage PL/pgsql.


Guillaume.

Hors ligne

#6 18/10/2008 17:46:10

Katagoto
Membre

Re : Fonctions variables et arguments

Ok, il est donc mieu de faire une fonction par table, ce code plante :

CREATE FUNCTION ri_ajoute_fils(IN integer, IN character) RETURNS void AS
$BODY$SELECT * FROM ri AS C WHERE C.id=$1;

UPDATE ri AS A
SET A.BordDroit = A.BordDroit + 2
WHERE A.BordDroit >= C.BordDroit;

UPDATE ri AS B
SET B.BordGauche = B.BordGauche + 2
WHERE B.BordGauche >= C.BordGauche;

INSERT INTO ri (BordDroit, BordGauche, nom) VALUES (C.BordDroit, C.BordDroit+1, $2);$BODY$
LANGUAGE 'sql' VOLATILE;

Erreur :

ERREUR:  la colonne a.borddroit n'existe pas
LIGNE 5 : SET A.BordDroit = A.BordDroit + 2
                            ^

********** Erreur **********

ERREUR: la colonne a.borddroit n'existe pas
État SQL :42703
Caractère : 151

Table :
-- Table: ri

-- DROP TABLE ri;

CREATE TABLE ri
(
  id serial NOT NULL,
  "BordDroit" integer,
  "BordGauche" integer,
  nom character(64),
  CONSTRAINT ri_pkey PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
ALTER TABLE ri OWNER TO katagoto;

Je comprend pas d'où ça vient...

Si quelqu'un à une idée...

Par avance merci de votre aide

Hors ligne

#7 18/10/2008 18:45:29

gleu
Administrateur

Re : Fonctions variables et arguments

Lire la documentation d'UPDATE semble une bonne idée pour commencer (http://docs.postgresql.fr/8.1/sql-update.html). Dans la section Paramètres, à colonne, il est indiqué :

Le nom d'une colonne dans table. Le nom de la colonne peut être qualifié avec un nom de sous-champ ou un indice de tableau, si nécessaire. Ne pas inclure le nom de la table dans la spécification d'une colonne cible -- par exemple, UPDATE tab SET tab.col = 1 est invalide.


Guillaume.

Hors ligne

#8 18/10/2008 18:59:25

Katagoto
Membre

Re : Fonctions variables et arguments

Même si je le met pas, ça plante...

Hors ligne

#9 21/10/2008 18:05:23

Katagoto
Membre

Re : Fonctions variables et arguments

Bonjour,

Je ne lâcherais rien, voilà mon code :

CREATE FUNCTION ri_ajoute_fils(IN integer, IN character) RETURNS void AS
$BODY$
UPDATE ri AS A
SET BordDroit = BordDroit + 2
FROM ri AS B
WHERE B.id = $1 AND A.BordDroit >= B.BordDroit;

UPDATE ri AS C
SET BordGauche = BordGauche + 2
FROM ri AS D
WHERE D.id = $1 AND C.BordDroit >= D.BordDroit;

INSERT INTO ri (BordDroite, BordGauche, nom)
VALUES ((SELECT BordDroite FROM ri WHERE id=$1)-2, (SELECT BordGauche FROM ri WHERE id=$1)-1, $2);
$BODY$
LANGUAGE 'sql' VOLATILE;

Ma Table :
-- Table: ri

-- DROP TABLE ri;

CREATE TABLE ri
(
  id serial NOT NULL,
  "BordDroit" integer,
  "BordGauche" integer,
  nom character(64),
  CONSTRAINT ri_pkey PRIMARY KEY (id),
  CONSTRAINT ri_id_key UNIQUE (id)
)
WITH (OIDS=FALSE);
ALTER TABLE ri OWNER TO katagoto;

Mon Erreur :

ERREUR:  la colonne « borddroit » n'existe pas
LIGNE 4 : SET BordDroit = BordDroit + 2
                          ^

********** Erreur **********

ERREUR: la colonne « borddroit » n'existe pas
État SQL :42703
Caractère : 112

Comment faire pour que ça marche ?

Par avance merci de votre aide

Hors ligne

#10 22/10/2008 14:41:07

Katagoto
Membre

Re : Fonctions variables et arguments

Voilà mon nouveau code :
CREATE FUNCTION ri_ajoute_fils(IN nomtable character, IN nom character, IN pk_parent integer) RETURNS void AS
$$
DECLARE
Bornes integer := SELECT BordDroite FROM $1 WHERE id=$3
BEGIN
UPDATE $1
SET BordDroit = BordDroit + 2
WHERE BordDroit >= Bornes;

UPDATE $1
SET BordGauche = BordGauche + 2
WHERE BordGauche >= Bornes;

INSERT INTO $1 (BordDroit, BordGauche, nom)
VALUES (Bornes, Bornes+1, $2);
END;
$$LANGUAGE 'plpgsql' VOLATILE;

Voilà mon nouveau problème :

ERREUR:  erreur de syntaxe sur ou près de « SELECT »
LIGNE 1 : SELECT  SELECT BordDroite FROM  $1  WHERE id= $2  BEGIN UPDA...
                  ^
REQUÊTE : SELECT  SELECT BordDroite FROM  $1  WHERE id= $2  BEGIN UPDATE  $1  SET BordDroit = BordDroit + 2 WHERE BordDroit >= Bornes
CONTEXTE : SQL statement in PL/PgSQL function "ri_ajoute_fils" near line 6

********** Erreur **********

ERREUR: erreur de syntaxe sur ou près de « SELECT »
État SQL :42601
Contexte : SQL statement in PL/PgSQL function "ri_ajoute_fils" near line 6

Où est-ce que j'ai planté encore ?

Par avance merci de votre aide

Hors ligne

#11 23/10/2008 17:34:06

SAS
Membre

Re : Fonctions variables et arguments

Katagoto a écrit :

Voilà mon nouveau code :
CREATE FUNCTION ri_ajoute_fils(IN nomtable character, IN nom character, IN pk_parent integer) RETURNS void AS
$$
DECLARE
Bornes integer := SELECT BordDroite FROM $1 WHERE id=$3

Une affectation de variable ne se fait pas de cette façon.

SELECT "BordDroite" into Bornes.

Pour commencer, je vous invite à modifier votre schéma pour supprimer la capitalisation des tables. Ca simpliefera grandement la suite.

Un certain nombre de vos erreurs viennent de problèmes entre des noms de tables à majuscules et des requêtes qui ne les utilisent pas.


Stéphane Schildknecht
Conseil, formations et support PostgreSQL
http://www.loxodata.com

Hors ligne

#12 25/10/2008 11:50:59

Katagoto
Membre

Re : Fonctions variables et arguments

Je pense que la casse n'est pas en cause, après la lecture du chapitre sur PL/pgsql j'arrive au code suivant :

CREATE FUNCTION ri_ajoute_fils(IN nomtable character, IN nom character, IN pk_parent integer) RETURNS void AS
$$
DECLARE
Bornes RECORD;
BEGIN
SELECT BordDroite INTO Bornes FROM nomtable WHERE id=pk_parent;

UPDATE nomtable
SET BordDroit = BordDroit + 2
WHERE BordDroit >= Bornes;

UPDATE nomtable
SET BordGauche = BordGauche + 2
WHERE BordGauche >= Bornes;

INSERT INTO nomtable (BordDroit, BordGauche, nom)
VALUES (Bornes, Bornes+1, nom);
END;
$$LANGUAGE 'plpgsql' VOLATILE;

Et donc à l'erreur suivante :

ERREUR:  erreur de syntaxe sur ou près de « $1 »
LIGNE 1 : SELECT BordDroite FROM  $1  WHERE id= $2
                                  ^
REQUÊTE : SELECT BordDroite FROM  $1  WHERE id= $2
CONTEXTE : SQL statement in PL/PgSQL function "ri_ajoute_fils" near line 4


********** Erreur **********

ERREUR: erreur de syntaxe sur ou près de « $1 »
État SQL :42601
Contexte : SQL statement in PL/PgSQL function "ri_ajoute_fils" near line 4

Il me semblait que Pl/pgslq permettait les variable à la clause FROM, ai-je mal lu ?

Par avance merci de votre aide

Hors ligne

#13 26/10/2008 20:43:18

Katagoto
Membre

Re : Fonctions variables et arguments

gleu a écrit :

Les paramètres de la fonction ne peuvent pas figurer au niveau de la clause FROM. En fait, ils ne sont pas utilisables pour remplacer un nom d'objet (nom de table, nom de colonne, etc.).

Le seul moyen pour faire cela est d'utiliser le langage PL/pgsql.

?

Hors ligne

#14 28/10/2008 16:22:10

frost242
Administrateur

Re : Fonctions variables et arguments

Et avec ça :

CREATE FUNCTION ri_ajoute_fils(IN nomtable character, IN nom character, IN pk_parent integer) RETURNS void AS
$$
DECLARE
  Bornes integer;
BEGIN
  EXECUTE SELECT "BordDroite" FROM nomtable WHERE id=pk_parent INTO Bornes ;

  EXECUTE UPDATE nomtable
    SET "BordDroit" = "BordDroit" + 2
  WHERE "BordDroit" >= Bornes;

  EXECUTE UPDATE nomtable
  SET "BordGauche" = "BordGauche" + 2
  WHERE "BordGauche" >= Bornes;

  EXECUTE INSERT INTO nomtable ("BordDroit", "BordGauche", nom)
  VALUES (Bornes, Bornes+1, nom);
END;
$$LANGUAGE 'plpgsql' VOLATILE;

Merci de lire le commentaire de SAS à propos de la capitalisation des noms de tables et de colonnes. PostgreSQL "minusculise" les noms des objets, sauf s'ils sont protégés par des doubles-quotes.


Thomas Reiss

Hors ligne

#15 28/10/2008 21:25:24

Katagoto
Membre

Re : Fonctions variables et arguments

CREATE OR REPLACE FUNCTION ri_ajoute_fils(nom_table character, nom character, pk_parent integer)
  RETURNS boolean AS
$BODY$
DECLARE
Bornes RECORD;
BEGIN
EXECUTE 'SELECT BordDroite INTO Bornes FROM '|| quote_indent (nom_table)||' WHERE id=pk_parent;
 
UPDATE '|| quote_indent (nom_table)||'
SET BordDroit = BordDroit + 2 
WHERE BordDroit >= Bornes;
 
UPDATE '|| quote_indent (nom_table)||'
SET BordGauche = BordGauche + 2 
WHERE BordGauche >= Bornes;
 
INSERT INTO '|| quote_indent (nom_table)||' (BordDroit, BordGauche, nom) 
VALUES (Bornes, Bornes+1, '''||nom||''');';
RETURN TRUE;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE
  COST 100;
ALTER FUNCTION ri_ajoute_fils(character, character, integer) OWNER TO katagoto;

Ca marche, mais quand j'essaye de l'appeler ça plante, comment faire ?

Par avance merci de votre aide

PS : votre code n'a pas marché hmm

Hors ligne

#16 29/10/2008 00:30:11

frost242
Administrateur

Re : Fonctions variables et arguments

Bien bien d'utiliser les quote_ident, mais il manque toujours les doubles-quotes (") autour des noms de colonnes contenant des lettres capitales (BordDroit par exemple).

Il manque également l'ordre EXECUTE devant les ordres UPDATE et INSERT, il est aussi nécessaire car ce sont des ordres générés dynamiquement.

En fait, il y a aussi un truc assez sympa avec PostgreSQL, c'est le debugger pas à pas PL/pgSQL: pgAdmin III le supporte depuis sa version 1.8 il me semble, et le module est fournie avec PostgreSQL 8.3 pour Windows. Sinon il est disponible à cette adresse: http://pgfoundry.org/projects/edb-debugger/.

Dernière modification par frost242 (29/10/2008 00:34:18)


Thomas Reiss

Hors ligne

#17 29/10/2008 14:55:26

Katagoto
Membre

Re : Fonctions variables et arguments

Ca marche mieu, du moins, ça appel ma fonction, mais il y a un bug dans ma fonction :

CREATE OR REPLACE FUNCTION ri_ajoute_fils(nom_table character, nom character, pk_parent integer)
  RETURNS boolean AS
$BODY$
DECLARE
Bornes RECORD;
BEGIN
EXECUTE 'SELECT ''BordDroite'' INTO Bornes FROM '|| quote_ident (nom_table)||' WHERE id='||pk_parent||';';

EXECUTE 'UPDATE '|| quote_ident (nom_table)||'
SET ''BordDroit'' = ''BordDroit'' + 2 
WHERE ''BordDroit'' >= Bornes;';
 
EXECUTE 'UPDATE '|| quote_ident (nom_table)||'
SET ''BordGauche'' = ''BordGauche'' + 2 
WHERE ''BordGauche'' >= ''Bornes'';';
 
EXECUTE 'INSERT INTO '|| quote_ident (nom_table)||' (''BordDroit'', ''BordGauche'', nom) 
VALUES (Bornes, Bornes+1, '''||nom||''');';
RETURN TRUE;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

Lorsque je fais :

SELECT ri_ajoute_fils('ri', 'smart', 14);

J'ai le droit à :

ERREUR:  EXECUTE of SELECT ... INTO is not implemented yet
CONTEXTE : PL/pgSQL function "ri_ajoute_fils" line 4 at EXECUTE statement

********** Erreur **********

ERREUR: EXECUTE of SELECT ... INTO is not implemented yet
État SQL :0A000
Contexte : PL/pgSQL function "ri_ajoute_fils" line 4 at EXECUTE statement

Qu'est-ce que cela signifie ?

Par avance merci de votre aide

Hors ligne

#18 29/10/2008 19:20:07

Katagoto
Membre

Re : Fonctions variables et arguments

Pour claure le sujet :

CREATE OR REPLACE FUNCTION ri_ajoute_fils(nom_table character, nom character, pk_parent integer)
  RETURNS boolean AS
$BODY$
DECLARE
Bornes RECORD;
BEGIN
EXECUTE 'SELECT "BordDroit" FROM "'|| nom_table ||'" WHERE id= ' || pk_parent || '' INTO Bornes;

EXECUTE 'UPDATE '|| quote_ident (nom_table)||'
SET "BordDroit" = "BordDroit" + 2 
WHERE "BordDroit" >= '||Bornes||';';
 
EXECUTE 'UPDATE '|| quote_ident (nom_table)||'
SET "BordGauche" = "BordGauche" + 2 
WHERE "BordGauche" >= '||Bornes||';';
 
EXECUTE 'INSERT INTO '|| quote_ident (nom_table)||' ("BordDroit", "BordGauche", nom) 
VALUES ('||Bornes||', ('||Bornes||'+1), '''||nom||''');';
RETURN TRUE;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

Merci à tous de votre aide

Hors ligne

#19 29/10/2008 21:38:36

frost242
Administrateur

Re : Fonctions variables et arguments

Chouette wink


Thomas Reiss

Hors ligne

Pied de page des forums