Oracle表中新加字段时默认的排列顺序可以修改吗?

来源:互联网 发布:房间4g网络信号差 编辑:程序博客网 时间:2024/06/10 23:50

原文地址:http://www.itpub.net/thread-1841773-1-1.html


例如表T
create table t
(
                 id number,
                 col1 varchar2(10),
                 col2 varchar2(10),
                 col3 varchar2(10)
);

SQL> desc t
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
ID                                                 NUMBER
COL1                                               VARCHAR2(10)
COL2                                               VARCHAR2(10)
COL3                                               VARCHAR2(10)

SQL> 


需要加一列
alter table t add col0 varchar2(10);

SQL> desc t
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
ID                                                 NUMBER
COL1                                               VARCHAR2(10)
COL2                                               VARCHAR2(10)
COL3                                               VARCHAR2(10)
COL0                                               VARCHAR2(10)



我希望新加的COL0排在COL1的前面,不考虑重新建表,做视图,同义词等手段,有什么其他方法吗?




--------------------------------------------------------------------------------
      首先感谢 @YuBinTAMU  带来的12C新特性,12C版本以下的童鞋只能观望一下喽  做了个小实验12C中确实可以解决我的需求,同时物理结构不发生改变,在我看到结果的时候也比较困惑oracle是怎么实现的,整理了一下头脑后,发现column_id很可疑,遂又继续验证了一步,嘿嘿 过程很有趣哟~~,下面是实验过程

试图测试性能(起初以为会有物理变化)

SQL> drop table t purge;

Table dropped.

SQL> create table t
  2  (
  3                   id number,
  4                   col1 varchar2(128),
  5                   col2 varchar2(128),
  6                   col3 varchar2(128)
  7  );

Table created.


SQL> insert into t select object_id,object_name,owner,object_type from dba_objects;

19386 rows created.

Elapsed: 00:00:02.56

...... 

SQL> insert into t select * from t;

620352 rows created.

Elapsed: 00:00:02.40

......

SQL> insert into t select * from t;

9925632 rows created.

Elapsed: 00:01:54.85

SQL> commit;

Commit complete.

Elapsed: 00:00:00.09

SQL> select count(1) from t;  

  COUNT(1)
----------
  19851264

Elapsed: 00:00:42.43
SQL>

查看当前表中列的的顺序

SQL> SELECT column_name, column_id FROM user_tab_cols  WHERE table_name = 'T' order by 2;

COLUMN_NAME           COLUMN_ID
-------------------- ----------
ID                            1
COL1                          2
COL2                          3
COL3                          4

Elapsed: 00:00:00.07

ROWID:AAAE1NAAEAAAACDAAA    4号文件131号块的第一行数据


SQL> SELECT dbms_rowid.rowid_block_number(ROWID) bno, dbms_rowid.rowid_relative_fno(ROWID) fno, ROWID, t.* FROM t where rownum=1;

       BNO        FNO ROWID                      ID
---------- ---------- ------------------ ----------
       131          4 AAAE1NAAEAAAACDAAA        652

Elapsed: 00:00:00.07


设置列为invisible之前dump出的block结果

SQL> alter system dump datafile 4 block 131;

System altered.

节选前三行:
block_row_dump:
tab 0, row 0, @0xb19
tl: 37 fb: --H-FL-- lb: 0x1  cc: 4
col  0: [ 3]  c2 16 57
col  1: [14]  56 24 49 4f 46 55 4e 43 4d 45 54 52 49 43
col  2: [ 6]  50 55 42 4c 49 43
col  3: [ 7]  53 59 4e 4f 4e 59 4d
tab 0, row 1, @0xb3e
tl: 40 fb: --H-FL-- lb: 0x1  cc: 4
col  0: [ 3]  c2 16 58
col  1: [23]
56 5f 24 49 4f 46 55 4e 43 4d 45 54 52 49 43 5f 48 49 53 54 4f 52 59
col  2: [ 3]  53 59 53
col  3: [ 4]  56 49 45 57
tab 0, row 2, @0xb66
tl: 45 fb: --H-FL-- lb: 0x1  cc: 4
col  0: [ 3]  c2 16 59
col  1: [22]
56 24 49 4f 46 55 4e 43 4d 45 54 52 49 43 5f 48 49 53 54 4f 52 59
col  2: [ 6]  50 55 42 4c 49 43
col  3: [ 7]  53 59 4e 4f 4e 59 4d

修改列为invisible
SQL> ALTER TABLE  t  MODIFY( COL1 INVISIBLE, COL2 INVISIBLE, COL3 INVISIBLE);

Table altered.

Elapsed: 00:00:00.94

此时column_id变成了NULL
SQL> SELECT column_name, column_id FROM user_tab_cols  WHERE table_name = 'T' order by 2;

COLUMN_NAME           COLUMN_ID
-------------------- ----------
ID                            1
COL1
COL3
COL2

Elapsed: 00:00:00.08

SQL> alter system dump datafile 4 block 131;

System altered.

设置invisible之后,查看dump结果: 
block_row_dump:
tab 0, row 0, @0xb19
tl: 37 fb: --H-FL-- lb: 0x1  cc: 4
col  0: [ 3]  c2 16 57
col  1: [14]  56 24 49 4f 46 55 4e 43 4d 45 54 52 49 43                          --为发生变化
col  2: [ 6]  50 55 42 4c 49 43
col  3: [ 7]  53 59 4e 4f 4e 59 4d
tab 0, row 1, @0xb3e
tl: 40 fb: --H-FL-- lb: 0x1  cc: 4
col  0: [ 3]  c2 16 58
col  1: [23]
56 5f 24 49 4f 46 55 4e 43 4d 45 54 52 49 43 5f 48 49 53 54 4f 52 59
col  2: [ 3]  53 59 53
col  3: [ 4]  56 49 45 57
tab 0, row 2, @0xb66
tl: 45 fb: --H-FL-- lb: 0x1  cc: 4
col  0: [ 3]  c2 16 59
col  1: [22]
56 24 49 4f 46 55 4e 43 4d 45 54 52 49 43 5f 48 49 53 54 4f 52 59
col  2: [ 6]  50 55 42 4c 49 43
col  3: [ 7]  53 59 4e 4f 4e 59 4d

Elapsed: 00:00:00.03


添加新的列COL0

SQL> ALTER TABLE t  ADD ( COL0 VARCHAR2(10));

Table altered.

Elapsed: 00:00:00.16


新添加的列的id变为了2
SQL> SELECT column_name, column_id FROM user_tab_cols  WHERE table_name = 'T' order by 2;

COLUMN_NAME           COLUMN_ID
-------------------- ----------
ID                            1
COL0                          2
COL1
COL3
COL2

添加col0之后,此块的dump结果:

block_row_dump:
tab 0, row 0, @0xb19
tl: 37 fb: --H-FL-- lb: 0x1  cc: 4
col  0: [ 3]  c2 16 57
col  1: [14]  56 24 49 4f 46 55 4e 43 4d 45 54 52 49 43                    --仍然没有变化    原因是因为这列上没有值
col  2: [ 6]  50 55 42 4c 49 43               
col  3: [ 7]  53 59 4e 4f 4e 59 4d
tab 0, row 1, @0xb3e
tl: 40 fb: --H-FL-- lb: 0x1  cc: 4
col  0: [ 3]  c2 16 58
col  1: [23]
56 5f 24 49 4f 46 55 4e 43 4d 45 54 52 49 43 5f 48 49 53 54 4f 52 59
col  2: [ 3]  53 59 53
col  3: [ 4]  56 49 45 57
tab 0, row 2, @0xb66
tl: 45 fb: --H-FL-- lb: 0x1  cc: 4
col  0: [ 3]  c2 16 59
col  1: [22]
56 24 49 4f 46 55 4e 43 4d 45 54 52 49 43 5f 48 49 53 54 4f 52 59
col  2: [ 6]  50 55 42 4c 49 43
col  3: [ 7]  53 59 4e 4f 4e 59 4d


更新此列上的值

SQL> update t set col0='000' where rowid='AAAE1NAAEAAAACDAAA';

1 row updated.

Elapsed: 00:00:00.03
SQL> commit;

Commit complete.

查询结果,COL的值为000
SQL> SELECT t.id,t.col0,t.col1,t.col2,t.col3  from t WHERE ROWID = 'AAAE1NAAEAAAACDAAA';

        ID COL0       COL1                                     COL2       COL3
---------- ---------- ---------------------------------------- ---------- ----------
       652 000        SYS_LOB0000000651C00002$$                SYS        LOB

Elapsed: 00:00:00.01

到这里,偶然发现一个可爱的情况,使用select * 时,在结果中看不到被设置为invisible的列,desc同样看不见,但是如果在select columns_list中手动指定出列名仍然可以被查出来,应该是默认不现实invisible的列


SQL> SELECT *  from t WHERE ROWID = 'AAAE1NAAEAAAACDAAA';

       ID COL0
---------- ----------
       652 000

Elapsed: 00:00:00.00

更新后继续dump:

SQL> alter system dump datafile 4 block 131;

System altered.

dump结果发生了变化:第一行显示有5列,后面的都是4列


block_row_dump:
tab 0, row 0, @0x4b1
tl: 45 fb: --H-FL-- lb: 0x2 cc: 5
col  0: [ 3]  c2 07 35
col  1: [25]
53 59 53 5f 4c 4f 42 30 30 30 30 30 30 30 36 35 31 43 30 30 30 30 32 24 24
col  2: [ 3]  53 59 53
col  3: [ 3]  4c 4f 42
col  4: [ 3]  30 30 30
tab 0, row 1, @0x13d1
tl: 24 fb: --H-FL-- lb: 0x0  cc: 4
col  0: [ 3]  c2 07 38
col  1: [ 6]  4b 4f 54 41 44 24
col  2: [ 3]  53 59 53
col  3: [ 5]  54 41 42 4c 45
tab 0, row 2, @0x13e9
tl: 28 fb: --H-FL-- lb: 0x0 cc: 4
col  0: [ 3]  c2 07 3b
col  1: [10]  53 59 53 5f 43 30 30 38 32 31
col  2: [ 3]  53 59 53
col  3: [ 5]  49 4e 44 45 58

验证数据,观察发现COL 4的值“303030” 是新加进来的,所以尝试转换,结果与我之前更新的000相符
SQL> set serveroutput on
SQL>
SQL> DECLARE
  2        str VARCHAR2(100);
  3  BEGIN
  4        dbms_stats.convert_raw_value('303030', str);
  5        dbms_output.put_line(str);
  6  END;
  7  /
000

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.13


把所有列设置为visible,并查看结果:
SQL> ALTER TABLE  t  MODIFY( COL1 VISIBLE, COL2 VISIBLE, COL3 VISIBLE);

Table altered.

Elapsed: 00:00:00.43

顺序发生了变化
SQL> SELECT column_name, column_id FROM user_tab_cols  WHERE table_name = 'T' order by 2;

COLUMN_NAME           COLUMN_ID
-------------------- ----------
ID                            1
COL0                          2
COL1                          3
COL2                          4
COL3                          5

SQL> desc t
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
ID                                                 NUMBER
COL0                                               VARCHAR2(10)
COL1                                               VARCHAR2(128)
COL2                                               VARCHAR2(128)
COL3                                               VARCHAR2(128)

Elapsed: 00:00:00.21

查询结果也发生了变化
SQL> SELECT *  from t WHERE ROWID = 'AAAE1NAAEAAAACDAAA';

        ID COL0       COL1                                     COL2       COL3
---------- ---------- ---------------------------------------- ---------- ----------
       652 000        SYS_LOB0000000651C00002$$                SYS        LOB

Elapsed: 00:00:00.00

把所有列都设为visible之后 dump结果:
SQL> alter system dump datafile 4 block 131;

System altered.

block_row_dump:
tab 0, row 0, @0x4b1
tl: 45 fb: --H-FL-- lb: 0x2  cc: 5
col  0: [ 3]  c2 07 35
col  1: [25]
53 59 53 5f 4c 4f 42 30 30 30 30 30 30 30 36 35 31 43 30 30 30 30 32 24 24   -----结果与之前一致
col  2: [ 3]  53 59 53
col  3: [ 3]  4c 4f 42
col  4: [ 3]  30 30 30
tab 0, row 1, @0x13d1
tl: 24 fb: --H-FL-- lb: 0x0  cc: 4
col  0: [ 3]  c2 07 38
col  1: [ 6]  4b 4f 54 41 44 24
col  2: [ 3]  53 59 53
col  3: [ 5]  54 41 42 4c 45
tab 0, row 2, @0x13e9
tl: 28 fb: --H-FL-- lb: 0x0  cc: 4
col  0: [ 3]  c2 07 3b
col  1: [10]  53 59 53 5f 43 30 30 38 32 31
col  2: [ 3]  53 59 53
col  3: [ 5]  49 4e 44 45 58

             在这次实验中证实oracle 12c中通过设置列的invisible属性,可以实现我问题中的要求;同时物理结构未发生改变,从修改的时间和dump出来的结果来看确实未发生改变,我觉得可能是修改字典表中COLUMN_ID来实现此功能的,纯属个人猜测,没办法想到了就继续验证,其实上面的内容中已有证据,无奈当时未想到,此时重新再来验证一次,实验步骤如下:



SQL> drop table t purge;

Table dropped.

SQL> create table t
  2  (
  3                   id number,
  4                   col1 varchar2(128),
  5                   col2 varchar2(128),
  6                   col3 varchar2(128)
  7  );

Table created.



查看原表column_id
SQL> SELECT table_name, column_name, data_type, column_id FROM dba_tab_columns  WHERE table_name = 'T'  ORDER BY column_id;

TABLE_NAME           COLUMN_NAME          DATA_TYPE             COLUMN_ID
-------------------- -------------------- -------------------- ----------
T                    ID                   NUMBER                        1
T                    COL1                 VARCHAR2                      2
T                    COL2                 VARCHAR2                      3
T                    COL3                 VARCHAR2                      4

修改为invisible
SQL> ALTER TABLE  t  MODIFY( COL1 INVISIBLE, COL2 INVISIBLE, COL3 INVISIBLE);

Table altered.

Elapsed: 00:00:00.06

查看修改后的结果
SQL> SELECT table_name, column_name, data_type, column_id FROM dba_tab_columns  WHERE table_name = 'T'  ORDER BY column_id;

TABLE_NAME           COLUMN_NAME          DATA_TYPE             COLUMN_ID
-------------------- -------------------- -------------------- ----------
T                    ID                   NUMBER                        1
T                    COL2                 VARCHAR2
T                    COL3                 VARCHAR2
T                    COL1                 VARCHAR2


添加新列col0
SQL> ALTER TABLE t  ADD ( COL0 VARCHAR2(10));

Table altered.

Elapsed: 00:00:00.03

查看新加列后的结果
SQL> SELECT table_name, column_name, data_type, column_id FROM dba_tab_columns  WHERE table_name = 'T'  ORDER BY column_id;

TABLE_NAME           COLUMN_NAME          DATA_TYPE             COLUMN_ID
-------------------- -------------------- -------------------- ----------
T                    ID                   NUMBER                        1
T                    COL0                 VARCHAR2                      2
T                    COL1                 VARCHAR2
T                    COL3                 VARCHAR2
T                    COL2                 VARCHAR2


将所有列设置为visible
SQL> ALTER TABLE  t  MODIFY( COL1 VISIBLE, COL2 VISIBLE, COL3 VISIBLE);

Table altered.

Elapsed: 00:00:00.08

查看最终结果
SQL> SELECT table_name, column_name, data_type, column_id FROM dba_tab_columns  WHERE table_name = 'T'  ORDER BY column_id;

TABLE_NAME           COLUMN_NAME          DATA_TYPE             COLUMN_ID
-------------------- -------------------- -------------------- ----------
T                    ID                   NUMBER                        1
T                    COL0                 VARCHAR2                      2
T                    COL1                 VARCHAR2                      3
T                    COL2                 VARCHAR2                      4
T                    COL3                 VARCHAR2                      5

           实验暂时画上一个句号。我在所有查询dba_tab_columns表的语句都是order by column_id,结果中column_id为null排在了后面,大家都知道 这是oracle对null的处理,所以我大胆的猜测ORACLE也是使用这种方法来处理对列的显示顺序,当我们设置invisible就将column_id设置为NULL,设置为visible时再设置column_id=表中max(column_id)+1。这算是完美解决吗?

原创粉丝点击