指定一个分区除了使用分区名称外,很多时候还可以使用FOR语句。
这篇描述测试FOR语句时碰到的ORA-14702错误。
仍然使用上一篇文章的例子:
SQL> CREATE TABLE T_PART_RANGE
2 (ID NUMBER,
3 NAME VARCHAR2(30),
4 CREATE_DATE DATE)
5 PARTITION BY RANGE (CREATE_DATE)
6 (PARTITION P1 VALUES LESS THAN (TO_DATE('2009-1', 'YYYY-MM')),
7 PARTITION P2 VALUES LESS THAN (TO_DATE('2009-4', 'YYYY-MM')),
8 PARTITION P3 VALUES LESS THAN (TO_DATE('2009-7', 'YYYY-MM')));
表已创建。
下面打算通过FOR语句的方式合并P2和P3分区:
SQL> ALTER TABLE T_PART_RANGE
2 MERGE PARTITIONS
3 FOR(TO_DATE('2009-4', 'YYYY-MM')),
4 FOR(TO_DATE('2009-7', 'YYYY-MM'))
5 INTO PARTITION P3;
ALTER TABLE T_PART_RANGE
*
第1行出现错误:
ORA-14702:分区编号无效或超出范围
语句出现了ORA-14702错误,查询Oracle的错误文档:
ORA-14702: The partition number is invalid or out-of-range
Cause:Attempted to use nonnumerical value or the number was out of range of the partitions.
Action:Use a valid partition number.
根据错误文档的描述,感觉是分区键值指定出现了错误,查询分区信息:
SQL> SELECT PARTITION_NAME, HIGH_VALUE
2 FROM USER_TAB_PARTITIONS
3 WHERE TABLE_NAME = 'T_PART_RANGE'
4 ORDER BY 1;
PARTITION_NAME HIGH_VALUE
-------------- ----------------------------------------------------------------------------------
P1 TO_DATE(' 2009-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
P2 TO_DATE(' 2009-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
P3 TO_DATE(' 2009-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
难道是分区键值指定有问题:
SQL> ALTER TABLE T_PART_RANGE
2 MERGE PARTITIONS
3 FOR(TO_DATE(' 2009-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')),
4 FOR(TO_DATE(' 2009-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
5 INTO PARTITION P3;
ALTER TABLE T_PART_RANGE
*
第1行出现错误:
ORA-14702:分区编号无效或超出范围
完全仿照USER_TAB_PARTITIONS视图中的分区定义,错误依旧。
最终发现了问题所在,FOR语句中指定的并不是分区定义时使用的值,而是存储在当前分区中的值:
SQL> ALTER TABLE T_PART_RANGE
2 MERGE PARTITIONS
3 FOR(TO_DATE('2009-1', 'YYYY-MM')),
4 FOR(TO_DATE('2009-4', 'YYYY-MM'));
表已更改。
SQL> SELECT PARTITION_NAME, HIGH_VALUE
2 FROM USER_TAB_PARTITIONS
3 WHERE TABLE_NAME = 'T_PART_RANGE'
4 ORDER BY 1;
PARTITION_NAME HIGH_VALUE
--------------- ---------------------------------------------------------------------------------
P1 TO_DATE(' 2009-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
SYS_P78 TO_DATE(' 2009-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
可以看到,在使用FOR语句的时候,是根据P1和P2分区定义时的日期指定的分区,但是MERGE的结果却是P2和P3分区进行了合并。
因此Oracle并非根据分区定义来判断分区,而是根据用户给出的值,来判断所属分区,所以,P1分区和SYS_P78分区的合并完全可以写成:
SQL> ALTER TABLE T_PART_RANGE
2 MERGE PARTITIONS
3 FOR(TO_DATE('1970-1', 'YYYY-MM')),
4 FOR(TO_DATE('2009-5', 'YYYY-MM'));
表已更改。
由于FOR语句的这种特性,使得HASH分区也可以使用这个特性:
SQL> CREATE TABLE T_PART_HASH
2 (ID NUMBER,
3 NAME VARCHAR2(30))
4 PARTITION BY HASH(ID)
5 PARTITIONS 16;
表已创建。
SQL> ALTER TABLE T_PART_HASH
2 MOVE PARTITION FOR(6);
表已更改。
这个例子对包含ID为6的分区进行了MOVE操作,而且甚至不需要指定的ID存在。
最后给一个简单的LIST分区的SPLIT的例子:
SQL> CREATE TABLE T_PART_LIST
2 (
3 OWNER VARCHAR2(30),
4 TABLE_NAME VARCHAR2(30),
5 TABLESPACE_NAME VARCHAR2(30),
6 STATUS VARCHAR2(18)
7 )
8 PARTITION BY LIST (TABLESPACE_NAME)
9 (
10 PARTITION P1 VALUES ('SYSTEM'),
11 PARTITION P2 VALUES ('YANGTK'),
12 PARTITION P3 VALUES (DEFAULT)
13 );
表已创建。
SQL> ALTER TABLE T_PART_LIST
2 SPLIT PARTITION FOR('SYSAUX')
3 VALUES ('SYSAUX')
4 INTO (PARTITION P3, PARTITION P4);
表已更改。
SQL> SELECT PARTITION_NAME, HIGH_VALUE
2 FROM USER_TAB_PARTITIONS
3 WHERE TABLE_NAME = 'T_PART_LIST'
4 ORDER BY 1;
PARTITION_NAME HIGH_VALUE
--------------- -------------------------------------
P1 'SYSTEM'
P2 'YANGTK'
P3 'SYSAUX'
P4 DEFAULT
oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html