2011-02-24 95 views
1

這裏就是我想要做的事:插入到一個臨時表,並在一個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組合?

回答

5

您可以通過在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; 
0

插入到temp_table後也許創建一個TRIGGER至極火災和更新原始

+0

這是假設OP希望這一直髮生 – 2011-02-24 22:59:40

0

創建一個遊標通過遊標更新表保存從插入值,然後循環。無需首先創建臨時表。

0

您可以使用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; 
相關問題