Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从oracle表中插入行,然后删除行_Sql_Oracle - Fatal编程技术网

Sql 从oracle表中插入行,然后删除行

Sql 从oracle表中插入行,然后删除行,sql,oracle,Sql,Oracle,我想看看是否有更好的方法来做到这一点。该语句获取6个月以上发生的所有行,并将它们放入存档表中。然后它获取两个表中存在的所有ID,并将它们从主表中删除。有什么想法吗 INSERT INTO ArchiveTable SELECT * FROM MainTable WHERE DateItHappened < (SYSDATE - 180); DELETE FROM MainTable a WHERE a.ID IN ( SELECT b.ID F

我想看看是否有更好的方法来做到这一点。该语句获取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)

在SQL Server中类似,但oracle没有内置的方法来执行此操作:

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

删除操作可以简化为:

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

我通常的方法是使用一个全局临时表来存储从源表移动到目标表的行的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很有用,因为它可以在提交时删除自己的行。

我认为您的方法很好。不起作用?下面的答案是。。。“最好把它放在那儿。”色雷斯比恩,你指的是我的答案吗?如果是,请提供详细信息。No@Joe,抱歉,第一个是关于sql server的。我在你回答之前写了我的评论。你的答案是好的。@ThrashBean好的-只是确定一下!代码可以工作,但我不是一个经验丰富的Oracle开发人员,所以我想确保我没有遗漏任何东西,因为这将在夜间流程中使用。我找不到任何关于Oracle版本的文档,也无法执行它,所以我猜没有。感谢您的输入!糟糕的是,这是一个很好的功能!这很有效。请您解释一下select语句的作用好吗?当然可以。SELECT只检查另一个表中是否存在指定的值。如果满足条件,即SELECT生成一行,则EXISTS被视为TRUE。请注意,SELECT中的1只是一个占位符,它只是为了使其成为有效的SQL语句。在这里查看更多信息:我想我以前不明白的是,它在“a”中每行调用一次select语句。到目前为止,我一直在处理测试数据,但是有没有人有与性能相关的数据,哪种方法更有效?我已经读到IN比EXISTS稍微慢一点,但是当我们删除4万到5万行时呢?一个相关的EXISTS通常被重写为半连接,就像IN子句一样。EXISTS对于NULL并没有那么棘手,这是我通常的选择。我希望我在表上有这样的权限,因为这样绝对更安全。不幸的是,安全检查只局限于基本的检查,很可能每天检查4万到5万次。第一天将是巨大的一天。我想没有分区选项吧?我简单地研究了一下,但无法创建和更改表,迫使我们的数据库安全团队在每个存档看起来都不太可能之前设置一个重新分区。我的另一个要求是现有代码工作不变,即MainTable必须引用包含最近6个月数据的表。对于分区,我相信引用的更改会让我束手无策。很难看出为表创建新分区会涉及到什么安全问题,特别是当您不需要ALTER table特权时——您可以将逻辑封装在过程中并调用它。听起来组织问题比组织中的技术问题更严重。