Удаление из нескольких таблиц сценария очистки SQL - PullRequest
0 голосов
/ 30 апреля 2018

Ответ внизу, выяснил в конце концов. Спасибо за все вклады.

Мне нужно сделать скрипт, который я буду превращать в хранимую процедуру, которая будет запускаться каждые несколько месяцев. Для этого нужно будет перейти в некоторые конкретные таблицы и удалить старые записи. Я думал, что это будет довольно просто, но я продолжаю сталкиваться с той же проблемой.

если я пытаюсь запустить полученный код и ошибку неверного идентификатора, это, похоже, проблема с полем даты, где оракул по умолчанию использует буквы в течение месяцев, я пробовал различное форматирование даты, но я не вижу на работу.

Я объявляю, с какой даты я хочу удалить, и затем строю вместе оператор немедленного выполнения, который будет проходить по циклу таблицы tabletoclean, содержащей имя таблицы и имя поля даты таблиц, на которых я буду выполнять очистку.

Код ошибки: ORA-00904: недопустимый интендификатор «APR». Я думаю, потому что он пытается использовать APR - APRIL вместо 04. но я не знаю. Насколько я вижу, ни одно из полей dtl_ не использует форматирование даты в названии месяца.

Declare
dtldate date := to_date(add_months( to_date(sysdate), -24 ), 'dd-mm-yy');

Begin
  for tbl IN (Select * from tbltoclean)
loop 

 execute immediate 'Delete from '||tbl.tbl_name || ' where ' || tbl.dtl_field ||' < ' || dtldate;

 DBMS_OUTPUT.PUT_LINE ('Deleted from '|| to_char(tbl.tbl_name));
 end loop;
 end;

если я запускаю строку немедленного выполнения в dbms.output, я возвращаю строку как Выберите * из таблицы, где поле даты <30-апреля-16 </p>

Подтверждение того, что проблема правильно связана с форматированием даты.

РЕДАКТИРОВАТЬ / ОТВЕТИТЬ Проблема была с переменной dtldate. он разместил даты для немедленного исполнения следующим образом.

Выберите * из таблицы, где поле даты <30-APR-16 </p>

Это не сработало, но

Выберите * из таблицы, где поле даты <'30 -APR-16 '</p>

будет работать, поэтому я отредактировал строку, в которой работает следующий код.

Declare
dtldate date := add_months( to_date(sysdate), -24 );

Begin
  for tbl IN (Select * from tbltoclean)
loop 

 execute immediate 'Select null from '||tbl.tbl_name || ' where ' || tbl.dtl_field ||' < ' || 'to_date('''||dtldate||''')'; --dtldate have escaped ''

 DBMS_OUTPUT.PUT_LINE ('Deleted from '|| to_char(tbl.tbl_name));
 end loop;
 end;

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

Это правильный способ лечения ДАТЫ:

DECLARE
    --
    DTLDATE DATE;
    --
BEGIN
    --
    DTLDATE := TRUNC(SYSDATE) -- 30/04/2018 14:36 -> 30/04/2018
    --
    DTLDATE := ADD_MONTHS(DTLDATE, -24) -- 30/04/2018 -> 30/04/2016
    --
    FOR TBL IN (SELECT * FROM TBLTOCLEAN) LOOP 
        --
        EXECUTE IMMEDIATE 'DELETE FROM '||TBL.TBL_NAME || 
                          ' WHERE ' || TBL.DTL_FIELD ||' < :DTLDATE' 
          USING DTLDATE;
        DBMS_OUTPUT.PUT_LINE ('DELETED FROM '|| TBL.TBL_NAME);
        --
    END LOOP;
    --
 END;
0 голосов
/ 30 апреля 2018

SYSDATE - это функция, которая возвращает DATE тип данных; нет смысла конвертировать его в дату (с TO_DATE) еще раз.

Итак, это может делать то, что вы хотите:

declare
  dtldate date := add_months(trunc(sysdate), -24);
begin
  for tbl in (select * from tbltoclean)
  loop 
    execute immediate 'Delete from '||tbl.tbl_name || 
                      ' where ' || tbl.dtl_field ||' < DATE ''' || to_char(dtldate, 'YYYY-MM-DD') || '''';

    dbms_output.put_line ('Deleted from '|| to_char(tbl.tbl_name));
  end loop;
end;
...