使用insert select复制记录,然后在同一组记录中更新属性

时间:2014-12-22 18:53:47

标签: sql database oracle plsql

我有一个Oracle程序,我想在其中执行以下操作:

  1. 将记录从一个表复制到另一个表
  2. 更新原始记录以表明它们已被复制
  3. 目前,我使用FOR循环分别处理每条记录。这是有效的,但是我认为可以更简单的做很多代码。

    我想:

    1. 消除for循环并使用INSERT INTO ... SELECT ...语句
    2. 复制记录
    3. 如果复制成功,请更新所有选定的记录。
    4. 这看似简单,只有一个INSERT和一个具有相同WHERE子句的UPDATE语句。但是,在执行两个语句之间的时间内,可能会插入需要复制的更多记录。如果我使用相同的WHERE子句,我可以将记录标记为尚未实际处理的已处理。

      有没有办法可以保存主键列表以便在两个语句中使用或合并语句?或者你会建议我坚持使用FOR循环并一次处理一个记录?欢迎所有建设性意见。

2 个答案:

答案 0 :(得分:3)

如果您运行两个语句 within a transaction ,任何失败都会导致回滚和更新。

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条件。

答案 1 :(得分:0)

如果源表同时更新的可能性很小,Rajesh的答案应该会很好。如果源表经常更新,则可序列化事务将经常失败。

另一种方法是使用闪回查询来获取表的时间点。 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;
/