Sql 使用insert select复制记录,然后更新同一组记录中的属性
我有一个Oracle过程,我想在其中执行以下操作: 将记录从一个表复制到另一个表 更新原始记录以表明它们已被复制 目前,我使用FOR循环分别处理每条记录。这是可行的,但要做一些我认为可能更简单的事情需要很多代码 我想: 消除for循环,并通过插入将记录复制到。。。选择陈述 如果复制成功,则更新所有选定记录。 这看起来很简单,只需一个INSERT和一个UPDATE语句,其中包含相同的WHERE子句。但是,在执行这两条语句之间,可能会插入更多需要复制的记录。如果我使用相同的WHERE子句,我可能会将尚未实际处理的记录标记为已处理Sql 使用insert select复制记录,然后更新同一组记录中的属性,sql,database,oracle,plsql,Sql,Database,Oracle,Plsql,我有一个Oracle过程,我想在其中执行以下操作: 将记录从一个表复制到另一个表 更新原始记录以表明它们已被复制 目前,我使用FOR循环分别处理每条记录。这是可行的,但要做一些我认为可能更简单的事情需要很多代码 我想: 消除for循环,并通过插入将记录复制到。。。选择陈述 如果复制成功,则更新所有选定记录。 这看起来很简单,只需一个INSERT和一个UPDATE语句,其中包含相同的WHERE子句。但是,在执行这两条语句之间,可能会插入更多需要复制的记录。如果我使用相同的WHERE子句,我可能会将
是否有一种方法可以保存主键列表,以便在两个语句中使用或合并语句?或者你会建议我坚持使用FOR循环,一次处理一条记录吗?欢迎所有构造性输入。如果在事务中运行这两条语句,任何失败都将导致insert和update回滚
insert into tgt..
select * from src
where <condition>
and row_status <> 'copied'; --ignoring records after they have been copied once?
update src
set row_status = 'copied'
where <same_where_condition_as_before>
commit;
如果在读取源表后插入了新行,则可能需要再次运行该块,并在适当的情况下更改where条件。如果源表有很小的机会同时更新,Rajesh的回答应该可以很好地执行。如果源表经常更新,可序列化事务将经常失败 另一种方法是使用flashback查询来查看表中的时间点。as-of语法是查看表在最近的历史中的外观的一种方便方法
declare
v_current_scn number;
begin
v_current_scn := dbms_flashback.get_system_change_number;
insert into tgt..
select * from src
where <condition>
and row_status <> 'copied'; --ignoring records after they have been copied once?
update src
set row_status = 'copied'
where rowid in
(
select rowid
from src as of scn v_current_scn
where <same_where_condition_as_before>
);
end;
/
最好使用insert into..select语句,然后更新原始表中复制的记录。从隔离级别设置为可重复读取的事务开始工作?事务应该可以轻松处理此问题。For循环太过分了。@SylvainLeroux谢谢你提供的信息。看起来事务级隔离可以满足我的需要。您会推荐这种方法而不是使用set transaction read only吗?这取决于源表更新的频率。如果不常见,则接受Rajesh的答案,将其放入循环中,并在ORA-08177失败时重新运行它:无法序列化此事务的访问。如果它经常更新,那么我会使用闪回。另一种方法是使用返回语法,但这需要更多的代码来保存IDs.Jon-对于Oracle的读取一致性模型,OP的问题不需要序列化。如果我认为OP需要序列化当前事务,我会选择select for update。你怎么认为?