我对Oracle PL / SQL数据库应用程序的开发非常陌生......我有一个客户要求,我们为他们创建了一个ETL,它删除了前几天的表。该表是使用同义词创建的,它需要一个时间戳来创建表,例如:TEST_TEST_todaysdate
现在他们想改变ETL并且不想放弃前几天的表,而是他们希望保留三天的数据,并且在第四天......程序应该删除最后几天作为循环使表保留最后三天!我希望你们能得到我,但就像这样 - 从星期一到星期三,星期四然后删除星期一,星期五然后删除星期二等等。
以下是代码段:
-- check &&1..&&3._&&2
select count(*)
into v_exist
from all_tables
where owner = upper('&&1')
and table_name = upper('&&3._&&2');
if v_exist > 0 then
for r in (select owner,table_name
from all_tables
where owner = upper('&&1')
and table_name like upper('&&3%') --- exclude MASTER_* tables
and table_name <> upper('&&3') --- just for precaution
这是我的代码:
and table_name = start_day DATE as ((SELECT extract(hour from current_timestamp)) - 4 FROM dual
--and table name =' || previous_days_table ||' -- saving previous days table
and table_name < upper('&&3._&&2')) loop
v_sql := 'DROP TABLE ' || r.owner || '.' || r.table_name || ' CASCADE CONSTRAINTS PURGE';
dbms_output.put_line(v_sql);
execute immediate v_sql;
end loop;
end if;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;
答案 0 :(得分:2)
有两种方法可以做到这一点;第一个是基于你自己的日期戳;表创建日期的第二个。
假设您的日期戳格式为YYYYMMDD,我会这样做:
begin
for xx in ( select owner, table_name
from all_tables
where regexp_like(table_name, 'TEST_TEST_[[:digit:]]{8}')
and to_date(substr(table_name, -8), 'yyyymmdd') < trunc(sysdate) - 4
and owner = 'THE_OWNER'
) loop
execute immediate 'drop table ' ||
xx.owner || '.' ||
xx.table_name ||
' purge';
end loop;
end;
/
基本上,所有这些都是为了让你的SQL语句正确,以便你只包含你想要删除的表。
或者,您可以使用从ALL_OBJECTS创建对象的日期,使您的SQL语句如下:
select owner, object_name
from all_objects
where object_type = 'TABLE'
and regexp_like(object_name, 'TEST_TEST_[[:digit:]]{8}')
and trunc(created) < trunc(sysdate) - 4
and owner = 'THE_OWNER'
;
请注意,这样做,特别是使用PURGE关键字本身就很危险。如果可能的话,最好将ETL更改为加载到单个表中,并将日期作为列,然后从该表中删除不再需要的任何数据。这也将消除动态创建和删除表的需要。