插入到一个临时表,并在一个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;
答
创建一个游标通过游标更新表保存从插入值,然后循环。无需首先创建临时表。
答
您可以使用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;
这是假设OP希望这一直发生 – 2011-02-24 22:59:40