2017-10-02 5 views
1

J'essaie de retourner un refcursor d'une procédure en python en utilisant cx_oracle, ma procédure ressemble à celle ci-dessous. ci-dessous la procédure est le python que j'essaie d'utiliser. quand je lance le script, tout ce qui est retourné estRenvoyer une procédure stockée out curseur variable dans cx_oracle

DB:  0.00400018692017 seconds 
Total: 0.00400018692017 seconds 
<__builtin__.OracleCursor on <cx_Oracle.Connection to connection_string>> 

comment puis-je itérer à travers le refcursor? oracle documentation

PROCEDURE prc_get_some_data(
    p_cursor  OUT SYS_REFCURSOR) 
IS 
BEGIN 
    DBMS_APPLICATION_INFO.SET_CLIENT_INFO ('Python Script'); 
    OPEN p_cursor FOR 
     SELECT * 
     FROM table; 
EXCEPTION 
    WHEN OTHERS 
     THEN 
      DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_STACK); 
      DBMS_OUTPUT.PUT_LINE(CHR(10)); 
      DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE); 
END prc_get_somedatas; 

script python

import sys, time 
from datetime import date, timedelta 
import random 
import cx_Oracle 
import string 

# Python Script to call a PL/SQL stored procedure to bulk load data 



class Test: 
    def __init__(self): 
     self.__db = cx_Oracle.connect('connection_string') 
     self.__cursor = self.__db.cursor() 

    def __exit__(self, type, value, traceback): 
     self.__cursor.close() 
     self.__db.close() 


    def get_some_data(self): 
     d=date.today() # Initialize a date variable with date of today 

     db_start = time.time() 
     start_all = time.time() 

     self.__cursor.bindarraysize = 2500 
     self.__cursor.arraysize = 10000 

     # create a cursor variable to return the results into 
     l_cur = self.__cursor.var(cx_Oracle.CURSOR) 

     #execute the procedure 
     l_test = self.__cursor.callproc("prc_get_some_data",[l_cur]) 


     db_elapsed = (time.time() - db_start) 
     total_elapsed = (time.time() - start_all) 

     print "DB:\t ", db_elapsed, " seconds" 
     print "Total:\t ", total_elapsed, " seconds" 

     return list(l_test) 



if __name__ == "__main__": 
    test = Test() 
    print test.get_some_data() 

base de données Oracle 12c client: 12.1.0.2

Répondre

1

L'appel à une procédure prend une séquence en tant que paramètre, et renvoie une séquence aussi.

l_test = self.__cursor.callproc("prc_get_some_data",[l_cur]) 
print(type(l_test)) 
#>>> <class 'list'> 

Vous pouvez donc accéder au curseur retourné par index:

ret_cursor = self.__cursor.callproc("prc_get_some_data",[l_cur])[0] 

ou

l_test = self.__cursor.callproc("prc_get_some_data",[l_cur]) 
ret_cursor = l_test[0] 

Vous pouvez ensuite imprimer le résultat avec une boucle

for line in ret_cursor: 
    print line 

ou avec print ret_cursor.fetchall(), ou avec le pprint outil si nécessaire.


Dans le documentation vous avez lié, la valeur de retour est directement décompressé à l_query et l_emp:

l_query, l_emp = self.__cursor.callproc("PKG_HR.FIND_EMPLOYEES", [p_query, l_cur]) 

Par ailleurs, vous devrez peut-être fermer le curseur retourné au fin, avec la même méthode que le curseur principal: ret_cursor.close(). Sinon, il peut lancer une exception à propos de la connexion ne peut pas être fermé.