oracle 无法获取dbms_sql.column_value

k7fdbhmy  于 2023-08-03  发布在  Oracle
关注(0)|答案(1)|浏览(119)

我试图从一个表中读取一个查询,并使用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;

字符串
我做错了什么?

piv4azn7

piv4azn71#

在您的版本中,从DBMS_SQL.DEFINE_COLUMN中删除注解,并使用l_ntt_desc_tab(i).col_type添加数据类型检查。
下面是一个工作示例:

CREATE OR REPLACE FUNCTION GenerateInsertScript(p_table_name VARCHAR2, p_pk_id NUMBER) RETURN CLOB AS
  v_sql CLOB;
  v_val CLOB;  
  v_query_str VARCHAR2(1000);
  v_name_pk VARCHAR2(1000);
  
  -- для динамического курсора
  desctab dbms_sql.desc_tab;
  cur_id INTEGER;
  ign INTEGER;
  col_count INTEGER;
  numvar NUMBER;
  datevar DATE;
  namevar VARCHAR2(1000);
  str VARCHAR2(2000);
BEGIN
  v_sql := NULL;
  v_val := NULL;

  -- ищем PK в таблице
  SELECT MAX(ccol.column_name) INTO v_name_pk  
    FROM all_cons_columns ccol 
    JOIN all_constraints cnst ON ccol.constraint_name = cnst.constraint_name
      AND cnst.constraint_type = 'P'
    WHERE ccol.table_name = p_table_name;
  
  -- подготавливаем динамический запрос
  v_query_str := 'SELECT * FROM ' || p_table_name;
  IF (p_pk_id IS NOT NULL) AND (v_name_pk IS NOT NULL) THEN
    v_query_str := v_query_str || ' WHERE ' || v_name_pk || '=' || p_pk_id; 
  END IF;  
  
  -- подготавливаем запрос
  cur_id := DBMS_SQL.open_cursor;
  DBMS_SQL.PARSE(cur_id, v_query_str, DBMS_SQL.NATIVE);
  DBMS_SQL.describe_columns(cur_id, col_count, desctab);
  
  -- создаем колонки
  FOR idx IN 1 .. col_count LOOP
    IF desctab(idx).col_type = 2 THEN -- NUMBER
      DBMS_SQL.DEFINE_COLUMN(cur_id, idx, numvar);
    ELSIF desctab(idx).col_type = 12 THEN -- DATE
      DBMS_SQL.DEFINE_COLUMN(cur_id, idx, datevar);
    ELSE -- VARCHAR
      DBMS_SQL.DEFINE_COLUMN(cur_id, idx, namevar, 1000);
    END IF;
    
    -- подготавливаем шапку запроса 
    IF v_sql IS NULL THEN
        v_sql := 'INSERT INTO ' || p_table_name || ' (';
      ELSE
        v_sql := v_sql || ', ';
      END IF;
      
      v_sql := v_sql || desctab(idx).col_name;
  END LOOP;
    
  -- выполняем запрос
  ign := DBMS_SQL.EXECUTE(cur_id);
  -- если запрос ничего не вернул, то выходим
  if DBMS_SQL.FETCH_ROWS(cur_id) = 0 THEN
    DBMS_SQL.CLOSE_CURSOR(cur_id);
    RETURN '';
  END IF;
  
  v_sql := v_sql || ') VALUES (';
  
  -- получаем VALUE из таблицы  
  FOR idx IN 1 .. col_count  
  LOOP 
    str := NULL;  
    IF desctab(idx).col_type = 2 -- NUMBER
    THEN  
       DBMS_SQL.COLUMN_VALUE(cur_id, idx, numvar);
       IF numvar IS NOT NULL THEN 
        str := TO_CHAR(numvar);  
       END IF;  
    ELSIF desctab(idx).col_type = 12 -- DATE  
    THEN  
       DBMS_SQL.COLUMN_VALUE(cur_id, idx, datevar); 
       IF datevar IS NOT NULL THEN 
        str := 'TO_DATE(''' || TO_CHAR(datevar, 'DD/MM/YYYY HH24:MI:SS') || ''',''DD/MM/YYYY HH24:MI:SS'')';
       END IF;   
    ELSE -- VARCHAR 
       DBMS_SQL.COLUMN_VALUE(cur_id, idx, namevar);
       IF namevar IS NOT NULL THEN
        str := '''' || namevar || ''''; 
       END IF;  
    END IF; 
    v_val := v_val || NVL(str, 'NULL');
    IF idx <> col_count THEN
      v_val := v_val || ', ';
    END IF;  
  END LOOP; 
  
  DBMS_SQL.CLOSE_CURSOR(cur_id); 
  
  IF v_val IS NULL THEN
    RETURN '';
  ELSE  
    RETURN v_sql || v_val || ');';
  END IF;  
END;

SELECT GenerateInsertScript('ORDERS', 136) FROM DUAL;

字符串

相关问题