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 28/11/2016 12:37:27

albourg
Membre

fonction convertie de oracle donne un résultat différent

CREATE OR REPLACE FUNCTION cec.qccontrolsaskedcount()
    RETURNS bigint
    LANGUAGE 'plpgsql'
    VOLATILE SECURITY DEFINER
    COST 100.0
AS $function$DECLARE

iRet bigint;

QCControlsAskedCountNoStage CURSOR FOR
SELECT CHECKASKCOUNT
FROM QUALITYCHECKSASKED QCA,  stagecharacteristics sc, batchState bs
WHERE qca.stage=sc.stageid and sc.characteristic like 'CFL%' and
bs.batchID=QCA.IDPELIDET AND bs.IDGROUP=iGroup LIMIT 1 OFFSET 0;

BEGIN
   iRet:=-1;

   open QCControlsAskedCountNoStage;
   FETCH QCControlsAskedCountNoStage into iRet;
   close QCControlsAskedCountNoStage;

   return iRet;
EXCEPTION
WHEN NO_DATA_FOUND THEN
   return -1;
END;
$function$;

arguments: igroup bigint.

Le curseur ne renvoie aucune ligne pour iGroup 1709311 (et c'est normal). CHECKASKCOUNT est défini comme un entier non null.
Je m'attends donc à ce que
select cec.qccontrolsaskedcount(1709311) renvoie -1. Mais ça envoie NULL. En oracle ca renvoie bien -1, et la valeur à renvoyer est de plus un entier non null. Cette fonction est sensée renvoyer un entier non null.

Il semble que le when no_data_found ne fonctionne pas en postgres de la même manière qu'en oracle. Quelqu'un peut m'expliquer ce qui coince?

Hors ligne

#2 28/11/2016 13:07:07

rjuju
Administrateur

Re : fonction convertie de oracle donne un résultat différent

C'est effectivement un peu différent sous postgres.  Si vous utilisez directement une requête (SELECT colonne INTO variable FROM...), vous avez la possibilité d'utiliser le mot clé « STRICT » qui lèvera alors une exception si une seule ligne n'est pas retournée (soit 0 lignes soit plus d'une), mais dans le cas d'un curseur il faut utiliser la variable « FOUND » mise à jour par « FETCH », cf http://docs.postgresql.fr/9.6/plpgsql-statements.html en dessous du tableau 41.1.


Votre procédure stockée pourrait être modifiée comme cela :

CREATE OR REPLACE FUNCTION cec.qccontrolsaskedcount()
    RETURNS bigint
    LANGUAGE 'plpgsql'
    VOLATILE SECURITY DEFINER
    COST 100.0
AS $function$DECLARE

iRet bigint;

QCControlsAskedCountNoStage CURSOR FOR
SELECT CHECKASKCOUNT
FROM QUALITYCHECKSASKED QCA,  stagecharacteristics sc, batchState bs
WHERE qca.stage=sc.stageid and sc.characteristic like 'CFL%' and
bs.batchID=QCA.IDPELIDET AND bs.IDGROUP=iGroup LIMIT 1 OFFSET 0;

BEGIN
   iRet:=-1;

   open QCControlsAskedCountNoStage;
   FETCH QCControlsAskedCountNoStage into iRet;
   close QCControlsAskedCountNoStage;

   IF NOT FOUND THEN
      RETURN -1;
   END IF;

   return iRet;
END;
$function$;

Hors ligne

Pied de page des forums