Page 1 sur 1

ODBC avec les procédures stockées Oracle

Publié : mar. 16/mars/2010 0:26
par alek6
Bonjour,

il s'agit de mon tout premier post sur PB (que j'ai découvert il y a un mois).

voici le résultat de quelques tests effectués sur Oracle avec PureBasic 4.41 (démo).

Le but de ces tests était de découvrir comment PB peut travailler avec les procédures PL/SQL Oracle. Ces tests sont les suivants:

1- lancer une procédure avec un paramètre IN qui est utilisé dans un update
2- lancer une procédure qui retourne un REF CURSOR
(cf. http://www.oracle-base.com/articles/mis ... rdsets.php)
3- lancer une procédure qui retourne un paramètre OUT

Côté Oracle:
CREATE OR REPLACE PACKAGE MYPKG
as
type myrefcursor is ref cursor;

end mypkg;
/

CREATE TABLE MYTESTTABLE (
FIELD1 NUMBER NULL,
FIELD2 NUMBER NULL
)
/

CREATE OR REPLACE PROCEDURE PROC1(myvar out mypkg.myrefcursor)
as
begin
open myvar for select 1,2 from dual;
end;
/

CREATE OR REPLACE PROCEDURE PROC2(myvar in varchar2)
is
begin
update mytesttable set field1 = myvar;
end;
/

CREATE OR REPLACE PROCEDURE PROC3(myvar out varchar2)
is
begin
myvar:='AAA';
end;
/



Côté PB:

Code : Tout sélectionner

;- Window Constants
;
Enumeration
  #Window_0
EndEnumeration

;- Gadget Constants
;
Enumeration
  #ListIcon_0
EndEnumeration

Enumeration
  #DbQuery_0
 
EndEnumeration


Procedure Open_Window_0()

If OpenWindow(#Window_0, 216, 0, 430, 310, "MY WINDOW",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )

    If UseGadgetList(WindowID(#Window_0))
    
          ListIconGadget(#ListIcon_0, 0, 0, 430, 310, "field1" , 100, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection  )
          AddGadgetColumn(#ListIcon_0,1,"field2", 250)     
           
          If UseODBCDatabase() 
               If OpenDatabase(#DbQuery_0,"NOMLIENODBC","LOGIN","PASSWD",#PB_Database_ODBC) 
              a.s="30"
              
              
              ; TEST 1 -REF CURSOR OUT PARAMETER
             Result = DatabaseQuery(#DbQuery_0,"{call PROC1({resultset 0,?})}") 
              ; TEST2 - IN PARAMETER UPDATE TABLE
             ;Result = DatabaseQuery(#DbQuery_0,"begin PROC2('"+ a.s +"'); END;") 
               
                If Result
                  While NextDatabaseRow(#DbQuery_0) 
                     AddGadgetItem (#ListIcon_0, -1, GetDatabaseString(#DbQuery_0,0) + Chr(10) + GetDatabaseString(#DbQuery_0,1))
                 
                  Wend 
                Else
                  MessageRequester("Erreur", "Impossible d'executer la requete: "+DatabaseError())
          
                EndIf 
                
              EndIf 
          EndIf
  
    EndIf
    
  EndIf
  
  
  Repeat
  evenement =WaitWindowEvent()
  Until evenement =#PB_Event_CloseWindow
    
EndProcedure


Open_Window_0()


Dans le test 1, j'ai eu un peu de mal à trouver la solution mais elle marche. Il faut utiliser une syntaxe ODBC avec les escapes.

Code : Tout sélectionner

  ; TEST 1 -REF CURSOR OUT PARAMETER
             Result = DatabaseQuery(#DbQuery_0,"{call PROC1({resultset 0,?})}") 
Les REF CURSOR sont vraiment une fonctionnalité puissante d'oracle puisque l'on peut renvoyer dans un simple paramètre le résultat d'un requête. Les performances peuvent dans certains cas être meilleures car le code PL/SQL est précompilé côté oracle.


Dans le test 2, on appelle la procédure avec la syntaxe pl/sql classique. La valeur du paramètre est passé en concaténant la variable PB. Une petite remarque, bien que ma variable PB soit de type string, oracle la convertie implicitement en number (bien sûr il vaut mieux éviter cela dans la réalité)

Code : Tout sélectionner

 ; TEST2 - IN PARAMETER UPDATE TABLE
Result = DatabaseQuery(#DbQuery_0,"begin PROC2('"+ a.s +"'); END;") 
Je n'ai malheureusement pas trouvé encore de solution pour le test 3.

La syntaxe devrait être quelque chose approchant cela:

Code : Tout sélectionner

 ; TEST3 - OUT PARAMETER UPDATE TABLE
Result = DatabaseQuery(#DbQuery_0,"{call PROC3(?)}") 
ou bien

Code : Tout sélectionner

 ; TEST3 - OUT PARAMETER UPDATE TABLE
Result = DatabaseQuery(#DbQuery_0,"Begin PROC3(:var); end;") 
là où je bloque c'est au moment de lier une variable locale PB avec la variable liée oracle :var ou bien la variable ODBC représentée par le caractère "?".

En php cela correspond par ex. à la fonction bindparam
http://www.manuelphp.com/php/function.p ... dparam.php

en VB (+OLEDB)
Set param1 = cmd.CreateParameter ("deptno", adInteger, adParamOutput)
cmd.Parameters.Append param1

bref cela semble reposer sur la fonction ODBC SQLBindCol
http://msdn.microsoft.com/en-us/library ... 85%29.aspx
http://download.oracle.com/docs/cd/B193 ... p_odbc.htm

Est-ce quelqu'un voit comment on peut faire ?

Voilà c'est pour faire avancer le schmilimili... le schmil... :lol:

a+

alek6