cx_Oracle与用户定义类型

2 投票
3 回答
4760 浏览
提问于 2025-04-15 12:08

有没有人知道在Oracle中使用cx_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。

3 个回答

-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版本上测试过。

0

你想更有效地填充对象表吗?

如果你能进行选择查询,可以看看BULK COLLECT INTO这个语句。

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)

撰写回答