【发布时间】:2017-10-03 07:39:28
【问题描述】:
通过这个guide,我能够将一个简单数据类型(如cx_Oracle.NUMBER)的关联数组传递给PL/SQL 过程。
CREATE OR REPLACE PACKAGE test
IS
TYPE t_ids IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
PROCEDURE foo(p_ids_i IN t_ids);
END;
/
称呼它:
ids = cursor.arrayvar(cx_Oracle.NUMBER, [1,2,3])
cursor.callproc('test.foo', [ids])
但是,我想调用下面的过程 foo,而不是采用复杂类型。
CREATE OR REPLACE PACKAGE test
IS
TYPE r_foo IS RECORD (id NUMBER, name VARCHAR2(10));
TYPE t_complex IS TABLE OF r_foo INDEX BY PLS_INTEGER;
PROCEDURE foo(p_ids_i IN t_complex);
END;
/
我尝试了各种方法,例如:
# Raises NotSupportedError: Variable_TypeByPythonType(): unhandled data type
foos = cursor.arrayvar((cx_Oracle.NUMBER, cx_Oracle.STRING), [(1, 'foo'), (2, 'bar')])
# Raises NotSupportedError: Variable_MakeArray(): type does not support arrays
foos = cur.arrayvar(cx_Oracle.OBJECT, [(1, 'foo'), (2, 'bar')])
以下失败:
# Raises DatabaseError: ORA-04043: object TEST.R_FOO does not exist
record_type = conn.gettype('TEST.R_FOO')
看起来您可以在包之外创建一个类型并引用它。
CREATE TYPE t_foo IS TABLE OF NUMBER; -- Not an Associative Array
引用它:
t = conn.gettype('T_FOO')
但是,您不能在包之外创建关联数组的记录。我可以用 Object 替换 RECORD,但我想不出任何东西来替换 Associative Array,这是 cx_Oracle 可以传入或传出的唯一集合类型。
完整代码:
PL/SQL:
-- 返回 12.1.0.2.0 从 v$instance 中选择版本; 创建或替换包测试 是 TYPE r_foo IS RECORD (id NUMBER, name VARCHAR2(10)); 类型 t_complex 是 PLS_INTEGER 的 r_foo 索引表; 程序 foo(p_ids_i IN t_complex); 结尾; / 创建或替换包体测试 是 程序 foo(p_ids_i IN t_complex) 是 开始 FOR i IN p_ids_i.FIRST .. p_ids_i.LAST LOOP DBMS_OUTPUT.PUT_LINE(p_ids_i(i).id || ' ' || p_ids_i(i).name); 结束循环; 结尾; 结尾; / - 以下工作按预期工作。 宣布 l_complex test.t_complex; 开始 l_complex(1).id := 1; l_complex(1).name := '马修'; l_complex(2).id := 2; l_complex(2).name := 'Moisen'; test.foo(l_complex); 结尾;Python:
导入 cx_Oracle 打印 cx_Oracle.version # 5.3 print cx_Oracle.clientversion() # (12, 1, 0, 2, 0) conn = cx_Oracle.connect('用户名/密码@sid') cur = conn.cursor() 结果 = cur.execute("SELECT * FROM user_source WHERE name = 'TEST' and type = 'PACKAGE'") # 这将成功打印包规范 结果中的行: 打印行 # 引发 DatabaseError: ORA-04043: 对象 TEST.R_FOO 不存在 conn.gettype('TEST.R_FOO') # 引发 DatabaseError: ORA-04043: 对象 TEST.T_COMPLEX 不存在 conn.gettype('TEST.T_COMPLEX') # 这会引发适当的异常,说我调用了该过程 # 错误,表明我可以访问它。 cur.callproc('TEST.FOO', [])在将 $ORACLE_HOME 等设置为我的 12c 客户端重新安装 cx_Oracle 后,我能够更进一步,但仍然遇到 append 操作错误。
【问题讨论】:
标签: python oracle plsql cx-oracle