从多个表中删除清理脚本SQL

时间:2018-04-30 12:29:34

标签: sql oracle plsql maintainability rowdeleting

在底部回答,最终发现。 thx所有的贡献。

我必须创建一个脚本,我将在一个存储过程中生成,然后每隔几个月运行一次。它需要进入一些特定的表并删除旧记录。我认为这将非常简单,但我仍然遇到同样的问题。

如果我尝试运行我得到的代码和无效的标识符错误,它似乎是日期字段的问题,其中oracle默认使用字母数月,我尝试了各种日期格式化,但我似乎没有工作。

我声明要从哪个日期删除,然后将执行立即声明串起来,该声明将循环通过包含表名的tabletoclean表,以及我将执行清理的表的日期字段名称。 / p>

错误代码为ORA-00904:“APR”无效的意图 我猜它是因为它试图使用APR - APRIL而不是04.但我不知道。据我所知,没有一个dtl_fields使用月份名称日期格式化。

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中运行execute immediate字符串,则返回字符串 从mytable中选择* datefield&lt; 30-APR-16

确认问题正确地与日期格式化有关。

编辑/答案 问题出在dtldate变量上。它将日期发布到执行立即,如下所示。

从mytable中选择* datefield&lt; 30-APR-16

这不起作用,但

从mytable中选择* datefield&lt; '30 -APR-16'

可以工作,所以我编辑了以下代码的字符串。

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 :(得分:2)

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;

答案 1 :(得分:-1)

这是处理日期的正确方法:

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;