简体   繁体   English

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

[英]Insert into a temporary table and update another table in one SQL query (Oracle)

Here's what I'm trying to do: 这是我想做的事情:

1) Insert into a temp table some values from an original table 1)将临时表中的某些值插入到临时表中

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

2) Update the original table 2)更新原始表

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

3) Select based on a join between the two tables 3)根据两个表之间的联接进行选择

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

Is there a way to combine steps 1 and 2? 有没有办法结合步骤1和2?

You can combine the steps by doing the update in PL/SQL and using the RETURNING clause to get the updated ids into a PL/SQL table. 您可以通过在PL / SQL中进行更新并使用RETURNING子句将更新后的ID放入PL / SQL表中来组合这些步骤。

EDIT: 编辑:

If you still need to do the final query, you can still use this method to insert into the temp_table; 如果仍然需要执行最终查询,则仍然可以使用此方法插入temp_table中。 although depending on what that last query is for, there may be other ways of achieving what you want. 尽管根据最后一个查询的目的,可能还有其他方式可以实现您想要的。 To illustrate: 为了显示:

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;

No, DML statements can not be mixed. 不,DML语句不能混用。

There's a MERGE statement, but it's only for operations on a single table . 有一个MERGE语句,但这仅用于单个表上的操作

也许在插入temp_table之后创建触发触发的TRIGGER并更新原始

Create a cursor holding the values from insert and then loop through the cursor updating the table. 创建一个游标,其中包含来自插入的值,然后循环游标以更新表。 No need to create temp table in the first place. 无需首先创建临时表。

You can combine steps 1 and 2 using a MERGE statement and DML error logging. 您可以使用MERGE语句和DML错误日志记录来组合步骤1和2。 Select twice as many rows, update half of them, and force the other half to fail and then be inserted into an error log that you can use as your temporary table. 选择两倍的行,更新其中一半,然后强制另一半失败,然后将其插入错误日志中,以用作临时表。

The solution below assumes that you have a primary key constraint on ID, but there are other ways you could force a failure. 下面的解决方案假定您对ID具有主键约束,但是还有其他方法可以强制失败。

Although I think this is pretty cool, I would recommend you not use it. 尽管我认为这很酷,但我还是建议您不要使用它。 It looks very weird, has some strange issues (the inserts into TEMP_TABLE are auto-committed), and is probably very slow. 看起来很奇怪,有一些奇怪的问题(自动提交到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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM