2016-08-18 86 views
0

我正在遷移數據庫,並試圖將表結構信息檢索到單個行項目以進行機器處理。由於技術原因,現有的遷移工具無法使用,必須按照這種方式進行處理。使用動態SQL檢索表結構

我已經運行有多個表上的成功以下查詢:

SELECT LISTAGG(column_name || ',' || data_type || ',' || data_length, ',') 
WITHIN GROUP (ORDER BY column_id) 
FROM all_tab_cols 
WHERE table_name = 'MyTableName' 

對於許多人來說,工作正常的表,準確地返回我所期待的:

ColumnName1, VARCHAR2, 20, ColumnName2, NUMBER, 22, ColumnName3, CHAR, 3, ... 

然而,有時不完全正確。例如,我從DB設計文檔知道ColumnName2應該是一個長度爲2的數字,而不是22.爲什麼返回不正確?

更令人費解的是,有時它根本不起作用,並且什麼都不會返回。我在想這是導致問題的CHAR數據類型,但是我的一些有CHAR的表格可以正常工作。如果它們是INTEGER,SHORTINT或DATE類型,它似乎會一直給我帶來問題。解決這個問題的最好方法是什麼?

我也知道表中存在,因爲當我運行一個簡單的

SELECT * FROM MyTableName 

它返回的所有表中的記錄。

UPDATE

我試着用data_precision和數字替換數據長度,它返回正確的答案,但我現在什麼都沒有了VARCHAR2。如果它是一個數字,我如何需要重構我的查詢來獲取data_precision,而如果它是其他任何東西,請給我data_length?

此外,我仍然有幾個表,不會讓我查看他們的結構。我對模式還不是很熟悉,但我知道有時候一張表可能存在不同的表。但是爲什麼數據會返回一個SELECT *,但是當我查看all_tab_col時,這裏的結構信息不會出現?

+0

你應該小心與ALL_TAB_COLS所有者。此外,在數字上,你應該使用DATA_PRECISION和DATA_SCALE而不是DATA_LENGTH – vercelli

+0

@Vercelli這三者有什麼區別?我還是比較新的SQL ...... OWNER有什麼問題?我不在這個數據庫中寫任何東西,只是從中讀取數據。 – SandPiper

+0

我試圖解析'select dbms_metadata.get_ddl('TABLE','MYTABLENAME','MYSCHEMA') FROM DUAL' – vercelli

回答

2

您需要決定是否使用data_length或者基於data_type,您可以用的情況下,表達做data_precision:如果我創建一個表

select listagg(column_name ||','|| data_type ||','|| 
    case 
    when data_type in ('VARCHAR2', 'NVARCHAR2', 'CHAR', 'RAW') 
     then to_char(data_length) 
    when data_type = 'NUMBER' 
     and (data_precision is not null or data_scale is not null) 
     then data_precision || case 
     when data_scale > 0 then '.' || data_scale 
     end 
    end, ',') within group (order by column_id) 
from all_tab_columns 
where table_name = 'MYTABLENAME' 
and owner = user -- if it is always current user, use user_tab_columns instead 
/

爲:

create table mytablename (col1 varchar2(20), col2 number(2), col3 char(3), col4 date, 
    col5 timestamp(3), col6 clob, col7 number(5,2)); 

然後該查詢產生:

COL1,VARCHAR2,20,COL2,NUMBER,2,COL3,CHAR,3,COL4,DATE,,COL5,TIMESTAMP(3),,COL6,CLOB,,COL7,NUMBER,5.2 

在這個例子中,我已經代表數字爲精度爲比例尺,但您可能沒有尺度需要擔心,或者可能想要以不同的方式處理它們 - 取決於結果的使用方式。並且我已經爲沒有大小的數據類型提供了一個空白字段,例如CLOB和DATE。

另請注意,時間戳(和間隔)包括數據類型本身的精度,所以timestamp(3)直接來自該列的data_type。帶時區和時間間隔的時間戳還包括數據類型名稱中的空格。

所以這是一個起點,您可以將其擴展到你需要以特定的方式來處理其他數據類型,或(說)拆分時間戳精度到一個單獨的逗號分隔的字段。

+0

這個概念很好。我修改了最後一個case語句,所以如果data_scale = 0,它會返回'Integer',如果它大於0,它會返回'Double'。非常感謝你的幫助! – SandPiper