Problème avec procédure stockée appelée via dblink
Bonjour,
J'ai un problème assez étonnant avec une procédure stockée SQL-Server appelée depuis oracle via un dblink.
Les données du problème :
Je crée une table TEST :
Code:
1 2
| CREATE TABLE TEST (TEXTE nvarchar(50))
INSERT INTO TEST (TEXTE) VALUES ('ABCD') |
Je crée une procédure qui me renvoie la table TEST
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| CREATE PROCEDURE [dbo].[TESTPROC]
@aParam Int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
if @aParam = 1
-- si param=1 renvoie la table TEST
select TEXTE from dbo.TEST
else
-- Sinon renvoie un code d'erreur -1
select '-1' as TEXTE
END |
Tout ça fonctionne bien sûr très bien sous SQL-Server
Là où c'est moins drôle c'est quand j'appelle la procédure depuis Oracle via un dblink :
Si j'appelle la procédure en lui passant aParam=0 elle me renvoie bien "-1" comme prévu
Si je l'appelle en lui passant 1 j'ai le message d'erreur :
Citation:
[Generic Connectivity Using ODBC][Microsoft][ODBC SQL Server Driver]
Erreur sur la ligne[Microsoft][ODBC SQL Server Driver]
Troncation à droite de la chaîne de données
Je modifie la procédure stockée en inversant simplement le IF:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ALTER PROCEDURE [dbo].[TESTPROC]
@aParam Int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
if @aParam != 1
-- Sinon renvoie un code d'erreur -1
select '-1' as TEXTE
else
-- si param=1 renvoie la table TEST
select TEXTE from dbo.TEST
END |
Là plus de problème, ça fonctionne dans tous les cas.
Sinon j'ai essayé ça qui fonctionne également dans tous les cas :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ALTER PROCEDURE [dbo].[TESTPROC]
@aParam Int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
if @aParam = 1
-- si param=1 renvoie la table TEST
select TEXTE from dbo.TEST
else
-- Sinon renvoie un code d'erreur -1
select '-1' as TEXTE
-- Code jamais éxécuté mais qui évite le message d'erreur
if 1=2 select 'xxxxxxxxxxxxxxxxxxxx'
END |
Si si je vous assure je ne fume pas et d'ailleurs je n'ai pas de moquette dans le bureau.
Il faut que le nombre de caractères dans le "if 1=2 select 'xxxxxxxxxxxxxx'" soit plus grand que la plus grande chaine de la table TEST.
Quelqu'un peut m'expliquer le fonctionnement de SQL-Server ? J'ai l'impression que le code est interpreté au runtime et qu'il se base sur le dernier select pour déterminer la taille du buffer (d'où le message d'erreur "troncation à droite") ?
Il est difficile de livrer un code "sérieux" en expliquant qu'il ne faut surtout pas inverser le sens des "if else" ou en ajoutant des "if 1=2" !
Merci.
Pour info j'ai mis le code de la procédure oracle :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| create or replace TYPE TTEST IS OBJECT (STR1 VARCHAR2(50));
/
create or replace TYPE TEST_SET AS TABLE OF TTEST;
/
create or replace function TEST (aParam in Integer) return TEST_SET pipelined as
lRec TTEST; -- Record resultat
c Integer; -- Handle de curseur
lReqSql VarChar2(200); -- Requète SqlServer
i Integer;
begin
lRec := TTEST('');
-- Crée un curseur pour requète dans SqlServer via HS
c := DBMS_HS_PASSTHROUGH.OPEN_CURSOR@DBLINK;
-- Construit la requète
lReqSQl:='EXEC TESTPROC '||to_char(aParam);
-- execution
DBMS_HS_PASSTHROUGH.PARSE@DBLINK(c, lreqSql);
--recuperation des données
loop
-- Lecture d'un enregistrement
i:=DBMS_HS_PASSTHROUGH.FETCH_ROW@DBLINK(c, False);
exit when I=0; -- EOF si i=0
DBMS_HS_PASSTHROUGH.GET_VALUE@DBLINK(c,1,lRec.Str1);
pipe row (lRec);
end loop;
DBMS_HS_PASSTHROUGH.CLOSE_CURSOR@DBLINK(c);
end;
/
-- appel de la fonction
select * from table(Test(1)); |