Vous n'êtes pas identifié(e).
Pages : 1
bonjour,
Je voudrais migrer une fonction Oracle vers Pgsql.
La fonction a des paramètres in out, dont un tableau d'entiers.
Pour la faire fonctionner sous Oracle, j'avais créé un package pour pouvoir passer un tableau d'entiers dont voici le descriptif :
CREATE OR REPLACE
PACKAGE PCK_LEP IS
TYPE TP$TABLE IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
PROCEDURE P_LEP(LK$DT1 VARCHAR2, LK$DT2 VARCHAR2) ;
FUNCTION MAJ_LEP (LK$LEP LEP%ROWTYPE,
LK$LISTE TP$TABLE)
RETURN NUMBER;
FUNCTION PEC_LEP ( LK$TP_E NUMBER,
LK$HR_E NUMBER,
LK$LEP IN OUT LEP%ROWTYPE,
LK$LG1 IN OUT NUMBER,
LK$LG2 IN OUT NUMBER,
LK$LISTE IN OUT TP$TABLE)
RETURN NUMBER;
END;
Le problème que je rencontre est que je ne sais pas comment migrer PEC_LEP, pg n'accepte pas [] smallint en in out ...
Y a t'il une alternative ?
Hors ligne
Quelle déclaration faites-vous pour cette fonction ? et quelle erreur renvoit-il ?
Guillaume.
Hors ligne
Bonsoir,
Voilà ce que j'obtiens :
CREATE OR REPLACE FUNCTION PEC_LEP (LK$TP_E INTEGER,
LK$HR_E INTEGER,
LK$LEP IN OUT LEP,
LK$LG1 IN OUT INTEGER,
LK$LG2 IN OUT INTEGER,
LK$LISTE IN OUT SMALLINT[])
RETURNS INTEGER AS
...
ERREUR: le type de résultat de la fonction doit être record à cause des paramètres OUT
********** Erreur **********
ERREUR: le type de résultat de la fonction doit être record à cause des paramètres OUT
État SQL :42P13
Je débute en pgsql, et je ne saisis pas comment il faut mettre les paramètres ...
Hors ligne
Vous ne pouvez pas utiliser la clause RETURNS étant donné que vous utilisez des paramètres en INOUT. Autre chose, il n'y a pas d'espace entre IN et OUT.
Guillaume.
Hors ligne
Merci !!!
Ça fonctionne
Hors ligne
En fait, j'ai quand même un souci : les champs INOUT ne sont pas modifiés. Ils sont juste fournis en copie dans la variable dans le RETURN ...
CREATE OR REPLACE FUNCTION p_test(test character varying)
RETURNS void AS
$BODY$
DECLARE
LC$test numeric:=0;
cd_ret2 varchar;
BEGIN
CD_RET2:=f_test2 (LC$test);
raise notice 'Valeur : %',LC$test;
return;
END ;
$BODY$
LANGUAGE plpgsql VOLATILE;
CREATE OR REPLACE FUNCTION f_test2(INOUT ma_var numeric)
RETURNS numeric AS
$BODY$
DECLARE
BEGIN
ma_var:=ma_var+1;
END ;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Donne
select p_test (null);
NOTICE: Valeur : 0
NOTICE: Valeur : 0
NOTICE: Retour : 1
Si j'ai plein de variables en entrée, le type en sortie est "record", que je peux récupérer en varchar par exemple.
Mais comment remettre les variables modifiées dans celles que j'avais fournies en paramètre ?
En gros, si je fais un F_calcul (Var1, Var2, Var3, Var4, Var5)
je voudais que mes variables Var1 à Var5 soient modifiées. Sous Oracle, il n'y avait besoin d'aucune manipulation mais je suis prêt à rajouter quelques instructions ...
Hors ligne
La valeur que vous testez est la valeur en entrée, pas la valeur en sortie. Sur votre fonction p_test, La valeur renvoyée par la fonction f_test2 est stockée dans CD_RET2. Autrement dit, vous devriez avoir :
CD_RET2:=f_test2 (LC$test);
raise notice 'Valeur : %',CD_RET2;
Attention que vous êtes dans le cadre d'une base de données. Du coup :
CD_RET2:=f_test2 (LC$test);
est équivalent à
SELECT INTO CD_RET2 f_test2 (LC$test);
ce qui donne plus de sens au fait que le retour est dans CD_RET2 et non pas dans LC$test.
Guillaume.
Hors ligne
Mais comment faire si la fonction a en paramètre plusieurs variables INOUT ?
Pgsql dit qu'il faut que le retour soit de type record. Comment alors transférer les données "record" dans les champs initiaux ?
concrètement,
SELECT INTO CD_RET2 F_calcul (Var1, Var2, Var3, Var4, Var5);
comment faire passer dans var1, var2, ... ce qui est dans le record CD_RET2 ?
Hors ligne
Mais comment faire si la fonction a en paramètre plusieurs variables INOUT ?
Indiquez les différentes variables (une par colonne récupérée), ie : SELECT INTO CD_RET1, CD_RET2, CD_RET3 F_calcul(...);
comment faire passer dans var1, var2, ... ce qui est dans le record CD_RET2 ?
SELECT INTO Var1, Var2, Var3, Var4, Var5 F_calcul (Var1, Var2, Var3, Var4, Var5);
J'ai l'impression que vous prenez les paramètres INOUT pour des paramètres fournies par référence. Ce n'est clairement pas le cas. Ça n'aurait aucun sens au niveau d'une connexion SQL.
Guillaume.
Hors ligne
Oui, c'est ça, je voudrais utiliser certaines fonctions pour des traitements.
C'est certain que je m'éloigne de l'esprit de l'origine des fonctions en SQL.
J'en utilise certaines pour faire des traitements qui auraient aussi bien pu être écrits dans d'autres langages.
Mais ça fonctionnait très bien avec Oracle.
Et j'ai toujours une erreur :
ERREUR: syntaxe en entrée invalide pour le type numeric : « (13,6,toto) »
État SQL :22P02
select into cd_ret1 , cd_ret2, cd_char titi.f_test3 ( cd_ret1 , cd_ret2, cd_char ) ;
Hors ligne
Quel est la définition de f_test3 ?
Guillaume.
Hors ligne
CREATE OR REPLACE FUNCTION titi.f_test3(INOUT ma_var2 numeric, INOUT ma_var numeric, INOUT ma_var3 character varying)
RETURNS record AS
$BODY$
DECLARE
BEGIN
ma_var3:='toto';
ma_var:=ma_var+1;
ma_var2:=ma_var2+ma_var;
END ;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
(J'ai laissé volatile pour les tests ; une telle fonction devrait être IMMUTABLE si j'ai bien compris la doc, mais j'ai laissé par défaut pour mes tests).
Hors ligne
Comme vous renvoyez plusieurs colonnes, vous devez faire un :
select into cd_ret1 , cd_ret2, cd_char * FROM titi.f_test3 ( cd_ret1 , cd_ret2, cd_char ) ;
Guillaume.
Hors ligne
Ah, oui, comme ça, ça fonctionne.
On progresse, mais j'ai un nouveau problème.
Ma fonction Oracle avait plusieurs paramètres IN OUT en entrée dont 1 de type ROWTYPE.
Et si j'essaie un :
select into RW$TEST , LC$VAR4 from select titi.test4 (0, 1 ,RW$TEST , LC$VAR4);
avec les 2 derniers en INOUT, j'ai droit à :
ERREUR : la variable de type RECORD ou ROW ne peut pas faire partie d'une liste INTO à plusieurs éléments
J'ai essayé d'autres syntaxes avec * mais elles produisent une erreur de syntaxe ...
Ya t'il une syntaxe qui convient ?
Hors ligne
Pour le smallint [] en INOUT avec plusieurs paramètres, ça fonctionne en le récupérant avec *, comme pour un champ de type character varying.
Plus que le champ modifié de type ROWTYPE à récupérer, et j'aurai tous les éléments pour voir si mes procédures et fonctions Oracle sont adaptables sous pgsql ...
Hors ligne
Au cas où ça peut aider d'autres personnes, ma problématique était d'écrire une fonction avec plusieurs paramètre inout dont au moins 2 doivent être récupérés avec la syntaxe * comme expliqué par gleu plus haut.
Je n'ai pas réussi à trouver une syntaxe avec un "select" qui fonctionne.
Pour contourner, j'ai créé une table vide avec tous les champs que je voulais (dont 2 de type smallint []).
J'ai créé une variable Var_table MATABLE;
et en faisant VAR_table := ma_fct (var1, Var2, VAR_table);
Ca fonctionnne.
Je ne trouve pas ma solution très propre parce que j'ai créé une table vide juste pour avoir une liste de champs, un peu comme pour définir une structure en C, mais c'est la seule que j'ai trouvée ...
Hors ligne
Pourquoi ne pas avoir créé un type ?
Guillaume.
Hors ligne
Et bien ... Parce que je ne savais pas que l'on pouvait faire comme ça.
En effet, ça fonctionne très bien, et là, c'est propre ;-)
Merci !
Hors ligne
Pour infos, le coup de la table fonctionne parce qu'un type est créé du même nom que la table. Mais seul un type de données vous est utile.
Guillaume.
Hors ligne
Pages : 1