Oracle 12c 新特性 --- 创建与分区表进行交换的表

博客涉及数据库分区表和索引的概念及实验,还提供了官方参考文档链接,可帮助了解数据库相关操作与知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念

 

A new DDL command allows the creation of a table that exactly matches the shape of a partitioned table and is therefore eligible for a partition or subpartition exchange of a partitioned table. Note that indexes are not created as part of this command.
新的DDL命令允许创建与分区表的形状完全匹配的表,因此有资格获得分区表的分区或分区交换。注意,索引不是作为该命令的一部分创建的。

Creating a table that qualifies for a partition or subpartition exchange can be a tedious task for older tables that have had various structural changes and reorganizations. With this new DDL, the task becomes very simple and straightforward to implement. It also adds some implicit business context to such an operation, as compared to a CREATE TABLE AS SELECT command.

创建符合分区或子分区交换条件的表,对于具有各种结构更改和重组的旧表来说,是一项单调乏味的任务。有了这个新的DDL,这个任务就变得非常简单,并且很容易实现。它还将一些隐式业务上下文添加到这样的操作中,与CREATE TABLE AS SELECT命令相比。

实验

在ORACLE 12.2中,create table语句被新的“for exchange With”子句丰富了。这使我们能够创建一个交换表,它是已分区表的克隆,它是稍后交换表命令的目标
新的子句处理数据类型、数据规模和精度,而不是NULL约束、隐藏列、虚拟列、未使用的列等。
索引、约束(除了非空)没有被克隆。

1) 创建分区表并建本地索引,主键,插入数据
[leo@www.cndba.cn ~]$ sqlplus / as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on Thu Aug 31 00:15:58 2017

Copyright (c) 1982, 2016, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> conn scott/tiger@pdbcndba
Connected.
SQL> CREATE TABLE EMP_PART ( 
   EMPNO    NUMBER(4,0)       NOT NULL
  ,ENAME    VARCHAR2(10 CHAR) NOT NULL
  ,JOB      VARCHAR2(9 CHAR)  NOT NULL
  ,MGR      NUMBER(4,0)说
  ,HIREDATE DATE              NOT NULL
  ,SAL      NUMBER(7,2)
  ,COMM     NUMBER(7,2)
  ,DEPTNO   NUMBER(2,0)       NOT NULL
  ,CONSTRAINT chk_sal_comm_less_1000 CHECK (NVL(sal,0) + NVL(comm,0) < 10000)
  ,CONSTRAINT chk_empno CHECK (empno between 1000 and 9999)
) 
PARTITION BY LIST (deptno) (
   PARTITION p_accounting VALUES (10)
  ,PARTITION p_research   VALUES (20)
  ,PARTITION p_sales      VALUES (30)
  ,PARTITION p_default    VALUES (DEFAULT)
);

Table created.
--创建本地索引
SQL> CREATE INDEX emp_part_idx ON EMP_PART (hiredate)
   LOCAL (
      PARTITION p_accounting_hiredate_idx
     ,PARTITION p_research_hiredate_idx
     ,PARTITION p_sales_hiredate_idx
     ,PARTITION p_default_hiredate_idx
); 

Index created.

--增加主键
SQL> ALTER TABLE emp_part 
   ADD CONSTRAINT emp_part_pk
   PRIMARY KEY (empno); 

Table altered.

--插入数据
SQL> INSERT INTO emp_part (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO)
SELECT EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO
  FROM emp
 WHERE deptno != 20;  

9 rows created.

SQL> commit;

Commit complete.
2 ) 增加虚拟列,隐藏列,列不可用
SQL> ALTER TABLE emp_part
   ADD total_income GENERATED ALWAYS AS (NVL(SAL,0) + NVL(COMM,0));  2  

Table altered.

SQL> ALTER TABLE emp_part MODIFY deptno INVISIBLE;

Table altered.

SQL> ALTER TABLE emp_part SET UNUSED COLUMN job;

Table altered.

--查看表分区
SQL> col table_name for a10
SQL> col partition_name for a40
SQL> SELECT table_name,
     partition_name
FROM  user_tab_partitions where table_name='EMP_PART';  2    3  

TABLE_NAME PARTITION_NAME
---------- ----------------------------------------
EMP_PART   P_ACCOUNTING
EMP_PART   P_DEFAULT
EMP_PART   P_RESEARCH
EMP_PART   P_SALES

如果我们想要使用一个exchange分区命令来加载department 20的数据,并使用一个现有的表来保存所有这些行,那么我们就必须确保使用的表的结构、索引、约束等都与分区表相同。create table命令中的新子句帮助我们解决这个问题(至少是一些问题)。
3) 创建交换表
SQL> CREATE TABLE emp_part_exchange FOR EXCHANGE WITH TABLE emp_part;

Table created.
--表中插入数据
SQL> INSERT INTO emp_part_exchange(EMPNO,ENAME,MGR,HIREDATE,SAL,COMM,DEPTNO)
SELECT EMPNO,ENAME,MGR,HIREDATE,SAL,COMM,DEPTNO
 FROM emp
 WHERE deptno = 20;

5 rows created.

SQL> commit;

Commit complete.

--查看表,可以看到虚拟列,隐藏列也被复制过来
SQL> set line 300
SQL> col column_name for a50
SQL> col DATA_TYPE for a30
SQL> col null for a10
SQL> col HIDDEN for a20
SQL>  VIRTUAL for a20
SQL> SELECT column_name
      ,data_type || 
       CASE data_type
          WHEN 'VARCHAR2' THEN '(' || data_length || ')'
          WHEN 'NUMBER' THEN NULLIF('(' || data_precision || ',' || data_scale || ')','(,)')
          WHEN 'DATE' THEN NULL
       END AS data_type
      ,nullable
      ,hidden_column
      ,virtual_column
  FROM user_tab_cols
 WHERE table_name = 'EMP_PART_EXCHANGE'
 ORDER BY segment_column_id;

COLUMN_NAME					   DATA_TYPE			  N HID VIR
-------------------------------------------------- ------------------------------ - --- ---
EMPNO						   NUMBER(4,0)			  N NO	NO
ENAME						   VARCHAR2(20) 		  N NO	NO
SYS_C00003_17083100:17:15$	   VARCHAR2(18) 		  Y YES NO
MGR						       NUMBER(4,0)			  Y NO	NO
HIREDATE					   DATE 			      N NO	NO
SAL						       NUMBER(7,2)			  Y NO	NO
COMM						   NUMBER(7,2)			  Y NO	NO
DEPTNO						   NUMBER(2,0)			  N YES NO
TOTAL_INCOME				   NUMBER			      Y NO	YES

9 rows selected.

--可以看到约束没有被创建
SQL> col constraint_name for a20
SQL> col constraint_type for a10
SQL> col search_condition_vc for a30
SQL> SELECT constraint_name, constraint_type, search_condition_vc
  FROM user_constraints
 WHERE table_name = 'EMP_PART_EXCHANGE';

CONSTRAINT_NAME      CONSTRAINT SEARCH_CONDITION_VC
-------------------- ---------- ------------------------------
SYS_C007531	           C		"DEPTNO" IS NOT NULL
SYS_C007532	           C		"EMPNO" IS NOT NULL
SYS_C007533	           C		"ENAME" IS NOT NULL
SYS_C007534	           C		"HIREDATE" IS NOT NULL

SQL> SELECT index_name, index_type, partitioned
  FROM user_indexes
 WHERE table_name = 'EMP_PART_EXCHANGE';
no rows selected

4)如果我们做一个交换分区在这一点上我们会失败如果交换表非空
SQL> ALTER TABLE emp_part 
   EXCHANGE PARTITION p_research 
   WITH TABLE emp_part_exchange; 

Error starting at line : 1 in command -
ALTER TABLE emp_part 
 EXCHANGE PARTITION p_research 
 WITH TABLE emp_part_exchange
Error report -
SQL Error: ORA-14118: CHECK constraint mismatch in ALTER TABLE EXCHANGE PARTITION
14118. 00000 - "CHECK constraint mismatch in ALTER TABLE EXCHANGE PARTITION"
*Cause: The corresponding columns in the tables specified in the
 ALTER TABLE EXCHANGE PARTITION statement have CHECK constraint
 defined on them.
*Action: Ensure that the two tables do not have CHECK constraint
 defined on any column

我们仍然需要手动创建约束交换表…
--分区交换
SQL> ALTER TABLE emp_part_exchange 
   ADD CONSTRAINT chk_sal_comm_less_1000_ep 
   CHECK (NVL(sal,0) + NVL(comm,0) < 10000);

Table altered.

SQL> ALTER TABLE emp_part_exchange 
   ADD CONSTRAINT chk_empno_ep 
   CHECK (empno between 1000 and 9999);

Table altered.

SQL> ALTER TABLE emp_part_exchange 
   ADD CONSTRAINT emp_part_pk_ep
   PRIMARY KEY (empno);  2    3  

--Table altered.
在此之后,交换分区就可以工作了
SQL> ALTER TABLE emp_part 
   EXCHANGE PARTITION p_research 
   WITH TABLE emp_part_exchange;   2    3  

Table altered.

--查看分区数据
SQL> SELECT table_name,
     partition_name
FROM  user_tab_partitions where table_name='EMP_PART';  2    3  

TABLE_NAME PARTITION_NAME
---------- ----------------------------------------
EMP_PART   P_ACCOUNTING
EMP_PART   P_DEFAULT
EMP_PART   P_RESEARCH
EMP_PART   P_SALES

SQL> SELECT * FROM EMP_PART PARTITION(p_research);

     EMPNO ENAME		       MGR HIREDATE	       SAL	 COMM TOTAL_INCOME
---------- -------------------- ---------- ------------ ---------- ---------- ------------
      7369 SMITH		      7902 17-DEC-80	       800		       800
      7566 JONES		      7839 02-APR-81	      2975		      2975
      7788 SCOTT		      7566 19-APR-87	      3000		      3000
      7876 ADAMS		      7788 23-MAY-87	      1100		      1100
      7902 FORD 		      7566 03-DEC-81	      3000		      3000

--查看约束
SQL> col constraint_name for a20
SQL> col constraint_type for a10
SQL> col search_condition_vc for a30
SQL> SELECT constraint_name, constraint_type, search_condition_vc
  FROM user_constraints
 WHERE table_name = 'EMP_PART_EXCHANGE';  2    3  

CONSTRAINT_NAME      CONSTRAINT SEARCH_CONDITION_VC
-------------------- ---------- ------------------------------
SYS_C007531	     C		"DEPTNO" IS NOT NULL
SYS_C007532	     C		"EMPNO" IS NOT NULL
SYS_C007533	     C		"ENAME" IS NOT NULL
SYS_C007534	     C		"HIREDATE" IS NOT NULL
CHK_SAL_COMM_LESS_10 C		NVL(sal,0) + NVL(comm,0) < 100
00_EP				00

CHK_EMPNO_EP	     C		empno between 1000 and 9999
EMP_PART_PK_EP	     P

7 rows selected.

总结:
 与create table as select 表达式创建表相比, FOR EXCHANGE WITH clause of CREATE TABLE 更进一步,它可以创建与分区表的形状完全匹配的表,除了表索引、约束不被创建。

参考官方文档:

http://docs.oracle.com/database/122/VLDBG/maintenance-partition-tables-indexes.htm#VLDBG1118

<think>好的,我现在需要帮助用户解决他们在清理Oracle分区数据时遇到的ORA-14126错误。首先,我需要回顾之前的对话,看看用户之前问过什么,以及我之前给出的建议。用户之前已经询问过这个错误,我给出了详细的分步分析和解决方法,包括语法检查、数据类型验证、分区顺序、名称冲突等。现在用户再次提到同样的错误,但这次是在执行清理分区数据时出现的。 我需要考虑,用户可能已经按照之前的建议检查了语法等问题,但问题依然存在,或者他们在清理过程中遇到了新的情况。ORA-14126通常分区操作中的语法或逻辑错误有关,但清理数据可能涉及不同的操作,比如删除分区、截断分区或者使用DELETE语句。这时候,我需要思考这些操作中可能触发的特定问题。 首先,用户提到的“清理分区数据”可能是指删除旧的分区,比如删除过期的数据分区。常见的操作包括ALTER TABLE DROP PARTITION或TRUNCATE PARTITION。这时候可能出现的错误原因包括: 1. 删除或截断分区的语法错误,比如漏掉了必要的子句或格式不正确。 2. 尝试删除最后一个分区,而结构不允许没有分区存在。 3. 分区名称拼写错误,或者分区不存在。 4. 分区依赖的约束或索引导致无法删除。 5. 权限问题,用户没有执行该操作的权限。 6. 使用了错误的分区维护命令,比如对间隔分区(interval partition)使用了不兼容的操作。 接下来,我需要按照之前的结构,分步骤分析可能的原因,并提供对应的解决方法。同时,要确保回答结构清晰,用户能够逐步排查问题。 在第一步确认错误背景时,需要明确ORA-14126在清理分区时的常见触发原因。例如,用户可能错误地使用了DELETE语句来清理分区数据,而分区表可能更适合使用DROP或TRUNCATE操作,因为DELETE会产生大量undo日志,且效率低下,但这不是ORA-14126的直接原因,但可能需要提醒用户最佳实践。 然后,检查分区维护命令的语法是否正确。比如,删除分区的正确语法是ALTER TABLE ... DROP PARTITION,如果用户漏掉了PARTITION关键字,或者分区名称有误,就会触发错误。 接下来,需要验证分区是否存在。用户可能输入了错误的分区名称,或者该分区已经被删除,导致操作失败。这时候,建议用户查询USER_TAB_PARTITIONS视图来确认分区名称是否正确。 然后,检查是否试图删除或截断最后一个分区。Oracle不允许没有任何分区,所以在删除最后一个分区前,可能需要合并分区或其他操作,或者用户应该使用DROP TABLE代替。 权限问题也需要考虑,用户是否有ALTER TABLE的权限,或者是否有DROP ANY TABLE的权限,这可能导致操作被拒绝,但通常权限问题会触发不同的错误代码,比如ORA-01031,但为了全面性,还是需要提及。 另外,如果是引用分区表或存在全局索引,删除分区可能需要额外的处理,比如UPDATE GLOBAL INDEXES子句,否则可能导致索引失效,进而引发错误。 此外,分区依赖的对象,比如物化视图或分区交换相关的,也可能导致问题,需要检查是否有依赖关系。 最后,建议用户查看详细的错误堆栈,使用DBMS_UTILITY扩展SQL或通过日志定位具体的错误点,并提供示例的正确操作语句,帮助用户修改他们的SQL命令。 需要确保回答结构清晰,每一步都有对应的示例和解决方法,并且语言简洁,易于理解。同时,提醒用户在操作前备份数据,避免数据丢失。</think>以下是针对应用程序清理Oracle分区数据时出现 **ORA-14126** 错误的逐步分析解决方法: --- ### **第一步:明确错误背景** **ORA-14126** 通常在执行分区表维护操作(如删除、截断、合并分区)时触发,常见原因包括: - **语法错误**:分区维护命令(如 `DROP PARTITION`、`TRUNCATE PARTITION`)的语法错误。 - **无效分区名称**:指定了不存在或拼写错误的分区名称。 - **依赖约束冲突**:分区被其他对象(如索引、外键)引用。 - **删除最后一个分区**:尝试删除中唯一的分区(Oracle不允许空分区表)。 --- ### **第二步:检查分区维护命令语法** #### 1. **删除分区** ```sql -- 错误示例:缺少关键字或格式错误 ALTER TABLE sales DROP p2023; -- 正确写法: ALTER TABLE sales DROP PARTITION p2023; ``` #### 2. **截断分区** ```sql -- 错误示例:误用TRUNCATE语法 TRUNCATE TABLE sales PARTITION p2023; -- 正确写法: ALTER TABLE sales TRUNCATE PARTITION p2023; ``` --- ### **第三步:验证分区是否存在** 通过数据字典确认分区名称是否正确: ```sql SELECT partition_name FROM user_tab_partitions WHERE table_name = 'SALES'; -- 替换为实际名 ``` - 若分区名称不存在,需修正为查询结果中的有效名称。 --- ### **第四步:检查是否为最后一个分区** - **错误场景**:若中仅剩一个分区,直接删除会报错。 - **解决方法**: 1. 合并分区或新建分区后再删除。 2. 若需清空,改用 `DROP TABLE`(慎用!需确认无数据保留需求)。 --- ### **第五步:处理依赖对象冲突** #### 1. **全局索引失效** 删除分区时,若未更新全局索引会导致错误: ```sql -- 错误示例:未处理全局索引 ALTER TABLE sales DROP PARTITION p2023; -- 正确写法(更新索引): ALTER TABLE sales DROP PARTITION p2023 UPDATE GLOBAL INDEXES; ``` #### 2. **外键或触发器依赖** 检查是否有外键引用该分区的数据: ```sql SELECT * FROM user_constraints WHERE constraint_type = 'R' AND table_name = 'SALES'; -- 替换为实际名 ``` - 需先禁用约束或级联删除。 --- ### **第六步:检查权限问题** 确保执行用户拥有 `ALTER TABLE` 权限: ```sql GRANT ALTER ANY TABLE TO your_user; -- 由DBA执行 ``` --- ### **第七步:其他注意事项** 1. **间隔分区表(Interval Partitioning)**: -为间隔分区,直接删除分区可能导致隐式分区生成问题,需确认操作是否兼容。 2. **分区键类型**: - 确认清理条件(如日期范围)分区键数据类型匹配,避免隐式转换错误。 --- ### **附:完整排查流程** 1. **提取错误SQL**:从应用日志或数据库跟踪文件中定位具体报错的SQL。 2. **简化操作**:在测试环境手动执行相同命令,复现问题。 3. **使用诊断工具**: ```sql -- 展开复杂SQL的隐式逻辑 DECLARE l_clob CLOB; BEGIN DBMS_UTILITY.EXPAND_SQL_TEXT( input_sql_text => '你的清理SQL', output_sql_text => l_clob ); DBMS_OUTPUT.PUT_LINE(l_clob); END; ``` 4. **查看详细错误堆栈**: ```sql SELECT * FROM dba_errors WHERE name = 'ORA-14126'; ``` --- ### **示例:安全删除分区的完整操作** ```sql -- 1. 确认分区存在 SELECT partition_name, high_value FROM user_tab_partitions WHERE table_name = 'SALES'; -- 2. 删除分区并更新索引 ALTER TABLE sales DROP PARTITION p2023 UPDATE GLOBAL INDEXES; -- 3. 清理后检查状态 SELECT status FROM user_indexes WHERE table_name = 'SALES'; ``` --- 如果需要进一步分析,请提供以下信息: - 完整的清理SQL语句。 - 的分区定义(`CREATE TABLE` 语句)。 - 数据库版本(如 Oracle 11g/12c/19c)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值