ORA-01830选择子分区时出错 - 适用于没有的表

时间:2016-04-27 16:03:09

标签: sql oracle

我们使用分区管理包,自动创建和删除分区,命名格式为YYYY_MM_DD。

目前该进程仅用于具有1个分区级别的表,现在我们需要将子分区添加到某些表中。

我们用来删除表等的命令在新的子分区表上都正常工作(例如ALTER TABLE DROP PARTITION" YYYY_MM_DD"),但是我们用来计算那些需要的游标drop会导致ORA-01830错误。

SELECT PARTITION_NAME
FROM USER_TAB_PARTITIONS
WHERE TABLE_NAME = 'TABLE_NAME'
and TO_DATE(PARTITION_NAME, 'YYYY_MM_DD') < SYSDATE;

当&#39; TABLE_NAME&#39;是一个正常的分区表,命令正常工作,但当它是子分区表时,它会出错ORA-01830。

SELECT PARTITION_NAME, TO_DATE(PARTITION_NAME, 'YYYY_MM_DD')
FROM USER_TAB_PARTITIONS
WHERE TABLE_NAME = 'TABLE_NAME';

上述工作 - 它似乎是在我们遇到问题的where子句中使用它时。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:2)

当你运行像

这样的查询时
SELECT PARTITION_NAME
  FROM USER_TAB_PARTITIONS
 WHERE TABLE_NAME = 'TABLE_NAME'
   and TO_DATE(PARTITION_NAME, 'YYYY_MM_DD') < SYSDATE;

Oracle可以按其选择的任何顺序自由评估谓词。 user_tab_partitions是一个连接许多不同对象的视图(如果你是如此倾向,你可以将它追溯到一堆x $对象和内存结构)。如果partition_name不是有效日期的任何对象中有一行,即使它与此特定表无关,此语句也可能失败。如果您碰巧幸运,并且您的查询计划涉及应用table_name谓词来过滤掉在应用to_date谓词之前无法正确转换的所有数据,则查询将起作用。如果您碰巧不幸,Oracle会在评估to_date谓词之前尝试将table_name谓词应用于转换引发错误的行。由于查询计划可能会随着时间的推移而发生变化,因此现在可用的查询可能会继续有效,直到有一天失败(反之亦然,当前失败的查询可能会突然明天或下周或明年开始工作)。当底层对象中的数据发生变化时,您可能也会遇到失败,这是我在添加子分区时怀疑发生的事情。

解决此问题的一个选项是创建自己的函数,尝试执行字符串到日期转换并吞下错误

CREATE OR REPLACE FUNCTION my_to_date( p_str IN VARCHAR2, 
                                       p_mask IN VARCHAR2 )
IS
  l_dt date;
BEGIN
  l_dt := to_date( p_str, p_mask );
  return l_dt;
EXCEPTION
  WHEN others THEN
    RETURN null;
END;

在实际代码中,您可能希望捕获实际异常,而不是使用when others。但这样可以让你做类似

的事情
SELECT PARTITION_NAME
  FROM USER_TAB_PARTITIONS
 WHERE TABLE_NAME = 'TABLE_NAME'
   and my_to_date(PARTITION_NAME, 'YYYY_MM_DD') < SYSDATE;

您还可以按照您想要的顺序强制执行步骤 - 例如,将所有分区名称选择到集合中,然后遍历集合以消除未来日期的分区。或者,由于分区名称字符串的排序方式与日期值排序的方式相同(假设MM和DD包含前导0),您可以进行显式字符串比较。

SELECT PARTITION_NAME
  FROM USER_TAB_PARTITIONS
 WHERE TABLE_NAME = 'TABLE_NAME'
   and PARTITION_NAME < to_char(SYSDATE, 'YYYY_MM_DD');