oracle表分区:更改分区键值列的数据,导致ORA-14402错误

alter table xxx enable row movement;

from asktom:


It is possible to update a partition key in all releases -- what is not possible
to do prior to 8i is to update the partition key in such a fashion as to cause
it to move from partition to partition.  For example:

ops$tkyte@8.0> CREATE TABLE partitioned
  2  ( x int,
  3    y int,
  4    z DATE
  5  )
  6  PARTITION BY RANGE (z)
  7  (
  8  PARTITION part_1 VALUES LESS
           THAN(to_date('01-jan-1995','dd-mon-yyyy')),
  9  PARTITION part_2 VALUES LESS
           THAN(to_date('01-jan-1996','dd-mon-yyyy'))
10  )
11  /

Table created.

ops$tkyte@8.0>
ops$tkyte@8.0> insert into partitioned values
  2  ( 1, 1, to_date('01-jan-1994','dd-mon-yyyy') );

1 row created.

ops$tkyte@8.0>
ops$tkyte@8.0> insert into partitioned values
  2  ( 2, 1, to_date('01-mar-1995','dd-mon-yyyy') );

1 row created.

ops$tkyte@8.0>
ops$tkyte@8.0> commit;

Commit complete.

ops$tkyte@8.0>
ops$tkyte@8.0> update partitioned set
  2           z = to_date('01-jan-1993')
               where z = to_date('01-jan-1994')
  3  /

1 row updated.

That shows we CAN update a partition key in 8.0

ops$tkyte@8.0> rollback;

Rollback complete.

ops$tkyte@8.0>
ops$tkyte@8.0> update partitioned set
  2  z = decode( x, 1, to_date('01-mar-1995','dd-mon-yyyy'),
  3              2, to_date('01-jan-1994','dd-mon-yyyy') )
  4  /
update partitioned set
       *
ERROR at line 1:
ORA-14402: updating partition key column would cause a partition change

But we cannot have it migrate.  Now, in Oracle8i, release 8.1 we can:

ops$tkyte@8i> CREATE TABLE partitioned
  2  ( x int,
  3    y int,
  4    z DATE
  5  )
  6  PARTITION BY RANGE (z)
  7  (
  8  PARTITION part_1 VALUES LESS
         THAN(to_date('01-jan-1995','dd-mon-yyyy')),
  9  PARTITION part_2 VALUES LESS
         THAN(to_date('01-jan-1996','dd-mon-yyyy'))
10  )
11  ENABLE ROW MOVEMENT
12  /

Table created.

Enable row movement will allow us to update a partition key and have it move
from partition to partition

ops$tkyte@8i>
ops$tkyte@8i> insert into partitioned values
  2  ( 1, 1, to_date('01-jan-1994','dd-mon-yyyy') );

1 row created.

ops$tkyte@8i>
ops$tkyte@8i> insert into partitioned values
  2  ( 2, 1, to_date('01-mar-1995','dd-mon-yyyy') );

1 row created.

ops$tkyte@8i>
ops$tkyte@8i> commit;

Commit complete.

ops$tkyte@8i>
ops$tkyte@8i> select rowid, a.* from partitioned a;

ROWID                       X          Y Z
------------------ ---------- ---------- ---------
AAAWBlAADAAAIfKAAA          1          1 01-JAN-94
AAAWBmAADAAAIgKAAA          2          1 01-MAR-95

ops$tkyte@8i> update partitioned set
  2  z = decode( x, 1, to_date('01-mar-1995','dd-mon-yyyy'),
  3              2, to_date('01-jan-1994','dd-mon-yyyy') )
  4  /

2 rows updated.

ops$tkyte@8i> select rowid, a.* from partitioned a;

ROWID                       X          Y Z
------------------ ---------- ---------- ---------
AAAWBlAADAAAIfKAAB          2          1 01-JAN-94
AAAWBmAADAAAIgKAAB          1          1 01-MAR-95

ops$tkyte@8i> commit;

Commit complete.


but -- notice the side effect -- the rows ROWID changed, one of 2 cases in
Oracle8i release 8.1 whereby for the first time a rowid of a row will change
(index organized tables are the other case -- if you update the primary key)

posted on 2008-12-28 20:26  一江水  阅读(4476)  评论(0编辑  收藏  举报