8

Python で cx_oracle を介して 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 に戻す機会はありますか?

4

3 に答える 3

14

このように、入力変数と出力変数をブロックにバインドできます。

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/hr@xe') 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. 入力変数と出力変数の両方に対して、PL/SQL ブロックで通常のバインド表記 (:) を使用します。
  2. 出力変数の場合、カーソルから (適切な型の) 変数を取得します。
  3. 実行呼び出しで、入力変数の値と (2) の変数をパラメーターとして指定します。
  4. 出力変数から値を取得する

スクリプトが印刷されるはずです

Average of 23 and 55 is: 39.0
于 2016-08-26T05:59:32.627 に答える
7

結果を返す関数が必要です。匿名ブロックはそうではありません。

たとえば、データベースに関数を作成する必要があります。

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 に返すことができます。タプルのリストを返すので、単一の行と列のみを求めている場合は、両方の 0番目のインデックスを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
>>>

また、バインド変数を使用して変数を呼び出しに渡し、execute()必要に応じて 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 history@monitor>>
>>> result = cursor.fetchall()[0][0]
>>> result
0.45000000000000001
>>>

Pythonでこれをすべて行う方が簡単かもしれませんが...実際の状況はもっと複雑だと思いますか?

于 2013-08-16T08:58:09.730 に答える