2013-08-16 68 views
5

我想通過Python中的cx_oracle執行Oracle PL/SQL語句。代碼如下所示:從Python中的cx_Oracle PL/SQL調用返回變量

db = cx_Oracle.connect(user, pass, dsn_tns) 
cursor = db.cursor() 

... 

sel = """ 
DECLARE 
    c NUMBER := 0.2; 
    mn NUMBER := 1.5; 
    res NUMBER; 
BEGIN 
    res := c+mn/6.; 
END; 
""" 
try: 
    cursor.execute(sel) 
    print "PL/SQL successful executed ..." 
except cx_Oracle.DatabaseError as e: 
    err, = e.args 
    print "\n".join([str(err.code),err.message,err.context]) 

該代碼運行沒有問題,但有沒有機會將結果返回給Python?

回答

7

您需要一個函數才能返回結果。一個匿名塊不會。

您需要create a function在數據庫中,例如:

create or replace function calculation return number is 
    c number := 0.2; 
    mn number := 1.5; 
    res number; 
begin 
    return c + mn/6.; 
end; 
/

然後改變你的Python代碼來調用函數,使用,callfunc()

db = cx_Oracle.connect(user, pass, dsn_tns) 
cursor = db.cursor() 

try: 
    result = cursor.callfunc('calculation', float) 
    print result 
except cx_Oracle.DatabaseError as e: 
    err, = e.args 
    print "\n".join([str(err.code),err.message,err.context]) 

這是不可能創造一個即時功能,但您的功能非常簡單,您可以在select語句中執行此操作,並使用fetchall(),如鏈接文檔中所述將結果返回給Python。 fetchall()返回一個元組列表,所以如果你只是在一行和一列之後,你可以立即選擇兩個索引的和。

>>> import cx_Oracle 
>>> db = cx_Oracle.connect('****','****','****') 
>>> cursor = db.cursor() 
>>> SQL = """select 0.2 + 1.5/6. from dual""" 
>>> try: 
...  cursor.execute(SQL) 
...  result = cursor.fetchall()[0][0] 
... except cx_Oracle.DataBaseError, e: 
...  pass 
... 
<__builtin__.OracleCursor on <cx_Oracle.Connection to ****@****>> 
>>> result 
0.45000000000000001 
>>> 

您也可以通過變量到您的通話​​使用綁定變量,因此,如果需要實例化它們在Python:

>>> c = 0.2 
>>> mn = 1.5 
>>> SQL = """select :c + :mn/6. from dual""" 
>>> bind_vars = { 'c' : c, 'mn' : mn } 
>>> cursor.execute(SQL, bind_vars) 
<__builtin__.OracleCursor on <cx_Oracle.Connection to [email protected]>> 
>>> result = cursor.fetchall()[0][0] 
>>> result 
0.45000000000000001 
>>> 

雖然這可能是簡單的做這一切在Python ...我假設你的實際情況更復雜?

+0

是否有可能以數據庫在調用db.close()後忘記它的方式臨時創建函數「on the fly」? –

+0

請參閱我的更新@ user1946052。 – Ben

+0

桌子有「雙重」任何含義或是某種佔位符? –

8

您可以像這樣將輸入和輸出變量綁定到塊。

import cx_Oracle 

SQL_BLOCK = ''' 
DECLARE 
    v_first NUMBER; 
    v_second NUMBER; 
    v_result NUMBER; 
BEGIN 
    v_first := :i_first; -- (1) 
    v_second := :i_second; -- (1) 

    v_result := (v_first + v_second)/2; 

    :o_result := v_result; -- (1) 
END; 
''' 

with cx_Oracle.connect('hr/[email protected]') as db: 
    cur = db.cursor() 
    o_result = cur.var(cx_Oracle.NUMBER) # (2) 
    cur.execute(SQL_BLOCK, i_first=23, i_second=55, o_result=o_result) # (3) 
    res = o_result.getvalue() # (4) 
    print('Average of 23 and 55 is: {}'.format(res)) 
  1. 使用常規綁定符號(:)用於從光標的輸入和輸出變量
  2. 對於輸出變量獲得變量PL/SQL塊(適當類型的)
  3. 在執行調用的輸入變量和來自可變提供值(2)作爲參數
  4. 從輸出變量檢索值

腳本應該打印

Average of 23 and 55 is: 39.0