Musisz zdecydować, czy użyć data_length
lub data_precision
na podstawie data_type
, co można zrobić za pomocą wyrażenia wielkości liter:
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
/
Jeśli utworzę tę tabelę jako:
create table mytablename (col1 varchar2(20), col2 number(2), col3 char(3), col4 date,
col5 timestamp(3), col6 clob, col7 number(5,2));
to zapytanie generuje:
COL1,VARCHAR2,20,COL2,NUMBER,2,COL3,CHAR,3,COL4,DATE,,COL5,TIMESTAMP(3),,COL6,CLOB,,COL7,NUMBER,5.2
W tym przykładzie przedstawiłem liczbę jako precyzja .skala , ale możesz nie mieć wagi, o którą musisz się martwić, lub możesz chcieć obchodzić się z nimi w inny sposób - zależy to od tego, jak zostanie użyty wynik. I umieściłem puste pole dla typów danych bez rozmiaru, np. CLOB i DATA.
Zauważ również, że znaczniki czasu (i interwały) zawierają precyzję w samym typie danych, więc timestamp(3)
pochodzi bezpośrednio z data_type
tej kolumny . Znaczniki czasu ze strefami czasowymi i interwałami zawierają również spacje w nazwie typu danych.
Jest to więc punkt wyjścia i możesz rozszerzyć go na inne typy danych, które musisz obsłużyć w określony sposób, lub (powiedzmy) podzielić dokładność znacznika czasu na oddzielne pole oddzielone przecinkami.