Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
#1 18/08/2011 19:31:38
- charleydc5
- Membre
Accès aux paramètres d'une fonction à l'intérieur d'un PREPARE
Bonjour à tous,
J'ai une fonction qui contient une table temporaire, donc un "PREPARE" suivi d'un SELECT et de la commande CREATE TEMP TABLE.
J'avais le message suivant à l'exécution:
ERROR: could not determine data type of parameter $2
CONTEXT: SQL statement "PREPARE tmpCas AS
J'ai donc découvert qu'il fallait spécifier les types de paramètre dans une instruction PREPARE, car autrement PostgreSQL les perçoit comme "unknown".
Mon instruction PREPARE est donc passée de
PREPARE tmpCas AS
à
PREPARE tmpCas(integer, character varying, character varying, integer, character varying, integer, character varying, character varying, integer, integer, character varying) AS
Maintenant, mon erreur n'est plus la même. C'est maintenant :
ERROR: operator does not exist: timestamp without time zone >= character varying
LINE 71: stirq.Cheminement.datCheminement BETWEEN $3 AND $4 AND
Lorsque j'arrive à la ligne en question, je remarque PostgreSQL perçoit $3 et $4 comme le troisième et le quatrième paramètre de mon PREPARE (donc character varying et integer), alors que ma fonction a comme troisième et quatrième paramètre des timestamp (intervalle de date pour ma requête).
Lorsque je ne suis pas dans un prepare, c'est parfait. Par contre, dans un PREPARE, je n'arrive plus à accéder aux paramètres de ma fonction.
J'ai essayé d'ajouter ceci au début de ma fonction :
DECLARE
ldatfrom TIMESTAMP := $3;
ldatto TIMESTAMP := $4;
.. et d'utiliser ldatfrom et ldatto dans le WHERE du PREPARE... négatif.
Quelqu'un a une idée?
Finalement, voici le code complet de ma fonction:
CREATE OR REPLACE FUNCTION stirq.qrycastempscoutstyperpt(
pvintregionid INT,
pvstrregionnom VARCHAR,
pvdatfrom timestamp without time zone,
pvdatto timestamp without time zone,
pvstrlangue VARCHAR)
RETURNS TABLE(intcasid integer, strnodossier character varying, strconseillernom character varying, intlocalisationid integer, strlocalisationnom character varying, intregionid integer, strregionnom character varying, stractivitenom character varying, inttemps integer, intcouts integer, strdossieretatnom character varying) AS
$BODY$
/*
DECLARE
ldatfrom TIMESTAMP := $3;
ldatto TIMESTAMP := $4;
*/
BEGIN
PREPARE tmpCas(integer, character varying, character varying, integer, character varying, integer, character varying, character varying, integer, integer, character varying) AS
SELECT Cas.intCasId AS intCasIdGlobal,
Cas.strNoDossier,
Users.strUserFirstName || ' ' || Users.strUserLastName AS strConseillerNom,
Localisation.intLocalisationId,
CASE $5
WHEN 'fr' THEN Localisation.strLocalisationNomFr
WHEN 'en' THEN Localisation.strLocalisationNomEn
END AS strLocalisationNom,
Region.intRegionId,
CASE $5
WHEN 'fr' THEN Region.strRegionNomFr
WHEN 'en' THEN Region.strRegionNomEn
END AS strRegionNom,
CASE $5
WHEN 'fr' THEN ActiviteNom.strActiviteNomFr
WHEN 'en' THEN ActiviteNom.strActiviteNomEn
END AS strActiviteNom,
Cheminement.intTemps,
Cheminement.intCouts,
CASE $5
WHEN 'fr' THEN DossierEtat.strDossierEtatAbrFr
WHEN 'en' THEN DossierEtat.strDossierEtatAbrEn
END AS strDossierEtatNom
FROM stirq.Cas
INNER JOIN stirq.DossierEtat ON
stirq.Cas.intDossierEtatId = stirq.DossierEtat.intDossierEtatId
INNER JOIN stirq.Localisation ON
stirq.Cas.intLocalisationId = stirq.Localisation.intLocalisationId
INNER JOIN stirq.Region ON
stirq.Localisation.intRegionId = stirq.Region.intRegionId
INNER JOIN stirq.Intervention ON
stirq.Cas.intCasId = stirq.Intervention.intCasId
INNER JOIN stirq.ActiviteNom ON
stirq.Intervention.intActiviteNomId = stirq.ActiviteNom.intActiviteNomId
INNER JOIN stirq.Cheminement ON
stirq.Intervention.intInterventionId = stirq.Cheminement.intInterventionId
INNER JOIN
(SELECT stirq.Cas.intCasId,
MAX(intCheminementId) AS intLastCheminementId
FROM stirq.Cheminement
INNER JOIN stirq.Intervention ON
stirq.Cheminement.intInterventionId = stirq.Intervention.intInterventionId
INNER JOIN stirq.Cas ON
stirq.Intervention.intCasId = stirq.Cas.intCasId
INNER JOIN stirq.Localisation ON
stirq.Cas.intLocalisationId = stirq.Localisation.intLocalisationId
INNER JOIN stirq.Region ON
stirq.Localisation.intRegionId = stirq.Region.intRegionId
WHERE
stirq.Cheminement.datCheminement BETWEEN $3 AND $4 AND
Region.intRegionId = $1
GROUP BY Cas.intCasId
) AS vwsLastCheminementCas ON
Cas.intCasId = vwsLastCheminementCas.intCasId
INNER JOIN (
SELECT Cheminement.intCheminementId,
Cheminement.intConseiller1Id
FROM stirq.Cheminement
INNER JOIN stirq.Intervention ON
stirq.Cheminement.intInterventionId = stirq.Intervention.intInterventionId
INNER JOIN stirq.Cas ON
stirq.Intervention.intCasId = stirq.Cas.intCasId
INNER JOIN stirq.Localisation ON
stirq.Cas.intLocalisationId = stirq.Localisation.intLocalisationId
INNER JOIN stirq.Region ON
stirq.Localisation.intRegionId = stirq.Region.intRegionId
WHERE
stirq.Cheminement.datCheminement BETWEEN $3 AND $4 AND
stirq.Region.intRegionId = $1
) AS vwsLastConseillerCas ON
vwsLastCheminementCas.intLastCheminementId = vwsLastConseillerCas.intCheminementId
INNER JOIN stirq.Users ON
vwsLastConseillerCas.intConseiller1Id = stirq.Users.intUserId
WHERE
Cheminement.datCheminement BETWEEN $3 AND $4 AND
Region.intRegionId = $1
ORDER BY Cas.strNoDossier, ActiviteNom.intOrder;
CREATE TEMP TABLE tmpCas AS EXECUTE tmpCas;
INSERT INTO tmpCas
SELECT 0,
NULL,
NULL,
0,
NULL,
$1,
$2::VARCHAR,
CASE $5
WHEN 'fr' THEN stirq.ActiviteNom.strActiviteNomFr
WHEN 'en' THEN stirq.ActiviteNom.strActiviteNomEn
END AS strActiviteNom,
NULL,
NULL,
NULL
FROM stirq.ActiviteNom
WHERE intActiviteTypeId = 4;
RETURN QUERY SELECT * FROM tmpCas;
DEALLOCATE tmpCas;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION stirq.qrycastempscoutstyperpt(integer, character varying, timestamp without time zone, timestamp without time zone, character varying) OWNER TO cxm526;
Merci !
Charles Morin
PostgreSQL 9.0.3 sur Windows 2008 Server Standard (x64)
Hors ligne
#2 18/08/2011 22:38:53
- gleu
- Administrateur
Re : Accès aux paramètres d'une fonction à l'intérieur d'un PREPARE
Peut-être qu'on peut résoudre ça avec une requête dynamique. Difficile de savoir sans connaître l'erreur.
Guillaume.
Hors ligne
#3 19/08/2011 12:22:19
- dverite
- Membre
Re : Accès aux paramètres d'une fonction à l'intérieur d'un PREPARE
Tu auras plus vite fait de supprimer le PREPARE qui n'est pas utile, dans le sens où tu peux faire:
CREATE TEMP TABLE tmpCas AS SELECT....
Le PREPARE est surtout utile quand une requête est réutilisée de multiples fois ce qui n'est pas le cas ici.
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
#4 19/08/2011 14:19:50
- charleydc5
- Membre
Re : Accès aux paramètres d'une fonction à l'intérieur d'un PREPARE
Ça fonctionne!
C'est bon à savoir que PREPARE n'est pas obligatoire pour les tables temporaires ponctuelles comme j'ai eu besoin de faire.
Merci beaucoup dverite pour les explications
Charles Morin
PostgreSQL 9.0.3 sur Windows 2008 Server Standard (x64)
Hors ligne