百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

Oracle 分区表的 FOR 语句,你这样用过吗?

sinye56 2024-10-10 11:03 5 浏览 0 评论

作者:杨廷琨

原文链接:https://www.modb.pro/db/15418


在11g以后,Oracle简化了指定分区的方式,不再需要明确指定分区名称,而是可以通过指定分区键值列数据的方式来指向对应的分区。

指定一个分区除了使用分区名称外,很多时候还可以使用FOR语句。
从11g开始,对分区进行操作的时候,不仅可以使用分区名称,还可以使用FOR语句。


在10g中,MERGE RANGE分区的语句如下:

SQL> SELECT * FROM V$VERSION;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE    10.2.0.3.0      Production
TNS for Solaris: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production
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')));表已创建。SQL> SELECT * FROM V$VERSION;
BANNER
----------------------------------------------------------------
SQL> ALTER TABLE T_PART_RANGE 
  2  MERGE PARTITIONS P2, P3
  3  INTO PARTITION P3;表已更改。


而在11g中,除了使用分区名称外,还可以使用FOR语句来代替,比如:

SQL> SELECT * FROM V$VERSION;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
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')));表已创建。SQL> ALTER TABLE T_PART_RANGE
  2  MERGE PARTITIONS
  3  FOR(TO_DATE('2009-01', 'YYYY-MM')), 
  4  FOR(TO_DATE('2009-04', 'YYYY-MM'))
  5  INTO PARTITION P3;表已更改。


这种语法的优势对于范围分区还不是很明显,而对于INTERVAL分区就十分有意义了。由于INTERVAL分区的分区名称是系统产生的,用户对INTERVAL分区最直观的莫过于存在分区中的数据的范围,根据分区的定义和INTERVAL的设置很容易可以确定分区的范围和其中的数据,但是分区的名称就必须通过数据字典才能查询得到。

一个INTERVAL分区的简单的例子:

SQL> CREATE TABLE T_PART_INTER
  2  (ID NUMBER, 
  3  NAME VARCHAR2(30), 
  4  CREATE_DATE DATE)
  5  PARTITION BY RANGE (CREATE_DATE) 
  6  INTERVAL (INTERVAL '3' MONTH)
  7  (PARTITION P1 VALUES LESS THAN (TO_DATE('2009-1', 'YYYY-MM')),
  8  PARTITION P2 VALUES LESS THAN (TO_DATE('2009-4', 'YYYY-MM')));表已创建。SQL> INSERT INTO T_PART_INTER
  2  SELECT ROWNUM, OBJECT_NAME, SYSDATE - ROWNUM * 10
  3  FROM USER_OBJECTS;已创建9行。SQL> COMMIT;提交完成。SQL> ALTER TABLE T_PART_INTER
  2  MERGE PARTITIONS
  3  FOR(TO_DATE('2009-10', 'YYYY-MM')),
  4  FOR(TO_DATE('2010-1', 'YYYY-MM'));表已更改。


继续上面的例子:

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: 分区编号无效或超出范围


最终发现了问题所在,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


想了解更多关于数据库、云技术的内容吗?

快来关注“数据和云"、"云和恩墨,"公众号及"云和恩墨"官方网站,我们期待大家一同学习与进步!

小程序”DBASK“在线问答,随时解惑,欢迎了解和关注!

相关推荐

Linux基础知识之修改root用户密码

现象:Linux修改密码出现:Authenticationtokenmanipulationerror。故障解决办法:进入单用户,执行pwconv,再执行passwdroot。...

Linux如何修改远程访问端口

对于Linux服务器而言,其默认的远程访问端口为22。但是,出于安全方面的考虑,一般都会修改该端口。下面我来简答介绍一下如何修改Linux服务器默认的远程访问端口。对于默认端口而言,其相关的配置位于/...

如何批量更改文件的权限

如果你发觉一个目录结构下的大量文件权限(读、写、可执行)很乱时,可以执行以下两个命令批量修正:批量修改文件夹的权限chmod755-Rdir_name批量修改文件的权限finddir_nam...

CentOS「linux」学习笔记10:修改文件和目录权限

?linux基础操作:主要介绍了修改文件和目录的权限及chown和chgrp高级用法6.chmod修改权限1:字母方式[修改文件或目录的权限]u代表所属者,g代表所属组,o代表其他组的用户,a代表所有...

Linux下更改串口的权限

问题描述我在Ubuntu中使用ArduinoIDE,并且遇到串口问题。它过去一直有效,但由于可能不必要的原因,我觉得有必要将一些文件的所有权从root所有权更改为我的用户所有权。...

Linux chown命令:修改文件和目录的所有者和所属组

chown命令,可以认为是"changeowner"的缩写,主要用于修改文件(或目录)的所有者,除此之外,这个命令也可以修改文件(或目录)的所属组。当只需要修改所有者时,可使用...

chmod修改文件夹及子目录权限的方法

chmod修改文件夹及子目录权限的方法打开终端进入你需要修改的目录然后执行下面这条命令chmod777*-R全部子目录及文件权限改为777查看linux文件的权限:ls-l文件名称查看li...

Android 修改隐藏设置项权限

在Android系统中,修改某些隐藏设置项或权限通常涉及到系统级别的操作,尤其是针对非标准的、未在常规用户界面显示的高级选项。这些隐藏设置往往与隐私保护、安全相关的特殊功能有关,或者涉及开发者选项、权...

完蛋了!我不小心把Linux所有的文件权限修改了!在线等修复!

最近一个客户在群里说他一不小心把某台业务服务器的根目录权限给改了,本来想修改当前目录,结果执行成了根目录。...

linux改变安全性设置-改变所属关系

CentOS7.3学习笔记总结(五十八)-改变安全性设置-改变所属关系在以前的文章里,我介绍过linux文件权限,感兴趣的朋友可以关注我,阅读一下这篇文章。这里我们不在做过的介绍,注重介绍改变文件或者...

Python基础到实战一飞冲天(一)--linux基础(七)修改权限chmod

#07_Python基础到实战一飞冲天(一)--linux基础(七)--修改权限chmod-root-groupadd-groupdel-chgrp-username-passwd...

linux更改用户权限为root权限方法大全

背景在使用linux系统时,经常会遇到需要修改用户权限为root权限。通过修改用户所属群组groupid为root,此操作只能使普通用户实现享有部分root权限,普通用户仍不能像root用户一样享有超...

怎么用ip命令在linux中添加路由表项?

在Linux中添加路由表项,可以使用ip命令的route子命令。添加路由表项的基本语法如下:sudoiprouteadd<network>via<gateway>这...

Linux配置网络

1、网卡名配置相关文件回到顶部网卡名命名规则文件:/etc/udev/rules.d/70-persistent-net.rules#PCIdevice0x8086:0x100f(e1000)...

Linux系列---网络配置文件

1.网卡配置文件在/etc/sysconfig/network-scripts/下:[root@oldboynetwork-scripts]#ls/etc/sysconfig/network-s...

取消回复欢迎 发表评论: