尝试将数据从一个环境复制到另一个环境。
根据源表创建分区和子分区,但仍然出现错误:插入的分区键没有映射到任何分区。
谢谢你的帮助。
可以尝试以下步骤:
-
检查分区和子分区的定义和边界。它们很容易弄乱,尤其是在进行子分区时。您必须实际检查所有分区中的子分区布局。子分区存在于一个分区中并不意味着它必须存在于另一个分区中。分区名称是不相关的。重要的是边界(
DBA_TAB_PARTITIONS/SUBPARTITIONS
中的HIGH_VALUE
,不幸的是LONG
,因此需要PL/SQL解决方案以编程方式查询)。 -
检查插入语句并确认将正确的源列放入了正确的目标列中。使用
INSERT
和SELECT
子句的显式列列表,不要依赖默认列顺序。它可能在分区键中插入了错误的列。 -
如果以上所有情况都符合,请查看源表上是否发生过分区交换。源表所有者可能已经与"
WITHOUT VALIDATION
";条款,以便加快进度。这可能导致错误的数据在错误的分区中,直到您尝试选择该数据并将其插入另一个类似的分区表时才会抛出错误,此时它正在进行验证,如果它没有映射到其他分区,则会抛出错误。 -
请记住,子分区可以因分区而异。您可能采用了最新的定义,或者第一个定义,或者子分区模板,这些都不能保证您需要所有分区。一个简单的测试方法是确保定义了一个
(DEFAULT)
子分区(假设它是LIST
)来捕获任何异常值。 -
如果它是一个
RANGE
分区(例如一些日期列),你可以创建一个遥远的未来日期分区(例如VALUES LESS THAN (TO_DATE('12/31/9999','MM/DD/YYYY'))
),然后尝试插入。如果有未知的未来日期,它将进入未来分区,然后您可以查询它以找出它是什么日期。 -
最后,考虑根本不定义分区,而是使用
INTERVAL
(如果RANGE
)或自动列表(如果LIST
),以便Oracle在您插入数据时自动创建分区(例如PARTITION BY RANGE(datecol) INTERVAL NUMTOYMINTERVAL(1,'MONTH')
)。您仍然需要定义一个子分区模板,以便为每个子分区创建子分区。我发现间隔分区在任何可能的情况下都是可取的(除了一些例外)。它是您的朋友,可以节省大量的输入和容易出错的分区定义。
如果您试图插入数据的分区不存在,您有两个选择。
-
从源表获取DDL并在目标表上创建这些分区。
-
运行这个查询,选择partition_name、column_name high_value partition_position从ALL_TAB_PARTITIONS a, ALL_PART_KEY_COLUMNS bwhere table_name='YOUR_TABLE' and a.table_name = b.t name;
该查询列出用作键的列名和允许的值。确保插入了允许的值(high_value)。否则,如果定义了默认分区,它就会到这里。
感谢