You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python列表传入Oracle PL/SQL存储过程触发PLS-00306错误求助

问题原因分析

你遇到的PLS-00306错误主要有两个核心原因:

  1. 调用存储过程时未指定完整的包名+过程名(仅写PROCEDURE_1,Oracle无法定位到包内的过程);
  2. 你定义的MY_ARRAY_TYPE是PL/SQL私有关联数组(索引表),这种类型仅在PL/SQL内部可见,无法通过Python数据库驱动(如cx_Oracle)直接传递普通列表进行映射。

解决方案

方案一:改用SQL级嵌套表类型(推荐,性能更优)

先创建SQL层面可见的集合类型,再调整存储过程和Python代码:

  1. 创建SQL级数组类型
CREATE OR REPLACE TYPE MY_SQL_ARRAY_TYPE IS TABLE OF NUMBER;
/
  1. 修改包与存储过程(使用SQL级类型,同时改用批量插入提升效率)
CREATE OR REPLACE PACKAGE procedure_1_pkg AS
   PROCEDURE procedure_1(my_array MY_SQL_ARRAY_TYPE); 
END procedure_1_pkg;
/

CREATE OR REPLACE PACKAGE BODY procedure_1_pkg AS
   PROCEDURE procedure_1(my_array MY_SQL_ARRAY_TYPE)
   IS
   BEGIN
      -- 批量插入替代循环,性能提升明显
      FORALL i IN 1..my_array.COUNT
         INSERT INTO TABLE_1(id) VALUES(my_array(i));
   END procedure_1;
END procedure_1_pkg;
/
  1. 调整Python代码(转换列表为Oracle数组并调用)
import cx_Oracle

# 建立连接(替换为你的连接信息)
conn = cx_Oracle.connect("用户名/密码@数据库地址:端口/服务名")
cur = conn.cursor()

MY_ARRAY = [1, 2, 3, 4]
# 将Python列表转换为Oracle可识别的数组类型
oracle_array = cur.arrayvar(cx_Oracle.NUMBER, MY_ARRAY)
# 调用完整路径的存储过程
cur.callproc('procedure_1_pkg.procedure_1', parameters=[oracle_array])

conn.commit()
cur.close()
conn.close()

方案二:不修改原存储过程,用PL/SQL块中转

如果不想改动现有存储过程,可以通过Python执行PL/SQL块,先将列表元素赋值给关联数组,再调用目标过程:

import cx_Oracle

conn = cx_Oracle.connect("用户名/密码@数据库地址:端口/服务名")
cur = conn.cursor()

MY_ARRAY = [1, 2, 3, 4]

# 定义PL/SQL块,完成关联数组初始化与过程调用
plsql_block = """
DECLARE
   v_array procedure_1_pkg.MY_ARRAY_TYPE;
BEGIN
   -- 给关联数组赋值
   FOR i IN 1..:arr_count LOOP
      v_array(i) := :arr_elements(i);
   END LOOP;
   -- 调用包内存储过程
   procedure_1_pkg.procedure_1(v_array);
END;
"""
# 绑定参数:数组长度与元素列表
cur.execute(plsql_block, arr_count=len(MY_ARRAY), arr_elements=MY_ARRAY)

conn.commit()
cur.close()
conn.close()

内容的提问来源于stack exchange,提问作者Eric

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 23:50:19