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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 :
[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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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));