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

时间:2011-02-24 22:54:57

标签: 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 个答案:

答案 0 :(得分: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;

答案 1 :(得分:3)

答案 2 :(得分:0)

在插入temp_table并更新原始文件后,可能会创建一个TRIGGER

答案 3 :(得分:0)

创建一个光标,保存insert中的值,然后循环更新表格。首先不需要创建临时表。

答案 4 :(得分: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;