Sql 在Oracle中使用单个语句在表之间移动行

Sql 在Oracle中使用单个语句在表之间移动行,sql,oracle,Sql,Oracle,由于愚蠢的遗留系统限制,我尝试使用一条语句编写以下查询: insert into dbo.mytable_archive select * from dbo.mytable where date < trunc(sysdate) - 14; delete from dbo.mytable where date < trunc(sysdate) - 14; exec move_to_arch(); 插入到dbo.mytable\u存档中 选择* 从db

由于愚蠢的遗留系统限制,我尝试使用一条语句编写以下查询:

insert into dbo.mytable_archive 
  select * 
    from dbo.mytable 
   where date < trunc(sysdate) - 14;

delete from dbo.mytable 
 where date < trunc(sysdate) - 14;
exec move_to_arch();
插入到dbo.mytable\u存档中
选择*
从dbo.mytable
其中日期
使用Google的强大功能,我发现在SQLServer中使用
RETURNING
子句I Postgres或
OUTPUT
子句的许多其他数据库中,这似乎都是可能的,但我无法为Oracle(V12)找到等效的解决方案


有什么解决办法吗?

您仍然需要两条语句,一条用于
insert
,另一条用于
delete
<代码>返回
将帮助您保存示例id。
Oracle提供
返回到
keyworks

您的限制是什么?如果要调用单个语句,可以:

create or replace procedure move_to_arch as
begin
insert into dbo.mytable_archive 
  select * 
    from dbo.mytable 
   where date < trunc(sysdate) - 14;

delete from dbo.mytable 
 where date < trunc(sysdate) - 14;
commit;
end;
/

如果您的声明在午夜前后运行,并且可能需要超过1秒,您最好执行以下操作:

create or replace procedure move_to_arch as
   theDate DATE := trunc(sysdate) - 14;
begin
insert into dbo.mytable_archive 
  select * 
    from dbo.mytable 
   where date < theDate ;

delete from dbo.mytable 
 where date < theDate ;
commit;
end;
/
创建或替换过程移动到
日期:=trunc(sysdate)-14;
开始
插入到dbo.mytable_存档中
选择*
从dbo.mytable
其中日期<日期;
从dbo.mytable中删除
其中日期<日期;
犯罪
结束;
/

使用内存表缓存delete语句的结果。这样可以避免从磁盘读取记录两次

create or replace procedure move_to_arch as
  TYPE mytableType IS table OF dbo.mytable%ROWTYPE;
  t mytableType;
begin
  delete from dbo.mytable 
  where date < trunc(sysdate) - 14
  RETURNING col1,col2 BULK COLLECT INTO t;

  FORALL J IN t.FIRST..t.LAST
    INSERT INTO dbo.mytable_archive VALUES t(J);
end;
/
创建或替换过程移动到
类型mytableType是dbo的表。mytable%ROWTYPE;
t表型;
开始
从dbo.mytable中删除
其中日期
在Oracle中,用一条语句无法做到这一点。除非我们这里有魔术师。我想我错了,因为那样会很方便。顺便说一句,同样的问题已经被问到了,如果我理解的很好,你需要在第一个语句中返回,然后在第二个语句中使用第一个查询的结果;如果是这样的话,请看一看。这不是触发的最佳情况吗?每次删除某个内容时,请将其保存到存档表中?答案是否与我的答案完全相同?不,如果您在23:59:00运行过程,并且INSERT耗时超过1分钟,则delete将删除不同的数据,因为
trunc(sysdate)-14
返回不同的值。确定,你说得对,我应该把手术开始的日期定下来,而不是私下。谢谢。两次并行执行
move_to_arch
是否可能导致行最终双重插入存档表?其原因是
insert
中的subselect不带任何锁,因此两个事务都可以在subselect中看到相同的行集。是的,可以将数据双重插入mytable_存档。这会是个问题吗?一个可能的解决方案是一个分区表(每天一个分区),在其中运行“exchange分区”。@NicholasKrasnov是的,你是对的。我现在将编辑答案,不确定Postgres的情况,但是MS SQL的
输出
可以用于此-您可以执行
删除
,通过
输出
将删除的行作为结果集输出,并使用
插入
插入该结果集。