Vous n'êtes pas identifié(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
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
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
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
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
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
Merci gleu.
C'est un détail qui m'a échappé
Hors ligne