2016-10-28 29 views
1

看起來像這樣是不可能的,但我很親密 - 也許有人可以帶我走到最後一步...在子查詢中獲取列名,然後返回這些列的值?

我有一堆動態代碼,我並不總是知道表和列我' m會處理,但我知道data_lengths爲2000的VARCHAR2列導致錯誤。我希望能夠動態地識別這些「不良」列,並將它們從我的結果中刪除一次。

此代碼:

SELECT LISTAGG(probs.column_name, ', ') WITHIN GROUP (ORDER BY column_name) FROM (select 1 grp, column_name from all_tab_columns where TABLE_NAME = 'MYTABLE' AND DATA_TYPE <> 'VARCHAR2' AND DATA_LENGTH < 2000 ) probs GROUP BY GRP

給了我一個很好的逗號分隔喜歡這一切我可以接受的列名的列表:

FIELD1, FIELD2, FIELD3, FIELD4...

而且我希望有一個方式a可以簡單地做一些事情,將字段名稱列表放入如下所示的選擇語句中:

SELECT (<my subquery, above>) FROM MYTABLE;

這可能嗎?

回答

2

假設這種情況

create table mytable (a number, b number, c number) 
insert into mytable values (10, 20, 30) 
insert into mytable values (1, 2, 3) 

,只有存在具有該名稱(否則就應該在從all_tab_columns查詢所有者)一個表,查詢可以簡化這種方式:

SELECT 'select ' || LISTAGG(column_name, ', ') WITHIN GROUP (ORDER BY column_name) || ' from ' || table_name 
    FROM all_tab_columns 
    WHERE  TABLE_NAME = 'MYTABLE' 
     AND DATA_TYPE <> 'VARCHAR2' 
     AND DATA_LENGTH < 2000 
GROUP BY table_name 

這會給:select A, B, C from MYTABLE

這裏的問題是,你不能簡單地運行一個返回可變數量列的語句;使用這一方法,可以構建一個xml:

SELECT xmltype(
       DBMS_XMLGEN.getxml(
            ( SELECT 'select ' || LISTAGG(column_name, ', ') WITHIN GROUP (ORDER BY column_name) || ' from ' || table_name 
             FROM all_tab_columns 
             WHERE  TABLE_NAME = 'MYTABLE' 
              AND DATA_TYPE <> 'VARCHAR2' 
              AND DATA_LENGTH < 2000 
            GROUP BY table_name) 
           ) 
      ) 
    FROM DUAL 

<?xml version="1.0"?> 
<ROWSET> 
    <ROW> 
    <A>10</A> 
    <B>20</B> 
    <C>30</C> 
    </ROW> 
    <ROW> 
    <A>1</A> 
    <B>2</B> 
    <C>3</C> 
    </ROW> 
</ROWSET> 

另一種方法可以使用一些PLSQL和動態SQL,與尤爾查詢稍加修改來連接領域,打造一個唯一的字符串的結果:

declare 
    type tTabResults is table of varchar2(1000); 
    vSQL varchar2(1000); 
    vTabResults tTabResults; 
begin 
    SELECT 'select ' || LISTAGG(column_name, '|| '', '' ||') WITHIN GROUP (ORDER BY column_name) || ' from ' || table_name 
    into vSQL 
     FROM all_tab_columns 
     WHERE  TABLE_NAME = 'MYTABLE' 
      AND DATA_TYPE <> 'VARCHAR2' 
      AND DATA_LENGTH < 2000 
    GROUP BY table_name; 
    -- 
    execute immediate vSQL bulk collect into vTabResults; 
    -- 
    for i in vTabResults.first .. vTabResults.last loop 
     dbms_output.put_line(vTabResults(i)); 
    end loop; 
end; 



10, 20, 30 
1, 2, 3 

請注意,我過於簡單的問題,處理數字字符串和不使用任何轉換,通過簡單地打印您的表中的值,不管它們的類型;在真正的解決方案中,您應該處理可能的列類型並修改初始查詢以添加一些類型轉換。

+0

感謝Aleksej--這絕對不像我希望的那麼簡單,而且由於我的動態代碼全都在R(我更容易理解),所以我最終做了2個查詢 - 第一個識別所有varchar2字段,然後用R來處理它們,並建立一個適當的最終查詢。我非常感謝你的時間 - 謝謝! – gruvn