DatabaseLibrary调用存储过程报错“AttributeError: 'cx_Oracle.Cursor' object has no attribute 'nextset'”

使用最新版cx oracle(8.3),需要调用oracle的存储过程,发现报错“AttributeError: 'cx_Oracle.Cursor' object has no attribute 'nextset'”

原因排查

查阅DatabaseLibrary发现报错在call_stored_procedure这个函数中

image

进一步阅读代码,发现cx aralce的游标类,已经没有nextset方法,因此继续查阅cx oracle官方文档,找到调用存储过程的方法callproc:https://cx-oracle.readthedocs.io/en/latest/api_manual/cursor.html#Cursor.callproc

查看该方法使用示例:https://cx-oracle.readthedocs.io/en/latest/user_guide/plsql_execution.html#plsqlproc

image

发现调用存储过程前,需要先定义接收结果变量。执行完成后需要调用结果变量的getvalue方法获取结果。

解决方案

参考call_stored_procedure方法,重写一个调用存储过程的函数,在使用时按照使用自定义关键字的方式导入即可使用(需要注意的是,robot中不需要再导入DatabaseLibrary,因为自定义的类是继承DatabaseLibrary,具有父类的所有方法)


from DatabaseLibrary import DatabaseLibrary
from robot.api import logger
from robot.api.deco import keyword

class CustomerDatabaseLibrary(DatabaseLibrary):
    @keyword('oracle_xxx')
    def call_p_xxx(self, spName='pkg_xxx.p_xxx', spParams=None,
                                    sansTran=False):
        cur = None
        if spParams is None:
            spParams = []
        try:
            cur = self.__get_cur()
            spName = self.__get_spName(spName)

            # 定义接收结果变量,不同存储过程不一样
            o_message = cur.var(str)
            o_result = cur.var(str)

            spParams.append(o_message)
            spParams.append(o_result)

            logger.info('Executing : Call Stored Procedure  |  %s  |  %s ' % (spName, spParams))

            cur.callproc(spName, spParams)

            retVal = [
                o_message.getvalue(),
                o_result.getvalue()
            ]
            if not sansTran:
                self._dbconnection.commit()
            return retVal
        finally:
            if cur:
                if not sansTran:
                    self._dbconnection.rollback()

    def __get_cur(self):
        cur = None
        if self.db_api_module_name in ["cx_Oracle"]:
            cur = self._dbconnection.cursor()
        else:
            cur = self._dbconnection.cursor(as_dict=False)
        return cur

    def __get_spName(self, spName=None):
        PY3K = sys.version_info >= (3, 0)
        if not PY3K:
            spName = spName.encode('ascii', 'ignore')
        return spName
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容