我正在迁移数据库,并且正在尝试将表结构信息检索到单个行项目中以进行机器处理。由于技术原因,不能使用现有的迁移工具,必须以这种方式处理它。
我在多个表上成功运行了以下查询:
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
它返回表中的所有记录。
更新
我尝试用data_precision替换data_length,对于数字,它返回了正确的答案,但现在我没有任何VARCHAR2。我如何重构我的查询以获取data_precision,如果它是一个数字,而不是给我data_length如果它是什么?
另外,我还有几张桌子不允许我查看他们的结构。我对模式仍然不太熟悉,但我理解有时候一个表可能存在于不同的表下。但是为什么用SELECT *返回数据,但是当我查看all_tab_col时,这里的结构信息不会出现?
答案 0 :(得分:2)
您需要根据data_length
决定是否使用data_precision
或data_type
,您可以使用案例表达式执行此操作:
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
。带有时区和时间间隔的时间戳也包括数据类型名称中的空格。
所以这是一个起点,您可以将它扩展到您需要以特定方式处理的其他数据类型,或者(比方说)将时间戳精度分成单独的逗号分隔字段。