2

カーソルの値を連結する関数があります。現在は 4 つの列のみを連結しており、その列名はハードコーディングする必要があります。カーソルを渡すと、11gの列名と列数に関係なく自動的にデータを連結するように、これに対する一般的な解決策を講じる方法はありますか?

FUNCTION generateData(p_dataCursor IN SYS_REFCURSOR)
RETURN VARCHAR2 AS
-- ---------------------------------------------------------------------
crlf         VARCHAR2(2)  := chr(13)||chr(10);
lv_message     VARCHAR2(32000);
BEGIN
  FOR rec IN p_dataCursor
  LOOP
      lv_message := lv_message || rec.a||','||rec.b||','||rec.c||','||rec.d || crlf; 
  END LOOP;
RETURN lv_message;
END;
4

1 に答える 1

1

11g の Oracle 組み込みパッケージ DBMS_SQL では関数 TO_CURSOR_NUMBER が提供されているため、「この関数は、OPEN された強くまたは弱く型付けされた参照カーソルを取得し、それを DBMS_SQL カーソル番号に変換します。」

コード例:

DECLARE
l_cursor SYS_REFCURSOR;
FUNCTION generateData(p_dataCursor IN SYS_REFCURSOR)
RETURN VARCHAR2 AS
  curs SYS_REFCURSOR := p_dataCursor;
  l_cursorid NUMBER;
  l_column_count INTEGER;
  l_describe_table DBMS_SQL.DESC_TAB;
  l_numvar NUMBER;
  l_ignore INTEGER;
  l_value VARCHAR2(2000);
  l_coma VARCHAR2(10);
  crlf         VARCHAR2(2)  := chr(13)||chr(10);
  lv_message     VARCHAR2(32000);
BEGIN

  l_cursorid := dbms_sql.to_cursor_number( curs );

  dbms_sql.describe_columns( l_cursorid, l_column_count, l_describe_table );

  FOR i IN 1..l_column_count LOOP
    dbms_sql.define_column(l_cursorid, i, l_value, 2000);
  END LOOP;

  LOOP 
    IF DBMS_SQL.FETCH_ROWS(l_cursorid)>0 THEN 
      l_coma := '';
      FOR i IN 1..l_column_count LOOP
        dbms_sql.column_value(l_cursorid, i, l_value);
        lv_message := lv_message || l_coma || l_value;
        l_coma := ',';
      END LOOP;
      lv_message := lv_message || crlf;
    ELSE
      EXIT;
    END IF;
  END LOOP;
  dbms_sql.close_cursor( l_cursorid );
  RETURN lv_message;
END;
BEGIN
  open l_cursor FOR 'SELECT 1 as A, 2 AS B, 3 AS C, 4 AS D FROM DUAL UNION ALL SELECT 1 as A, 2 AS B, 3 AS C, 4 AS D FROM DUAL';
  dbms_Output.put_Line(generateData(l_cursor));
END;
/
于 2013-07-31T06:47:59.657 に答える