【问题标题】:Insert then delete rows out of an oracle table从 oracle 表中插入然后删除行
【发布时间】:2014-02-11 18:27:22
【问题描述】:

我想看看是否有更好的方法来做到这一点。该语句将所有发生在 6 个月以上的行放入存档表中。然后它获取两个表中存在的所有 id 并将它们从主表中删除。有什么想法吗?

INSERT INTO ArchiveTable
    SELECT *
    FROM MainTable
    WHERE DateItHappened < (SYSDATE - 180);

DELETE FROM MainTable a
   WHERE a.ID IN (
   SELECT b.ID 
   FROM ArchiveTable b 
   JOIN MainTable a
     ON b.ID = 
        a.ID);

更新:

我继续执行下面 Joe 的建议,以使其成为最终代码。如果有人有任何需要更改的地方,请告诉我。

INSERT INTO ArchiveTable
    SELECT *
    FROM MainTable
    WHERE DateItHappened < (SYSDATE - 180);

DELETE FROM maintable a
    WHERE EXISTS (SELECT 1         
     FROM archivetable b
    WHERE a.id = b.id)

【问题讨论】:

  • 我认为你的方法很好。不工作?下面的答案......最好把它留在那里。
  • @ThrashBean 你指的是我的回答吗?如果有,请提供详细信息。
  • 没有@Joe,对不起,第一个,关于 sql server。我在你回答之前写了我的评论。你的回答很好。
  • @ThrashBean 好的 - 只是确保!
  • 代码可以运行,但我不是经验丰富的 Oracle 开发人员,所以我想确保我没有遗漏任何内容,因为这将在夜间进程中使用。

标签: sql oracle


【解决方案1】:

DELETE 可以简化:

DELETE FROM maintable a
 WHERE EXISTS (SELECT 1
                 FROM archivetable b
                WHERE a.id = b.id)

【讨论】:

  • 这行得通。您介意解释一下该 select 语句的作用吗?
  • 当然。 SELECT 只是检查另一个表中是否存在指定的值。如果满足条件(即 SELECT 生成一行),则认为 EXISTS 为 TRUE。请注意,SELECT 中的“1”只是一个占位符——它只是为了使它成为有效的 SQL 语句。在此处查看更多信息:stackoverflow.com/questions/5846882/…
  • 我想我以前不明白的是它在“a”中每行调用一次该 select 语句。到目前为止,我正在使用测试数据,但是是否有人拥有与哪种方法更有效的性能相关数据?我读过 IN 比 EXISTS 稍慢,但是当我们删除 40 到 5 万行时呢?
  • 关联的 EXISTS 通常被重写为半连接,就像 IN 子句一样。 EXISTS 对 NULLS 没有那么棘手,是我通常的选择。
【解决方案2】:

我通常的方法是使用全局临时表来存储我从源表移动到目标表的行的 rowid,然后使用该集合来执行删除。对于不稳定的初始数据集等问题,它可以 100% 安全。

insert all
  into archivetable (col1, col2 ...)
  values (col1, col2 ...)
  into maintable_deletes (delete_rowid)
  values (rowid)
select rowid, *
from   maintable;

delete from maintable
where  rowid in (select delete_rowid from maintable_deletes);

commit;

GTT 很有用,因为它可以在提交时删除自己的行。

【讨论】:

  • 我希望我在桌子上有这种权限,因为这绝对更安全。不幸的是,安全检查使我仅限于基础知识。
  • 每天最有可能在 40 到 5 万之间。第一天将是巨大的。
  • 我想没有分区选项?
  • 我简单地调查了一下,但无法创建和更改表,迫使我们的数据库安全团队在每个存档似乎不太可能之前设置一个重新分区。我的另一个要求是现有代码工作不变,即 MainTable 必须引用包含最近 6 个月数据的表。有了分区,我相信参考的变化让我束手无策。
  • 很难看出为表创建新分区可能涉及哪些安全问题,尤其是当您不需要 ALTER TABLE 权限时——您可以将逻辑封装在一个过程中并调用它.听起来组织问题比您组织中的技术问题更大。
【解决方案3】:

在 SQL Server 中会这样,但 oracle 没有内置方法来执行此操作:

delete m
output deleted.ColumnA, deleted.ColumnB
into ArchiveTable
from 
MainTable m
where DateItHappened < (SYSDATE - 180);

【讨论】:

  • 我找不到任何关于 oracle 版本的文档,也无法执行,所以我猜不是。感谢您的意见!
  • 糟糕,这是一个不错的功能!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-18
  • 1970-01-01
相关资源
最近更新 更多