【问题标题】:Drop all table with name like TABLE_REPO_%_<SYSDATE-2>, TABLE_REPO_%_<SYSDATE-3>, TABLE_REPO_%_<SYSDATE-4> and so on.删除名称为 TABLE_REPO_%_<SYSDATE-2>、TABLE_REPO_%_<SYSDATE-3>、TABLE_REPO_%_<SYSDATE-4> 等的所有表。
【发布时间】:2017-03-28 21:26:01
【问题描述】:

作为脚本的一部分,我创建表以每天备份数据并创建名称为 sysdate -1 的表。但我不想用这样的表加载我的数据库,所以一旦它们 2 天大,我也会删除这些表。这有助于我将数据保留 1 天。表名将如下所示: TABLE_REPO_CR_SYSDATE-1 TABLE_REPO_DRP_SYSDATE-1 TABLE_REPO_UPD_SYSDATE-1

所以假设今天是 3 月 28 日,我运行我的脚本,备份表将被创建为:

TABLE_REPO_CR_20170327
TABLE_REPO_DRP_20170327
TABLE_REPO_UPD_20170327 

明天(3 月 29 日)当我运行工作时,今天和明天的表格将是: TABLE_REPO_CR_20170328 TABLE_REPO_DRP_20170328 TABLE_REPO_UPD_20170328 在 3 月 30 日,当我运行脚本时,将会有: TABLE_REPO_CR_20170329 TABLE_REPO_DRP_20170329 TABLE_REPO_UPD_20170329

现在我的问题是我想删除所有名称为 TABLE_REPO_%_(SYSDATE-2 及以下) 的表,例如 TABLE_REPO_%_(sysdate-1) 以外的所有表

个人可以删除,但是如何全部删除??

 BEGIN

  FOR t in (SELECT tname FROM tab  WHERE tname like 'TABLE_REPO_%' || to_char(sysdate-2,'yyyymmdd'))
  LOOP
    EXECUTE immediate 'drop table ' || t.tname;
  END LOOP;
  EXCEPTION  WHEN OTHERS THEN
        IF SQLCODE != -942 THEN
             RAISE;
        END IF;
  END;
  /
 COMMIT;

谢谢!

【问题讨论】:

  • sysdate, EXECUTE immediate ----- 我认为你使用的是 Oracle
  • 你发帖的方式有什么问题?遍历表并执行 DROP 应该可以工作,为什么需要不同的解决方案?
  • 也许你的意思是如何一次做 -2、-3、-4 等 - 你可以用另一个循环来做;或更简单地更改您的光标查询以排除您要保留的日期。但这不是一次性清理吗?如果您每天都运行此程序,您将只有一天的价值可以正常清除?

标签: sql oracle


【解决方案1】:

您可以更改光标查询以查找所有匹配的表除了今天或昨天的:

FOR t in (
  SELECT table_name as tname FROM user_tables
  WHERE table_name like 'TABLE_REPO_%'
  AND table_name NOT like 'TABLE_REPO_%' || to_char(sysdate-1,'yyyymmdd')
  AND table_name NOT like 'TABLE_REPO_%' || to_char(sysdate,'yyyymmdd')
)
LOOP

如果您的邮件表也以 TABLE_REPO_ 开头,您也可以明确排除它们:

  AND table_name NOT IN ('TABLE_REPO_CR', ...)

或查找以八位数字结尾的任何数字(这是一个始终是日期的假设......):

  WHERE regexp_like(table_name, '^TABLE_REPO_.*\d{8}$')

(我也切换到寻找user_tables.table_name 而不是tab.tname,因为它更常用。在文档中它说“包含TAB 是为了兼容性。Oracle 建议您不要使用此视图。 ")

快速演示,展示可以找到(和丢弃)的内容:

with user_tables (table_name) as (
  select 'TABLE_REPO_CR' from dual
  union all select 'TABLE_REPO_CR_' || to_char(sysdate - 3, 'yyyymmdd') from dual
  union all select 'TABLE_REPO_CR_' || to_char(sysdate - 2, 'yyyymmdd') from dual
  union all select 'TABLE_REPO_CR_' || to_char(sysdate - 1, 'yyyymmdd') from dual
  union all select 'TABLE_REPO_CR_' || to_char(sysdate, 'yyyymmdd') from dual
)
SELECT table_name as tname FROM user_tables
WHERE regexp_like(table_name, '^TABLE_REPO_.*\d{8}$')
AND table_name NOT like 'TABLE_REPO_%' || to_char(sysdate-1,'yyyymmdd')
AND table_name NOT like 'TABLE_REPO_%' || to_char(sysdate,'yyyymmdd');

TNAME                 
----------------------
TABLE_REPO_CR_20170326
TABLE_REPO_CR_20170327

顺便说一句,您可能还想检查今天和/或昨天的表确实存在,以防出现问题或延迟或任何可能导致您无法备份的情况。

【讨论】:

  • 这看起来不错,但这也会删除我的主表,因为它们的名称如 TABLE_REPO_CR、.TABLE_REPO_UPD 等。我想保留它们并删除所有超过 2 天的表。
  • @Mishti - 是的,如果它们匹配该模式;对不起,我没有从问题中得到这个。我添加了两个选项来排除它们。 (显示了审查和测试来自互联网的代码而不是盲目地运行它的重要性……干得好*8-)
  • 非常感谢你hhhhhhhh :) 这对我来说很好!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-19
  • 2021-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多