2016-08-15 68 views
1

在Oracle PL/SQL中,我運行了一個查詢,並試圖逐一讀取每一列的每一列,以便我可以用分隔符(硬格式要求)。該腳本用於多個不同大小的表格,因此預先不知道列的數量。我用如何通過ID或索引號引用列

SELECT COUNT(column_name) INTO NumColumns FROM all_tabs_cols 
WHERE table_name = Table_Array(i); 

其中Table_Array已被定義。這是一個for循環的中間,並已成功地獲得了一個列的總數。 Table_Cursor是一個SELECT *語句。在此之後,我試圖做類似

FOR j IN 0..NumColumns-1 LOOP 
    FETCH TABLE_CURSOR.column(j) INTO DataValue; 
    DBMS_OUTPUT.PUT(DataValue || '/'); 
END LOOP 

上面是僞代碼。它闡明瞭我所追求的概念。我不知道PL/SQL是否足夠了解如何獲得像這樣的值。我也擔心在執行此操作時意外推進遊標。我怎樣才能完成這項任務?

+0

誰不只是使用LISTAGG或其他聚合函數? – OldProgrammer

+0

這不是你應該如何使用SQL - SQL是基於設置 - 只要你看看你有麻煩。 – Hogan

+0

@霍根,我很害怕這個。那麼,什麼是更好的方式來獲取這些信息呢? – SandPiper

回答

2

您必須使用某種形式的動態SQL。這裏有一個簡單的例子:

它構建SQL語句,它將從你想要的表中選擇'/'分隔列。然後它使用動態SQL來運行該SQL語句。

DECLARE 
    p_table_name VARCHAR2(30) := 'DBA_OBJECTS'; 
    l_sql VARCHAR2(32000); 

    TYPE varchar2tab IS TABLE OF VARCHAR2(32000); 
    l_array varchar2tab; 

BEGIN 
    SELECT 'SELECT ' || listagg(column_name,' ||''/''||') within group (order by column_id) || ' FROM ' || owner || '.' || table_name || ' WHERE ROWNUM <= 100' 
    INTO l_sql 
    FROM dba_tab_columns 
    where table_Name = 'DBA_OBJECTS' 
    group by owner, table_Name; 

    EXECUTE IMMEDIATE l_sql BULK COLLECT INTO l_array; 

    FOR i in l_array.first .. l_array.last LOOP 
    dbms_output.put_line(l_array(i)); 
    END LOOP; 
END; 
+0

這就像一個冠軍。我改變的唯一的事情是在運行EXECUTE IMMEDIATE之前將整個l_sql放在一起作爲單個字符串。非常感謝你! – SandPiper

+0

不客氣。確保你添加了適當的錯誤處理。 Oracle行可以(超過!)長於32,000個字節。而且,這對於某些數據類型的表(例如'LONG')不起作用。 –

+0

我仍在學習SQL。爲了我的好奇心,爲什麼它不適用於LONG數據類型?還有其他什麼? – SandPiper

0

這是你的代碼應該是什麼樣子:

SELECT F1 || ', ' || F2 || ', ' || ... || ', ' || FN 
FROM TABLE 

沒有循環


這裏是你如何生成不使用循環代碼。 請注意,如果您想要,可以取出where語句並生成整個數據庫的代碼。 首先測試一個表格。

SELECT 'SELECT '|| LISTAGG(COLUMN_NAME, ' || '', '' || ') || ' FROM '||TABLE_NAME as sql_stm 
FROM ALL_TAB_COLUMNS 
WHERE TABLE_NAME='tablename' 
GROUP BY TABLE_NAME; 
+0

所以你的意思是說,如果他有1000張桌子,他必須按照上面的方式每次做到這一點。我希望你明白我的觀點。 – XING

+0

這沒有幫助。我的問題與@Raj_Te完全相同。我有很多表,表結構偶爾會改變。我無法控制這一點。我必須使用動態SQL腳本來獲取它。我不知道表列名稱是什麼,這就是爲什麼我需要通過索引來引用它。 – SandPiper

+1

**正確**編寫一些生成上述代碼的sql。不要使用循環。循環很慢。 – Hogan