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 :
Je crée une procédure qui me renvoie la 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')
Tout ça fonctionne bien sûr très bien sous SQL-Server
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
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 :
Je modifie la procédure stockée en inversant simplement le IF:[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
Là plus de problème, ça fonctionne 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 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
Sinon j'ai essayé ça qui fonctionne également dans tous les cas :
Si si je vous assure je ne fume pas et d'ailleurs je n'ai pas de moquette dans le bureau.
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
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));
Partager