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

#1 20/07/2009 13:08:37

zied
Membre

Passer le nom d'un Champ comme paramètre d'une proc. stockée

Bonjour
Je veux créer une procédure stocké à laquelle je veux passer en paramètre 2 variables  Le nom d'un champ et sa valeur

J'ai écrit ce code pour tester mais ça ne marche pas :

CREATE OR REPLACE FUNCTION __searchtest(character, character)
  RETURNS SETOF record AS
$BODY$
select prod_version from vprod_details
where $1=$2;

$BODY$
  LANGUAGE 'sql' VOLATILE
  COST 100
  ROWS 1000;
ALTER FUNCTION __searchtest(character, character) OWNER TO postgres;

avec $1 le nom du champ et $2 est la valeur du champ. 
Est-ce possible?
Si oui comment faire?

Hors ligne

#2 20/07/2009 14:19:11

Marc Cousin
Membre

Re : Passer le nom d'un Champ comme paramètre d'une proc. stockée

Impossible de le faire de la sorte : la fonction sql ne peut pas avoir comme variable le nom d'une colonne je pense.

Il faudra passer par du plpgsql et fabriquer l'ordre SQL à la volée, comme expliqué ici :
http://docs.postgresql.fr/8.4/plpgsql-statements.html paragraphe 38.5.4.
Evidemment, cela aussi est pénible, puisqu'il faut fabriquer l'ordre SQL par concaténation


Marc.

Hors ligne

#3 20/07/2009 15:57:09

zied
Membre

Re : Passer le nom d'un Champ comme paramètre d'une proc. stockée

J'ai essayé cette écriture

 

CREATE OR REPLACE FUNCTION __searchtest2(character, character)
  RETURNS bigint AS
$BODY$
PREPARE  test(character,character) AS SELECT prod_version FROM vprod_details
WHERE $1=$2;
 
EXECUTE test('prod_ref','ZA01820C'); 
 
$BODY$
  LANGUAGE 'sql' VOLATILE
  COST 100;
ALTER FUNCTION __searchtest(character, character) OWNER TO postgres;

J'ai l'erreur suivante

ERROR: return type mismatch in function declared to return bigint
DÉTAIL : Function's final statement must be a SELECT.
CONTEXTE : SQL function "__searchtest2"

Hors ligne

#4 20/07/2009 16:47:41

gleu
Administrateur

Re : Passer le nom d'un Champ comme paramètre d'une proc. stockée

Vous ne pouvez pas le faire en SQL. Il faut obligatoirement passer par PL/pgsql (ou un autre, plus évolué que SQL).

CREATE OR REPLACE FUNCTION __searchtest2(character, character)
  RETURNS bigint AS
$BODY$
DECLARE
  requete text;
  ma_valeur le_type_de_ma_valeur;
BEGIN
requete := 'SELECT prod_version FROM vprod_details WHERE '||quote_ident($1)||'='||quote_literal($2);
EXECUTE requete INTO mavaleur;
RETURN ma_valeur;
END
$BODY$
LANGUAGE 'plpgsql';

Quelque chose comme cela me paraît mieux. Il y a certainement moyen de mieux faire avec les dernières versions de PostgreSQL (notamment avec la 8.4 et son RETURN QUERY EXECUTE).


Guillaume.

Hors ligne

#5 21/07/2009 11:00:13

zied
Membre

Re : Passer le nom d'un Champ comme paramètre d'une proc. stockée

Merci.
Voici le résultat final

CREATE OR REPLACE FUNCTION __searchtest3
(
    _key character varying,
	_value character varying,
	OUT prod_version bigint
)
RETURNS bigint
AS $$
DECLARE __query text DEFAULT NULL;
BEGIN
 
	__query := 'SELECT prod_version FROM vprod_details WHERE "' || _key || '" = \'' || _value || '\'';
	EXECUTE __query INTO prod_version;
 
	RETURN;
	
END $$ LANGUAGE plpgsql;

Hors ligne

#6 21/07/2009 11:50:37

gleu
Administrateur

Re : Passer le nom d'un Champ comme paramètre d'une proc. stockée

N'oubliez pas quote_literal. Ça vous protège des chaînes contenant par exemple des guillemets. Car là, avec votre code, si _value contient un guillemet, la fonction échouera. Sans compter que ça permet une attaque de type injection SQL du plus mauvais effet.


Guillaume.

Hors ligne

#7 21/07/2009 12:03:08

zied
Membre

Re : Passer le nom d'un Champ comme paramètre d'une proc. stockée

Merci gleu.
C'est un détail qui m'a échappé

Hors ligne

Pied de page des forums