插入目标表,然后更新oracle中的源表字段

时间:2012-08-29 15:47:28

标签: oracle

在Oracle中,我有一个要求,我需要在Source中将记录插入Target,然后在目标更新后更新源的PROCESSED_DATE字段。

1种方法是使用游标并逐行循环来实现相同的目的。

还有其他方法以有效的方式做同样的事情吗?

4 个答案:

答案 0 :(得分:1)

不需要游标。假设您要传输那些尚未传输的行(由processed_date中的NULL值标识)。

insert into target_table (col1, col2, col3)
select col1, col2, col3
from source_table
where processed_date is null;

update source_table
   set processed_date = current_timestamp
where processed_date is null;

commit;

为避免更新在INSERT运行时或INSERT与更新之间插入的行,请以可序列化模式启动事务。

之前运行INSERT,使用以下语句启动事务:

set transaction isolation level SERIALIZABLE;  

有关详细信息,请参阅手册:

答案 1 :(得分:0)

触发器应该有效。目标表可以有一个触发器,在更新时,使用处理日期更新源表的列。

答案 2 :(得分:0)

我在这种情况下的首选解决方案是使用PL / SQL数组和批处理DML,例如:

DECLARE
  CURSOR c IS SELECT * FROM tSource;
  TYPE tarrt IS TABLE OF c%ROWTYPE INDEX BY BINARY_INTEGER;
  tarr tarrt;
BEGIN
  OPEN c;
  FETCH c BULK COLLECT INTO tarr;
  CLOSE c;
  FORALL i IN 1..tarr.COUNT
    INSERT INTO tTarget VALUES tarr(i);
  FORALL i IN 1..tarr.COUNT
    UPDATE tSource SET processed_date = SYSDATE
    WHERE tSource.id = tarr(i).id;
END;

以上代码仅作为示例,并对表的结构做出一些假设。

它首先查询源表,并且只会插入和更新这些记录 - 这意味着您无需担心其他会话在运行时同时在源表中插入更多记录。

也可以轻松更改为批量处理行(使用提取LIMIT子句和循环),而不是像我这里一样一次性处理。

答案 3 :(得分:0)

从其他人那里得到另一个答案。认为解决方案似乎比启用隔离级别更合理,因为我的所有新记录都将PROCESSED_DATE设置为null(在记录插入Target表时插入了30行) 此外,只能使用我的作业更新PROCESSED_DATE = NULL行。任何其他用户都无法在任何时间更新这些记录。

declare
date_stamp date;
begin
select sysdate
into date_stamp
from dual;

update source set processed_date = date_stamp
where procedded_date is null;
Insert into target 
select * from source
where processed_date = date_stamp;
commit;
end;

/

让我知道对此的任何进一步想法。非常感谢您对此的所有帮助。