有没有人知道使用cx_Oracle在Oracle中使用用户定义类型的更简单方法?
例如,如果我有这两种类型:
CREATE type my_type as object(
component varchar2(30)
,key varchar2(100)
,value varchar2(4000))
/
CREATE type my_type_tab as table of my_type
/
然后包my_package
中的程序如下:
PROCEDURE my_procedure (param in my_type_tab);
要执行PL / SQL中的过程,我可以这样做:
declare
l_parms my_type_tab;
l_cnt pls_integer;
begin
l_parms := my_type_tab();
l_parms.extend;
l_cnt := l_parms.count;
l_parms(l_cnt) := my_type('foo','bar','hello');
l_parms.extend;
l_cnt := l_parms.count;
l_parms(l_cnt) := my_type('faz','baz','world');
my_package.my_procedure(l_parms);
end;
但是,我想知道如何在Python中完成它,类似于以下代码:
import cx_Oracle
orcl = cx_Oracle.connect('foo:bar@mydb.com:5555/blah' + instance)
curs = orcl.cursor()
params = ???
curs.execute('begin my_package.my_procedure(:params)', params=params)
如果参数是一个字符串,我可以像上面那样做,但由于它是用户定义的类型,我不知道如何调用它而不使用纯PL / SQL代码。
编辑:对不起,我应该说我正在寻找用Python代码而不是PL / SQL做更多事情的方法。
答案 0 :(得分:3)
虽然cx_Oracle可以选择用户定义的类型,但据我所知,支持将用户定义的类型作为绑定变量传递。例如,以下内容将起作用:
cursor.execute("select my_type('foo', 'bar', 'hello') from dual")
val, = cursor.fetchone()
print val.COMPONENT, val.KEY, val.VALUE
然而,你不能做的是构造一个Python对象,将其作为输入参数传递,然后让cx_Oracle将Python对象“转换”为Oracle类型。所以我想说你将不得不在PL / SQL块中构造你的输入参数。
您可以传入Python列表,因此以下内容应该有效:
components=["foo", "faz"]
values=["bar", "baz"]
keys=["hello", "world"]
cursor.execute("""
declare
type udt_StringList is table of varchar2(4000) index by binary_integer;
l_components udt_StringList := :p_components;
l_keys udt_StringList := :p_keys;
l_values udt_StringList := :p_values;
l_parms my_type_tab;
begin
l_parms.extend(l_components.count);
for i in 1..l_components.count loop
l_parms(i) := my_type(l_components(i), l_keys(i), l_values(i));
end loop;
my_package.my_procedure(l_parms);
end;""", p_components=components, p_values=values, p_keys=keys)
答案 1 :(得分:0)
您是否尝试更有效地填充对象表?
如果您可以进行SELECT,请查看BULK COLLECT INTO子句
答案 2 :(得分:-1)
我不太确定您的硬编码是什么意思,但您可以构建这样的动态数组:
SQL> desc my_procedure
Parameter Type Mode Default?
--------- ----------- ---- --------
P_IN MY_TYPE_TAB IN
SQL> declare
2 l_tab my_type_tab;
3 begin
4 select my_type(owner, table_name, column_name)
5 bulk collect into l_tab
6 from all_tab_columns
7 where rownum <= 10;
8 my_procedure (l_tab);
9 end;
10 /
PL/SQL procedure successfully completed
已经使用Oracle 11.1.0.6进行了测试。