python - 使用 Python 和 Cx_Oracle 调用带有 XMLTYPE 输入和输出参数的 Oracle 存储过程
问题描述
我正在尝试使用 Python 和 Cx_Oracle 8.2.1 运行 Oracle 存储过程。这个过程有两个 XMLTYPE 参数,一个用于输入,一个用于输出,在 Oracle 中会这样调用它并且工作正常:
DECLARE
RXML_OUT XMLTYPE;
BEGIN
RXML_OUT := NULL;
MYPACKAGE.MYPROCEDURE ( IN_SXML, RXML_OUT );
END;
但是,我一直无法使用 Cx_Oracle 调用它。我试图这样称呼它:
connection = cx_Oracle.connect(config["db"]["usuario"], config["db"]["password"],
"{}/{}".format(config["db"]["host"], config["db"]["servicio"]), encoding=config["db"]["nls_charset"],
nencoding=config["db"]["nls_ncharset"])
cursor = connection.cursor()
xml_in = """
<myxml>
<sometag>This is some XML</sometag>
</myxml>
"""
rxml_out = cursor.var(cx_Oracle.STRING)
res = cursor.callproc('MYPACKAGE.MYPROCEDURE', [xml_in, rxml_out])[1]
我可以毫无问题地运行具有其他数据类型和常规查询的其他过程。但是,有了这个,我收到以下错误:
cx_Oracle.DatabaseError: ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'MYPROCEDURE'
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'MYPROCEDURE'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
据我从文档中收集到的,Cx_Oracle 没有 XML 数据类型,如果小于 1 GB,XMLTYPE 可以被视为字符串(我正在处理的这些 XML 文件的长度最多为几 KB,所以我m 远低于该限制)。我在这里做错了什么?
更新 1
我尝试过使用临时 CLOB,如此处的文档中所示。结果是一样的(请注意,我们的 DBA 实际上修改了程序,只有第一个参数是 XMLTYPE IN,第二个是 VARCHAR OUT):
xml_in = connection.createlob(cx_Oracle.DB_TYPE_CLOB)
xml_in.write("""
<myxml>
<sometag>This is some XML</sometag>
</myxml>
""")
po_msgerror = cursor.var(cx_Oracle.STRING)
po_msgerror.setvalue(0, "")
cursor.callproc('MYPACKAGE_PKG.MYPROCEDURE', [xml_in, po_msgerror])
最终结果和之前一样:
cx_Oracle.DatabaseError: ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to
'MYPROCEDURE'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
更新 2
我还尝试使用匿名 PL/SQL 块来调用过程,如文档中所示(与以前的代码片段相同,但使用 execute 方法而不是 callproc):
#cursor.callproc('MYPACKAGE_PKG.MYPROCEDURE', [xml_in, po_msgerror])
cursor.execute("""BEGIN
MYPACKAGE_PKG.MYPROCEDURE ( :1, :2 );
END;
""", [xml_in, po_msgerror])
结果还是一样:
cx_Oracle.DatabaseError: ORA-06550: line 2, column 3:
PLS-00306: wrong number or types of arguments in call to 'MYPROCEDURE'
ORA-06550: line 2, column 3:
PL/SQL: Statement ignored
解决方案
经过大量的实验,我终于能够成功调用该过程并传递一个XMLTYPE输入参数。以下代码有效(该过程采用两个参数,一个 XMLTYPE IN 和一个 VARCHAR OUT):
# Consumo de package para envío del XML de prestaciones
xml_in = """
<myxml>
<sometag>This is some XML</sometag>
</myxml>
"""
po_msgerror = cursor.var(cx_Oracle.STRING)
po_msgerror.setvalue(0, "")
cursor.execute("""BEGIN
MYPACKAGE_PKG.MYPROCEDURE ( sys.xmltype(:1), :2 );
END;
""", [xml_in, po_msgerror])
没有必要为 XMLTYPE IN 参数使用 CLOB,一个字符串就可以了。使用匿名 PL/SQL 块调用过程并将第一个参数显式传递为 sys.xmltype 就足够了。
我不知道是否可以以相同的方式强制转换 XMLTYPE OUT 参数并将其绑定到字符串变量。但至少对于输入参数,这工作得很好。
推荐阅读
- wildfly - Wildfly-15.0.1.Final 与 OpenJdk-11 的部署因 org.jboss.modules.ModuleNotFoundException 错误而失败
- javascript - 如何在 php 中的 json_decode() 中显示特殊字符,如“Ñ”
- java - 需要有关弹性搜索自动化的信息
- java - 禁止登录 SwaggerGen
- osgi - Adobe AEM/OSGI:如何从任何类访问 OSGI 服务?
- bash - 在 macOS 上更改 .profile 中的陷阱后无法消除错误
- ios - CAGradientLayer 上均匀分布的颜色
- typescript - 如何在打字稿中将 Blob 类型转换为字节数组?
- html - 从跨域加载 vtt 的问题
- c# - Xamarin.Android 膨胀自定义视图