插入到一个临时表,并在一个SQL查询中更新另一个表(Oracle)的

问题描述:

这里就是我想要做的事:插入到一个临时表,并在一个SQL查询中更新另一个表(Oracle)的

1)插入到一个临时表从原始表中的一些值

INSERT INTO temp_table SELECT id FROM original WHERE status='t' 

2)更新原来的表

UPDATE original SET valid='t' WHERE status='t' 

3)基于两个表之间的联接选择

SELECT * FROM original WHERE temp_table.id = original.id 

有没有办法将步骤1和步骤2组合?

您可以通过在PL/SQL中执行更新并使用RETURNING子句将更新后的ID获取到PL/SQL表中来组合步骤。

编辑:

如果您仍然需要做最终的查询,你仍然可以使用这个方法来插入temp_table;尽管取决于最后一次查询的内容,但可能有其他方法来实现您想要的内容。举例说明:

DECLARE 
    id_table_t IS TABLE OF original.id%TYPE INDEX BY PLS_INTEGER; 
    id_table id_table_t; 
BEGIN 
    UPDATE original SET valid='t' WHERE status='t' 
    RETURNING id INTO id_table; 
    FORALL i IN 1..id_table.COUNT 
    INSERT INTO temp_table 
    VALUES (id_table(i)); 
END; 
/

SELECT * FROM original WHERE temp_table.id = original.id; 

不,DML语句不能混合使用。

有一个MERGE statement, but it's only for operations on a single table

插入到temp_table后也许创建一个TRIGGER至极火灾和更新原始

+0

这是假设OP希望这一直发生 – 2011-02-24 22:59:40

创建一个游标通过游标更新表保存从插入值,然后循环。无需首先创建临时表。

您可以使用MERGE语句和DML错误日志记录组合第1步和第2步。选择两倍的行数,更新其中的一半,并强制另一半失败,然后插入到可用作临时表的错误日志中。

下面的解决方案假定您对ID有主键约束,但还有其他方法可以强制失败。

虽然我觉得这很酷,但我建议你不要使用它。它看起来很奇怪,有一些奇怪的问题(对TEMP_TABLE的插入是自动提交的),可能非常慢。

--Create ORIGINAL table for testing. 
--Primary key will be intentionally violated later. 
create table original (id number, status varchar2(10), valid varchar2(10) 
    ,primary key (id)); 

--Create TEMP_TABLE as error log. There will be some extra columns generated. 
begin 
    dbms_errlog.create_error_log(dml_table_name => 'ORIGINAL' 
    ,err_log_table_name => 'TEMP_TABLE'); 
end; 
/

--Test data 
insert into original values(1, 't', null); 
insert into original values(2, 't', null); 
insert into original values(3, 's', null); 
commit; 


--Update rows in ORIGINAL and also insert those updated rows to TEMP_TABLE. 
merge into original original1 
using 
(
    --Duplicate the rows. Only choose rows with the relevant status. 
    select id, status, valid, rownumber 
    from original 
    cross join 
    (select 1 rownumber from dual union all select 2 rownumber from dual) 
    where status = 't' 
) original2 
    on (original1.id = original2.id and original2.rownumber = 1) 
--Only math half the rows, those with rownumber = 1. 
when matched then update set valid = 't' 
--The other half will be inserted. Inserting ID causes a PK error and will 
--insert the data into the error table, TEMP_TABLE. 
when not matched then insert(original1.id, original1.status, original1.valid) 
    values(original2.id, original2.status, original2.valid) 
log errors into temp_table reject limit 999999999; 


--Expected: ORIGINAL rows 1 and 2 have VALID = 't'. 
--TEMP_TABLE has the two original values for ID 1 and 2. 
select * from original; 
select * from temp_table;