ORA-14096: Tables in ALTER TABLE EXCHANGE PARTITION Must Have the Same Number of Columns
ORA-14096 is thrown when you attempt an ALTER TABLE ... EXCHANGE PARTITION operation and the partitioned table and the non-partitioned exchange table do not have the same number of columns. Oracle requires that both tables be structurally identical — matching column count, data types, and column order — before allowing a partition swap. This error is especially common in data warehouse environments where staging tables are created manually or with outdated DDL scripts.
Top 3 Causes
1. Column Count Mismatch Between the Two Tables
The most straightforward cause: the partitioned table has a different number of columns than the staging table. This typically happens when a column is added or dropped from the partitioned table after the staging table was originally created, and that change was never propagated to the staging table.
-- Check column counts for both tables
SELECT
(SELECT COUNT(*) FROM user_tab_cols WHERE table_name = 'SALES_PART') AS part_columns,
(SELECT COUNT(*) FROM user_tab_cols WHERE table_name = 'SALES_STAGE') AS stage_columns
FROM dual;
-- Find columns in the partition table but missing from the staging table
SELECT column_name, data_type, data_length
FROM user_tab_cols WHERE table_name = 'SALES_PART'
MINUS
SELECT column_name, data_type, data_length
FROM user_tab_cols WHERE table_name = 'SALES_STAGE';
2. Staging Table Built from an Incorrect or Partial DDL
When the staging table is created manually or using a CREATE TABLE AS SELECT with only selected columns, the column count will not match. Reusing old DDL scripts without checking for schema changes is a common pitfall in production environments.
-- WRONG: This creates a table with only selected columns
CREATE TABLE sales_stage AS
SELECT sale_id, sale_date, amount -- missing columns!
FROM sales_part WHERE 1 = 0;
-- CORRECT: Derive the staging table from the full partition table structure
CREATE TABLE sales_stage AS
SELECT * FROM sales_part WHERE 1 = 0;
3. Hidden or Virtual Columns in the Partitioned Table
Oracle can add hidden virtual columns internally, for example when a function-based index is created. These columns do not appear in a standard DESC output but are counted by Oracle's partition exchange validation. If the staging table lacks these hidden columns, ORA-14096 will be raised.
-- Check for virtual/hidden columns (use user_tab_cols, NOT user_tab_columns)
SELECT column_name, hidden_column, virtual_column, data_default
FROM user_tab_cols
WHERE table_name = 'SALES_PART'
AND (hidden_column = 'YES' OR virtual_column = 'YES');
-- Add the matching virtual column to the staging table
ALTER TABLE sales_stage
ADD (annual_revenue AS (monthly_revenue * 12));
Quick Fix Solutions
Fix 1 — Add the missing column to the staging table:
ALTER TABLE sales_stage ADD (region_code VARCHAR2(10));
-- Retry the exchange
ALTER TABLE sales_part
EXCHANGE PARTITION p_2024_q1
WITH TABLE sales_stage
WITHOUT VALIDATION;
Fix 2 — Recreate the staging table from the partitioned table:
DROP TABLE sales_stage PURGE;
CREATE TABLE sales_stage AS
SELECT * FROM sales_part WHERE 1 = 0;
ALTER TABLE sales_part
EXCHANGE PARTITION p_2024_q1
WITH TABLE sales_stage
INCLUDING INDEXES
WITHOUT VALIDATION;
Prevention Tips
1. Always derive the staging table directly from the partitioned table.
Never hand-write DDL for a staging table used in partition exchange. Use CREATE TABLE AS SELECT * FROM <partition_table> WHERE 1=0 every time to guarantee structural parity. Rebuild the staging table at the start of each load cycle to pick up any schema changes automatically.
2. Add a pre-flight validation step to your ETL workflow.
Before executing any EXCHANGE PARTITION, run a quick column-count check and structure comparison. This can be embedded as a stored procedure or a shell script guard that aborts the job if a mismatch is detected, preventing runtime failures in production.
-- Simple pre-flight guard query
DECLARE
v_diff NUMBER;
BEGIN
SELECT ABS(
(SELECT COUNT(*) FROM user_tab_cols WHERE table_name = 'SALES_PART') -
(SELECT COUNT(*) FROM user_tab_cols WHERE table_name = 'SALES_STAGE')
) INTO v_diff FROM dual;
IF v_diff > 0 THEN
RAISE_APPLICATION_ERROR(-20001,
'ORA-14096 risk detected: column count mismatch. Aborting exchange.');
END IF;
END;
/
Related Errors
- ORA-14097 – Column type or length mismatch between the two tables during partition exchange.
- ORA-14098 – ROW MOVEMENT setting differs between the partitioned and exchange tables.
- ORA-14400 – Inserted row does not map to any partition; may appear after a partition exchange when re-inserting data.
📖 Want a more detailed guide?
Check out the full in-depth version (Korean) on oraerror.com — includes detailed analysis, additional SQL examples, and prevention tips.
Top comments (0)