使用oracledb向Oracle存储过程传递rowtype变量报错排查
问题:使用Python oracledb调用Oracle存储过程时出现TypeError
我有一个Oracle包ETL_RUN,其中包含如下声明的存储过程:
procedure pRunTask(pTask in out nocopy TASK_RUN%rowtype)
我尝试通过Python的oracledb库调用该存储过程,代码如下:
cursor.callproc('ETL_RUN.pRunTask', [task_run])
但出现如下错误:
File "...flows\migration_simple.py", line 48, in init cursor.callproc('ETL_RUN.pRunTask', keyword_parameters={'pTask': task_run}) File "...venv\lib\site-packages\oracledb\cursor.py", line 651, in callproc self._call(name, parameters, keyword_parameters) File "...venv\lib\site-packages\oracledb\cursor.py", line 113, in _call return self.execute(statement, bind_values) File "...venv\lib\site-packages\oracledb\cursor.py", line 701, in execute impl.execute(self) File "src\\oracledb\\impl/thin/cursor.pyx", line 178, in oracledb.thin_impl.ThinCursorImpl.execute File "src\\oracledb\\impl/thin/protocol.pyx", line 437, in oracledb.thin_impl.Protocol._process_single_message File "src\\oracledb\\impl/thin/protocol.pyx", line 438, in oracledb.thin_impl.Protocol._process_single_message File "src\\oracledb\\impl/thin/protocol.pyx", line 399, in oracledb.thin_impl.Protocol._process_message File "src\\oracledb\\impl/thin/protocol.pyx", line 376, in oracledb.thin_impl.Protocol._process_message File "src\\oracledb\\impl/thin/messages.pyx", line 314, in oracledb.thin_impl.Message.send File "src\\oracledb\\impl/thin/messages.pyx", line 2162, in oracledb.thin_impl.ExecuteMessage._write_message File "src\\oracledb\\impl/thin/messages.pyx", line 2096, in oracledb.thin_impl.ExecuteMessage._write_execute_message File "src\\oracledb\\impl/thin/messages.pyx", line 428, in oracledb.thin_impl.MessageWithData._write_bind_params File "src\\oracledb\\impl/thin/messages.pyx", line 1115, in oracledb.thin_impl.MessageWithData._write_bind_params_row File "src\\oracledb\\impl/thin/messages.pyx", line 1081, in oracledb.thin_impl.MessageWithData._write_bind_params_column File "src\\oracledb\\impl/thin/packet.pyx", line 809, in oracledb.thin_impl.WriteBuffer.write_dbobject TypeError: object of type 'NoneType' has no len()
其中task_run变量是从另一个Oracle函数获取的<oracledb.DbObject MAP.TASK_RUN%ROWTYPE at 0x152bec935e0>,请问哪里操作有误?
解决方案
检查DbObject字段值:错误提示
NoneType没有len(),说明task_run中的某个字符串类型字段(比如VARCHAR2)值为None。在oracledb thin模式下,绑定字符串类型的None会触发该错误,需确保所有字符串字段都赋值为空字符串''而非None。显式指定参数方向:由于存储过程参数是
IN OUT NOCOPY类型,调用时需显式标记参数方向。示例代码:
import oracledb # 初始化绑定参数,指定类型和方向 bind_param = cursor.var(oracledb.DB_OBJECT, typename="MAP.TASK_RUN", direction=oracledb.BIND_INOUT) bind_param.setvalue(0, task_run) cursor.callproc('ETL_RUN.pRunTask', [bind_param]) # 获取存储过程修改后的对象 updated_task_run = bind_param.getvalue()
确认类型完全匹配:验证
task_run的类型与存储过程要求的TASK_RUN%ROWTYPE完全一致,检查获取task_run的函数是否返回了完整的行类型对象,无字段缺失。切换到thick模式:若thin模式对复杂类型兼容性不足,可切换到thick模式(需安装Oracle客户端),执行以下代码启用:
oracledb.init_oracle_client()
内容的提问来源于stack exchange,提问作者privod
相关产品推荐
相关产品推荐

