【问题标题】:Return only the column headers as text仅将列标题作为文本返回
【发布时间】:2017-08-24 14:47:04
【问题描述】:

我正在尝试将一组列标题的值作为文本返回,如果您将使用 listagg 函数,则类似,但是,这些字段可以是用户定义的,不一定位于表中,因此使用 lisatagg on dba_tab_cols 不是一个选项。

我正在使用的示例代码如下

with test_data1 as (select '2012' extract_yr, '01' extract_mth, 'John Smith' person1, 'Jane Doe' person2 from dual)
    ,test_data2 as (select '2016' extract_yr, '01' extract_mth, 'John Smith' person1, 'Jane Doe' person2 from dual)

select t1.extract_yr year
      ,t1.extract_mth month
      ,t1.person1 first_person
      ,t1.person2 second_person
from test_data1 t1
union all
select t2.extract_yr year
      ,t2.extract_mth month
      ,t2.person1 first_person
      ,t2.person2 second_person
from test_data2 t2

我所追求的是将标头放入逗号分隔的输出/变量中,这样我就可以在一些动态 SQL 中进一步使用它们。 所以在上面的例子中,我希望看到:

YEAR, MONTH, FIRST_PERSON, SECOND_PERSON

这是用于我正在编写的脚本自动化程序,因此输出需要以逗号分隔的 clob 格式。将执行数百个脚本,并且输出字段会因脚本而异。

任何正确方向的帮助或指示将不胜感激

【问题讨论】:

  • 既然你知道字段列表......你能不能:SELECT ('YEAR,MONTH, FIRST_PERSON, SECOND_PERSON') as FieldList from dual? 既然你说他们可以“用户定义”在哪里?如何使用动态SQL?它们必须在某个时候传入,并且使用该点您可以制作像上面这样的 SQL 语句。
  • 我觉得我可能遗漏了一些信息,这是我正在编写的一个测试脚本自动化程序。输出需要以逗号分隔的 clob 中,将执行数百个脚本,并且输出字段将因脚本而异。

标签: sql plsql oracle11g


【解决方案1】:

第二种方法是使用dbms_sql.describe_columns

declare
    v_sql varchar2(32767) := 'with test_data1 as (select ''2012'' extract_yr, ''01'' extract_mth, ''John Smith'' person1, ''Jane Doe'' person2 from dual)
                                    ,test_data2 as (select ''2016'' extract_yr, ''01'' extract_mth, ''John Smith'' person1, ''Jane Doe'' person2 from dual)
                                select t1.extract_yr year
                                      ,t1.extract_mth month
                                      ,t1.person1 first_person
                                      ,t1.person2 second_person
                                from test_data1 t1
                                union all
                                select t2.extract_yr year
                                      ,t2.extract_mth month
                                      ,t2.person1 first_person
                                      ,t2.person2 second_person
                                from test_data2 t2';
    v_cursor_id integer;
    v_col_cnt integer;
    v_columns dbms_sql.desc_tab;
    v_cols varchar2(250);
begin
    v_cursor_id := dbms_sql.open_cursor;
    dbms_sql.parse(v_cursor_id, v_sql, dbms_sql.native);
    dbms_sql.describe_columns(v_cursor_id, v_col_cnt, v_columns);

    for i in 1 .. v_columns.count loop
        dbms_output.put_line(v_columns(i).col_name);

        if i < v_columns.count then
            v_cols := v_cols || v_columns(i).col_name || ', ';
        else
            v_cols := v_cols || v_columns(i).col_name;
        end if;

    end loop;

    dbms_sql.close_cursor(v_cursor_id);
    dbms_output.put_line(v_cols);
exception when others then
    dbms_sql.close_cursor(v_cursor_id);
    raise;
end;

【讨论】:

  • 有没有办法让 v_sql 成为一个 clob?我发现一些提交的 SQL 脚本有效,但有几个较大的似乎不起作用。
  • @Spoons 你使用长度超过 32767 的查询吗?
  • 遗憾的是 - 正在加载的字段是 clob 类型的,因为一些将被输入系统的测试脚本非常庞大。
【解决方案2】:

你的意思是这样的吗?

SELECT LISTAGG(Column_Name, ', ')
       WITHIN GROUP (ORDER BY GROUP) as ColumnNames
FROM   all_tab_cols
WHERE  table_name = 'TableName'
       AND owner = 'OwnerName'

如果您想在结果之外获得它,只需加入他们。

【讨论】:

  • 遗憾的是,这行不通,我将同时启动数百个具有不同名称的脚本,并且在某些情况下,整个脚本都带有别名。 all_tab_cols 的链接需要重写数百个脚本,理想情况下我需要能够即时执行此操作。
【解决方案3】:

我不确定,但也许对你有意义。

首先我们创建一个新的临时表

create GLOBAL TEMPORARY table mytmp
    ON COMMIT DELETE ROWS
    as with test_data1 as (select '2012' extract_yr, '01' extract_mth, 'John Smith' person1, 'Jane Doe' person2 from dual)
        ,test_data2 as (select '2016' extract_yr, '01' extract_mth, 'John Smith' person1, 'Jane Doe' person2 from dual)
    select t1.extract_yr year
          ,t1.extract_mth month
          ,t1.person1 first_person
          ,t1.person2 second_person
    from test_data1 t1
    union all
    select t2.extract_yr year
          ,t2.extract_mth month
          ,t2.person1 first_person
          ,t2.person2 second_person
    from test_data2 t2;

然后提取我们的列

SELECT LISTAGG(Column_Name, ', ') WITHIN GROUP (ORDER BY Column_Name)
    FROM   all_tab_cols
    WHERE  table_name = upper('mytmp');

并删除表

drop table mytmp; 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    • 1970-01-01
    • 2014-07-02
    • 1970-01-01
    相关资源
    最近更新 更多