2015-01-13 4 views
0

В принципе, нужно отказаться от старых разделов (ов) в таблице 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; 

дата присутствует в колонке "high_value". Например, один из разделов High_value = TO_DATE(' 1950-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')

Мне нужна дата, которая будет храниться в переменной «l_date», поэтому ее можно использовать для дальнейших вычислений.

Ошибка:

ORA-01843: не действительный месяц

ORA-06512: в строке 9

01843.00000 - "не действительный месяц"

+3

Какие у вас проблемы? Выполняется ли это, и если да, то в чем разница между результатами и ожидаемым? – DaaaahWhoosh

+1

Вы получаете «ORA-01830: конец формата даты заканчивается перед преобразованием всей строки ввода»? Аргумент substr и форматная модель выглядят неправильно для раздела даты; какие сырые высокие ценности вы ожидаете? –

ответ

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 (используя, например, регулярное выражение) и используйте это!

UPDATE Это будет работать, чтобы захватить маску, предполагая, что 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))); 

Надежда это помогает.

+0

Извините за задержку в ответе, спасибо за код предложения, он работал так, как я хотел. – Lastwish