当您在 Oracle 9i 上查询 ALL_TAB_COLS 视图时,它会列出标记为 UNUSED 的列以及“活动”表列。似乎没有一个字段明确说明列是否未使用,或者我可以加入的任何视图都列出了表中未使用的列。如何轻松找出未使用的列,以便将它们从 ALL_TAB_COLS 中过滤掉?
问问题
20320 次
2 回答
2
尝试使用 ALL_TAB_COLUMNS 而不是 ALL_TAB_COLS。在 Oracle 11.2 中,我发现未使用的列出现在 ALL_TAB_COLS(尽管已重命名)中,但不在 ALL_TAB_COLUMNS 中。
我创建了一个这样的表:
create table t1 (c1 varchar2(30), c2 varchar2(30);
然后设置 c2 未使用:
alter table t1 set unused column c2;
然后我看到:
select column_name from all_tab_cols where owner='ME' and table_name='T1';
COLUMN_NAME
-----------
C1
SYS_C00002_10060107:25:40$
select column_name from all_tab_columns where owner='ME' and table_name='T1';
COLUMN_NAME
-----------
C1
于 2010-06-01T11:43:05.047 回答
1
ALL_TAB_COLUMNS 定义中的唯一过滤器是“其中 hidden_column = 'NO'”,因此似乎在 HIDDEN_COLUMN 字段中标记了 UNUSED 列。
进一步查看数据定义视图,当列变为 UNUSED 时,COL$.PROPERTY 似乎设置为 32800(位 2^5 和 2^15)。2^5 用于标记隐藏列,因此似乎 2^15 未使用。您可以创建一个自定义版本的 ALL_TAB_COLS 基于您需要的内容,例如这个。
CREATE OR REPLACE FORCE VIEW all_tab_cols_rev (owner,
table_name,
column_name,
data_type,
data_type_mod,
data_type_owner,
data_length,
data_precision,
data_scale,
nullable,
column_id,
default_length,
data_default,
num_distinct,
low_value,
high_value,
density,
num_nulls,
num_buckets,
last_analyzed,
sample_size,
character_set_name,
char_col_decl_length,
global_stats,
user_stats,
avg_col_len,
char_length,
char_used,
v80_fmt_image,
data_upgraded,
hidden_column,
virtual_column,
segment_column_id,
internal_column_id,
histogram,
qualified_col_name,
unused_column)
AS
SELECT u.NAME,
o.NAME,
c.NAME,
DECODE (c.type#,
1, DECODE (c.CHARSETFORM, 2, 'NVARCHAR2', 'VARCHAR2'),
2, DECODE (c.scale, NULL, DECODE (c.precision#, NULL, 'NUMBER', 'FLOAT'), 'NUMBER'),
8, 'LONG',
9, DECODE (c.CHARSETFORM, 2, 'NCHAR VARYING', 'VARCHAR'),
12, 'DATE',
23, 'RAW',
24, 'LONG RAW',
58, NVL2 (ac.synobj#, (SELECT o.NAME
FROM obj$ o
WHERE o.obj# = ac.synobj#), ot.NAME),
69, 'ROWID',
96, DECODE (c.CHARSETFORM, 2, 'NCHAR', 'CHAR'),
100, 'BINARY_FLOAT',
101, 'BINARY_DOUBLE',
105, 'MLSLABEL',
106, 'MLSLABEL',
111, NVL2 (ac.synobj#, (SELECT o.NAME
FROM obj$ o
WHERE o.obj# = ac.synobj#), ot.NAME),
112, DECODE (c.CHARSETFORM, 2, 'NCLOB', 'CLOB'),
113, 'BLOB',
114, 'BFILE',
115, 'CFILE',
121, NVL2 (ac.synobj#, (SELECT o.NAME
FROM obj$ o
WHERE o.obj# = ac.synobj#), ot.NAME),
122, NVL2 (ac.synobj#, (SELECT o.NAME
FROM obj$ o
WHERE o.obj# = ac.synobj#), ot.NAME),
123, NVL2 (ac.synobj#, (SELECT o.NAME
FROM obj$ o
WHERE o.obj# = ac.synobj#), ot.NAME),
178, 'TIME(' || c.scale || ')',
179, 'TIME(' || c.scale || ')' || ' WITH TIME ZONE',
180, 'TIMESTAMP(' || c.scale || ')',
181, 'TIMESTAMP(' || c.scale || ')' || ' WITH TIME ZONE',
231, 'TIMESTAMP(' || c.scale || ')' || ' WITH LOCAL TIME ZONE',
182, 'INTERVAL YEAR(' || c.precision# || ') TO MONTH',
183, 'INTERVAL DAY(' || c.precision# || ') TO SECOND(' || c.scale || ')',
208, 'UROWID',
'UNDEFINED'),
DECODE (c.type#, 111, 'REF'),
NVL2 (ac.synobj#, (SELECT u.NAME
FROM user$ u, obj$ o
WHERE o.owner# = u.user#
AND o.obj# = ac.synobj#), ut.NAME),
c.LENGTH,
c.precision#,
c.scale,
DECODE (SIGN (c.null$), -1, 'D', 0, 'Y', 'N'),
DECODE (c.col#, 0, TO_NUMBER (NULL), c.col#),
c.deflength,
c.default$,
h.distcnt,
h.lowval,
h.hival,
h.density,
h.null_cnt,
CASE
WHEN NVL (h.distcnt, 0) = 0
THEN h.distcnt
WHEN h.row_cnt = 0
THEN 1
WHEN ( h.bucket_cnt > 255
OR ( h.bucket_cnt > h.distcnt
AND h.row_cnt = h.distcnt
AND h.density * h.bucket_cnt <= 1) )
THEN h.row_cnt
ELSE h.bucket_cnt
END,
h.timestamp#,
h.sample_size,
DECODE (c.CHARSETFORM,
1, 'CHAR_CS',
2, 'NCHAR_CS',
3, NLS_CHARSET_NAME (c.CHARSETID),
4, 'ARG:' || c.CHARSETID),
DECODE (c.CHARSETID, 0, TO_NUMBER (NULL), NLS_CHARSET_DECL_LEN (c.LENGTH, c.CHARSETID) ),
DECODE (BITAND (h.spare2, 2), 2, 'YES', 'NO'),
DECODE (BITAND (h.spare2, 1), 1, 'YES', 'NO'),
h.avgcln,
c.spare3,
DECODE (c.type#,
1, DECODE (BITAND (c.property, 8388608), 0, 'B', 'C'),
96, DECODE (BITAND (c.property, 8388608), 0, 'B', 'C'),
NULL),
DECODE (BITAND (ac.flags, 128), 128, 'YES', 'NO'),
DECODE (o.status,
1, DECODE (BITAND (ac.flags, 256), 256, 'NO', 'YES'),
DECODE (BITAND (ac.flags, 2),
2, 'NO',
DECODE (BITAND (ac.flags, 4), 4, 'NO', DECODE (BITAND (ac.flags, 8), 8, 'NO', 'N/A') ) ) ),
DECODE (c.property, 0, 'NO', DECODE (BITAND (c.property, 32), 32, 'YES', 'NO') ),
DECODE (c.property, 0, 'NO', DECODE (BITAND (c.property, 8), 8, 'YES', 'NO') ),
DECODE (c.segcol#, 0, TO_NUMBER (NULL), c.segcol#),
c.intcol#,
CASE
WHEN NVL (h.row_cnt, 0) = 0
THEN 'NONE'
WHEN ( h.bucket_cnt > 255
OR ( h.bucket_cnt > h.distcnt
AND h.row_cnt = h.distcnt
AND h.density * h.bucket_cnt <= 1) )
THEN 'FREQUENCY'
ELSE 'HEIGHT BALANCED'
END,
DECODE (BITAND (c.property, 1024),
1024, (SELECT DECODE (BITAND (cl.property, 1), 1, rc.NAME, cl.NAME)
FROM SYS.col$ cl, attrcol$ rc
WHERE cl.intcol# = c.intcol# - 1
AND cl.obj# = c.obj#
AND c.obj# = rc.obj#(+)
AND cl.intcol# = rc.intcol#(+)),
DECODE (BITAND (c.property, 1), 0, c.NAME, (SELECT tc.NAME
FROM SYS.attrcol$ tc
WHERE c.obj# = tc.obj#
AND c.intcol# = tc.intcol#) ) ),
DECODE (c.property, 0, 'NO', DECODE (BITAND (c.property, 32768), 32768, 'YES', 'NO') )
FROM SYS.col$ c, SYS.obj$ o, SYS.hist_head$ h, SYS.user$ u, SYS.coltype$ ac, SYS.obj$ ot, SYS.user$ ut
WHERE o.obj# = c.obj#
AND o.owner# = u.user#
AND c.obj# = h.obj#(+)
AND c.intcol# = h.intcol#(+)
AND c.obj# = ac.obj#(+)
AND c.intcol# = ac.intcol#(+)
AND ac.toid = ot.oid$(+)
AND ot.type#(+) = 13
AND ot.owner# = ut.user#(+)
AND ( o.type# IN (3, 4) /* cluster, view */
OR ( o.type# = 2 /* tables, excluding iot - overflow and nested tables */
AND NOT EXISTS (
SELECT NULL
FROM SYS.tab$ t
WHERE t.obj# = o.obj#
AND ( BITAND (t.property, 512) = 512
OR BITAND (t.property, 8192) = 8192) ) ) )
AND ( o.owner# = USERENV ('SCHEMAID')
OR o.obj# IN (SELECT obj#
FROM SYS.objauth$
WHERE grantee# IN (SELECT kzsrorol
FROM x$kzsro) )
OR /* user has system privileges */
EXISTS (
SELECT NULL
FROM v$enabledprivs
WHERE priv_number IN
(-45 /* LOCK ANY TABLE */,
-47 /* SELECT ANY TABLE */,
-48 /* INSERT ANY TABLE */,
-49 /* UPDATE ANY TABLE */,
-50 /* DELETE ANY TABLE */) ) );
我会将视图放在具有 SELECT ANY DICTIONARY 权限的单独锁定模式中,然后为其创建一个公共同义词。这样,您的所有用户将只能看到他们有权访问的表的 UNUSED_COLUMN 列。
于 2010-06-01T12:39:11.387 回答