从字符串中提取日期的一部分

时间:2015-01-13 18:31:47

标签: sql oracle plsql partitioning substr

基本上想要删除Oracle表中的旧分区,目前在使用SUBSTR函数时遇到问题。

代码:

DECLARE
  l_sql_stmt VARCHAR2(1000);
  l_date     DATE;

BEGIN
  FOR x IN (SELECT * 
             FROM user_tab_partitions
             WHERE table_name = 'TABLE_NAME')
  LOOP
    l_date := to_date( substr( x.high_value, 11, 19 ), 'YYYYMMDD' );
    IF( l_date < add_months( trunc(sysdate), -15 ) )
      THEN
        l_sql_stmt := 'ALTER TABLE TABLE_NAME' || ' DROP PARTITION ' || x.partition_name;
        dbms_output.put_line( l_sql_stmt );
        EXECUTE IMMEDIATE l_sql_stmt;
     END IF;
  END LOOP;
END;

日期出现在&#34; HIGH_VALUE&#34;列中。 例如,分区的一个High_value = TO_DATE(' 1950-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

我需要将日期存储在&#34; l_date&#34;变量,因此它可以用于进一步的计算。

错误:

ORA-01843:不是有效月份

ORA-06512:第9行

01843.00000 - &#34;不是有效月份&#34;

1 个答案:

答案 0 :(得分:0)

如果high_value等于以下(我认为您正在说的话):TO_DATE(' 1950-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'),那么以下代码行是错误的:

l_date := to_date( substr( x.high_value, 11, 19 ), 'YYYYMMDD' );

错误的原因是掩码YYYYMMDD错误。 SUBSTR( x.high_value, 11, 19)将返回以下内容:

1950-01-01 00:00:00

所以你想用YYYY-MM-DD HH24:MI:SS作为面具:

l_date := to_date( substr( x.high_value, 11, 19 ), 'YYYY-MM-DD HH24:MI:SS' );

或者SYYYY-MM-DD(如high_value本身所述),假设年份必须签名

l_date := to_date( substr( x.high_value, 11, 19 ), 'SYYYY-MM-DD HH24:MI:SS' );

尝试从high_value(例如,使用正则表达式)中提取掩码并使用它可能是值得的!

更新这将捕获掩码,假设high_value具有相同的通用格式:

-- Try to capture the mask
WITH x AS (
    SELECT 'TO_DATE('' 1950-01-01 00:00:00'', ''SYYYY-MM-DD HH24:MI:SS'', ''NLS_CALENDAR=GREGORIAN'')' AS high_value
      FROM dual
)
SELECT REGEXP_SUBSTR(x.high_value, '[^'']+', INSTR(x.high_value, '''', 1, 3))
  FROM x

因此,您可以在代码中使用以下内容:

l_date := TO_DATE( SUBSTR( x.high_value, 11, 19 ), REGEXP_SUBSTR( x.high_value, '[^'']+', INSTR( x.high_value, '''', 1, 3 ) ) );

希望这有帮助。