动态列计数

时间:2013-06-12 08:00:42

标签: sql oracle plsql

简单问题:

我有一个游标,它针对存储过程参数中提供的select语句运行,因此列数是未知的。

问题是如何打印列?

示例代码:

CREATE OR REPLACE Procedure MyExampleProcedure(P_QUERY VARCHAR2, P_dest VARCHAR2, P_file VARCHAR2)
AS
    --Declaring types to use it for variables declarations
    -----------------------------------------------
    TYPE cursor_ref IS REF CURSOR;
    TYPE typ_new_code IS TABLE OF VARCHAR2(50);
    TYPE typ_new_desc IS TABLE OF VARCHAR2(500);

    --Declaring variables based on previous types
    -----------------------------------------------
    c1 cursor_ref;
    new_code typ_new_code;
    new_desc typ_new_desc;

    -----------------------------------------------
    V_DEST_FILE   utl_file.file_type;
BEGIN

      V_DEST_FILE := utl_file.fopen(P_dest, P_file,'W');

      OPEN c1 for P_QUERY;

      FETCH C1 BULK COLLECT INTO new_code,new_desc;--This is the problematic area, not being able to iterate over the columns in the fetched row dynamically !
      FOR I IN new_code.first .. new_code.last LOOP

        utl_file.put(V_DEST_FILE, new_desc(i));

      END LOOP;

      utl_file.fclose(V_DEST_FILE);


EXCEPTION
      WHEN NO_DATA_FOUND THEN
                --Whatever
      WHEN OTHERS THEN
                --Whatever    
END;

正如您所看到的,这仅适用于包含codedesc两列的select语句,无论名称是什么

2 个答案:

答案 0 :(得分:2)

鉴于代码并且假设您使用的是11g,则无法在基础结果集中获取列名。如果您想这样做,您可能需要使用DBMS_SQL包来打开游标,描述结果并获取数据。我想你也可以编写Java存储过程并使用JDBC API来描述查询。

假设您打算根据SQL语句生成某种文件,我强烈建议利用Tom Kyte's dump_csv procedure而不是尝试构建自己的文件。

答案 1 :(得分:1)

只为这项运动,可以做到 -

在打开游标之前添加:

dbms_output.put_line(dbms_xmlgen.getXMLType(P_QUERY)
                       .extract('ROWSET/ROW/*[1]').getrootelement());

dbms_output.put_line(dbms_xmlgen.getXMLType(P_QUERY)
                       .extract('ROWSET/ROW/*[2]').getrootelement());

(我使用了dbms_output.put_line但你也可以使用utl_file)

请注意,这意味着您只是为列名运行整个查询,因此这可能不是首选解决方案......