使用DBMS_SQL包处理查询时调用dbms_sql.column_value报错求助
问题描述
尝试从CSV_EXP_CFG表中读取查询语句,使用DBMS_SQL包进行处理。语句解析正常,也能看到查询中的列,但无法获取查询结果,调试时调用dbms_sql.column_value会抛出异常,代码如下:
/*--------------------------------------------------------------------------------------------------------------------*/ PROCEDURE MY_PROC( nCSV_EXP_CFG_ID IN NUMBER,nN1 IN NUMBER DEFAULT null ) /*--------------------------------------------------------------------------------------------------------------------*/ as l_ntt_desc_tab dbms_sql.desc_tab; nCursorId INTEGER; nColCnt INTEGER; nRowCnt INTEGER; rCSV_EXP_CFG CSV_EXP_CFG%ROWTYPE; TYPE rowArray IS VARRAY(20) OF VARCHAR2(255); colVal rowArray; BEGIN SELECT * INTO rCSV_EXP_CFG FROM CSV_EXP_CFG WHERE CSV_EXP_CFG_ID = nCSV_EXP_CFG_ID; nCursorId:=dbms_sql.open_cursor; dbms_sql.parse(nCursorId, rCSV_EXP_CFG.EXPORT_TABLE, dbms_sql.native); IF nN1 IS NOT NULL THEN DBMS_SQL.BIND_VARIABLE (nCursorId, 'n1', nN1); END IF; dbms_sql.describe_columns(nCursorId, nColCnt, l_ntt_desc_tab); FOR i IN 1..nColCnt LOOP DBMS_OUTPUT.PUT_LINE( l_ntt_desc_tab(i).col_name); --DBMS_SQL.DEFINE_COLUMN(nCursorId, i, colVal(i), 255); END LOOP; nRowCnt:=dbms_sql.execute(nCursorId); LOOP EXIT WHEN dbms_sql.fetch_rows(nCursorId) = 0; FOR i IN 1..nColCnt LOOP --here I'm getting the exception dbms_sql.column_value(nCursorId, i, colVal(i)); END LOOP; END LOOP; Dbms_sql.close_cursor(nCursorId); EXCEPTION WHEN OTHERS THEN NULL; END MY_PROC;
错误原因及修复方案
- VARRAY未初始化:定义的
colVal是VARRAY类型,必须先调用构造函数rowArray()初始化,再用extend(nColCnt)扩展容量,否则直接访问colVal(i)会触发异常。 - 缺失列定义步骤:注释掉的
DBMS_SQL.DEFINE_COLUMN是DBMS_SQL流程的必要环节——必须先定义要提取的列的类型和长度,后续才能通过column_value获取对应列的值。 - 异常处理掩盖错误:
EXCEPTION WHEN OTHERS THEN NULL;会吞掉所有错误信息,无法定位具体问题,应改为打印错误详情,同时确保异常时游标能正常关闭。
修复后的代码
/*--------------------------------------------------------------------------------------------------------------------*/ PROCEDURE MY_PROC( nCSV_EXP_CFG_ID IN NUMBER,nN1 IN NUMBER DEFAULT null ) /*--------------------------------------------------------------------------------------------------------------------*/ as l_ntt_desc_tab dbms_sql.desc_tab; nCursorId INTEGER; nColCnt INTEGER; nRowCnt INTEGER; rCSV_EXP_CFG CSV_EXP_CFG%ROWTYPE; TYPE rowArray IS VARRAY(20) OF VARCHAR2(255); colVal rowArray; BEGIN SELECT * INTO rCSV_EXP_CFG FROM CSV_EXP_CFG WHERE CSV_EXP_CFG_ID = nCSV_EXP_CFG_ID; nCursorId:=dbms_sql.open_cursor; dbms_sql.parse(nCursorId, rCSV_EXP_CFG.EXPORT_TABLE, dbms_sql.native); IF nN1 IS NOT NULL THEN DBMS_SQL.BIND_VARIABLE (nCursorId, 'n1', nN1); END IF; dbms_sql.describe_columns(nCursorId, nColCnt, l_ntt_desc_tab); -- 初始化VARRAY并扩展容量 colVal := rowArray(); colVal.extend(nColCnt); FOR i IN 1..nColCnt LOOP DBMS_OUTPUT.PUT_LINE( l_ntt_desc_tab(i).col_name); -- 恢复列定义 DBMS_SQL.DEFINE_COLUMN(nCursorId, i, colVal(i), 255); END LOOP; nRowCnt:=dbms_sql.execute(nCursorId); LOOP EXIT WHEN dbms_sql.fetch_rows(nCursorId) = 0; FOR i IN 1..nColCnt LOOP dbms_sql.column_value(nCursorId, i, colVal(i)); -- 可选:输出获取到的列值用于验证 DBMS_OUTPUT.PUT_LINE('列' || i || '(' || l_ntt_desc_tab(i).col_name || ')值:' || colVal(i)); END LOOP; END LOOP; Dbms_sql.close_cursor(nCursorId); EXCEPTION WHEN OTHERS THEN -- 打印错误信息便于调试 DBMS_OUTPUT.PUT_LINE('错误详情:' || SQLERRM); -- 确保异常时游标关闭 IF DBMS_SQL.IS_OPEN(nCursorId) THEN DBMS_SQL.CLOSE_CURSOR(nCursorId); END IF; END MY_PROC;
内容的提问来源于stack exchange,提问作者hajduk
相关产品推荐
相关产品推荐

