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

如何用python-oracledb执行PL/SQL脚本?执行报错求解

问题分析与解决

报错原因

你遇到的DPY-1004: no statement executed错误,核心原因是代码逻辑误解了getimplicitresults()的作用:

  • getimplicitresults()仅用于获取PL/SQL中通过DBMS_SQL.RETURN_RESULT显式返回的结果集,或者通过REF CURSOR输出的数据集。
  • 你的PL/SQL脚本用的是dbms_output.put_line()输出内容,这属于Oracle的服务器端输出缓冲区,并非隐式结果集,所以调用getimplicitresults()会报错。

启用Thick Mode能否解决?

不能。这个问题和Thin/Thick模式无关,不管切换到哪种模式,用getimplicitresults()读取dbms_output的输出都是行不通的。

正确的解决方法

有两种可行方案,根据需求选择:

方案1:改用返回结果集替代dbms_output

修改PL/SQL脚本,直接通过DBMS_SQL.RETURN_RESULT输出内容,这样就能用getimplicitresults()获取:

sql = """
DECLARE
v_version            VARCHAR(32);
v_dbname             VARCHAR(32);
v_patch              VARCHAR(32);
v_sql                VARCHAR(255);
BEGIN
SELECT SUBSTR(banner, INSTR(banner, 'Release')+8, 2) INTO v_version FROM v$version WHERE banner LIKE '%Oracle%';
SELECT UPPER(name) INTO v_dbname FROM v$database;

IF v_version > 12 THEN
    v_sql := 'select max(TRIM(REGEXP_SUBSTR(REGEXP_SUBSTR(description,''[^:]+'',1,2),''[^(]+'',1,1))) keep (dense_rank last order by action_time) from registry$sqlpatch';
    EXECUTE IMMEDIATE v_sql INTO v_patch;
    DBMS_SQL.RETURN_RESULT(DBMS_SQL.TO_CURSOR('SELECT ''oracle_sql_patch,db='||v_dbname||' dbver="'||v_patch||'"'' AS output FROM DUAL'));
ELSIF v_version > 11 THEN
    v_sql := 'select max(REGEXP_SUBSTR(REGEXP_SUBSTR(description, ''12.[0-9].*''),''[^(]+'',1,1)) keep (dense_rank last order by action_time) from registry$sqlpatch where bundle_series is not null';
    EXECUTE IMMEDIATE v_sql INTO v_patch;
    DBMS_SQL.RETURN_RESULT(DBMS_SQL.TO_CURSOR('SELECT ''oracle_sql_patch,db='||v_dbname||' dbver="'||v_patch||'"'' AS output FROM DUAL'));
ELSE
    v_sql := 'select max(replace(replace(replace(regexp_replace(comments, ''[^[:digit:].]''),''PSU'',''''),''64'',''''),''2021'','''')) keep (dense_rank last order by action_time) from registry$history';
    EXECUTE IMMEDIATE v_sql INTO v_patch;
    DBMS_SQL.RETURN_RESULT(DBMS_SQL.TO_CURSOR('SELECT ''oracle_sql_patch,db='||v_dbname||' dbver="'||v_patch||'"'' AS output FROM DUAL'));
END IF;
END;
"""

cursor.execute(sql)
for implicit_cursor in cursor.getimplicitresults():
    for row in implicit_cursor:
        print(row[0])

方案2:启用并读取dbms_output

如果想保留原PL/SQL的dbms_output.put_line()逻辑,只需在python-oracledb中启用dbms_output缓冲区,执行脚本后读取输出即可,Thin和Thick模式都支持:

# 启用dbms_output,设置缓冲区大小为无限制
cursor.execute("BEGIN DBMS_OUTPUT.ENABLE(buffer_size => NULL); END;")

sql = """
DECLARE
v_version            VARCHAR(32);
v_dbname             VARCHAR(32);
v_patch              VARCHAR(32);
v_sql                VARCHAR(255);
BEGIN
SELECT SUBSTR(banner, INSTR(banner, 'Release')+8, 2) INTO v_version FROM v$version WHERE banner LIKE '%Oracle%';
SELECT UPPER(name) INTO v_dbname FROM v$database;

IF v_version > 12 THEN
    v_sql := 'select max(TRIM(REGEXP_SUBSTR(REGEXP_SUBSTR(description,''[^:]+'',1,2),''[^(]+'',1,1))) keep (dense_rank last order by action_time) from registry$sqlpatch';
    EXECUTE IMMEDIATE v_sql INTO v_patch;
    dbms_output.put_line('oracle_sql_patch,db='||v_dbname||' dbver="'||v_patch||'"');
ELSIF v_version > 11 THEN
    v_sql := 'select max(REGEXP_SUBSTR(REGEXP_SUBSTR(description, ''12.[0-9].*''),''[^(]+'',1,1)) keep (dense_rank last order by action_time) from registry$sqlpatch where bundle_series is not null';
    EXECUTE IMMEDIATE v_sql INTO v_patch;
    dbms_output.put_line('oracle_sql_patch,db='||v_dbname||' dbver="'||v_patch||'"');
ELSE
    v_sql := 'select max(replace(replace(replace(regexp_replace(comments, ''[^[:digit:].]''),''PSU'',''''),''64'',''''),''2021'','''')) keep (dense_rank last order by action_time) from registry$history';
    EXECUTE IMMEDIATE v_sql INTO v_patch;
    dbms_output.put_line('oracle_sql_patch,db='||v_dbname||' dbver="'||v_patch||'"');
END IF;
END;
"""

cursor.execute(sql)

# 循环读取dbms_output的内容
cursor.execute("BEGIN DBMS_OUTPUT.GET_LINE(:line, :status); END;", line=oracledb.STRING, status=oracledb.NUMBER)
while cursor.status == 0:
    print(cursor.line)
    cursor.execute("BEGIN DBMS_OUTPUT.GET_LINE(:line, :status); END;", line=oracledb.STRING, status=oracledb.NUMBER)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 02:37:45