【问题标题】:How can you tell which columns are unused in ALL_TAB_COLS?如何判断 ALL_TAB_COLS 中哪些列未使用?
【发布时间】:2011-02-26 07:31:00
【问题描述】:

当您在 Oracle 9i 上查询 ALL_TAB_COLS 视图时,它会列出标记为 UNUSED 的列以及“活动”表列。似乎没有一个字段明确说明列是否未使用,或者我可以加入的任何视图都列出了表中未使用的列。如何轻松找出哪些是未使用的列,以便将它们从 ALL_TAB_COLS 中过滤掉?

【问题讨论】:

    标签: oracle oracle9i data-dictionary


    【解决方案1】:

    尝试使用 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
    

    【讨论】:

    • 不幸的是,all_tab_cols 有一些我确实需要的信息(隐藏的数据类型和 LOB 列,隐藏的功能索引的虚拟列......)
    • 未使用的列名格式是否保证相同(sys_c00002_10060107:25:40$')?
    • 抱歉,我不知道 - 虽然我想是的。
    【解决方案2】:

    ALL_TAB_COLUMNS 定义中的唯一过滤器是“where 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 列。

    【讨论】:

    • 不幸的是,还有其他隐藏列需要我的信息(索引虚拟列、LOB 列...)
    猜你喜欢
    • 1970-01-01
    • 2015-04-15
    • 2020-02-15
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 2019-07-19
    • 2013-07-03
    • 1970-01-01
    相关资源
    最近更新 更多