简体   繁体   English

在表中插入数据,在一个查询中用FK更新其他表

[英]Insert data in table, update other table with FK in one query

I have one Table A with 3 attributes: 我有一个具有3个属性的表A:

ID (PK), UNIT(varchar2), VALUE(number) ID(PK),UNIT(varchar2),VALUE(数字)

And I have another Table B that references the PK of Table A via a foreign key. 我还有另一个表B,它通过外键引用表A的PK。

ID, FK_TABLE_A ID,FK_TABLE_A

In Table B are already records, but the value of the attribute FK_TABLE_A is null. 表B中已经有记录,但是属性FK_TABLE_A的值为空。 What I want is, that all records in Table B get an own unique reference to Table A's PK by inserting new data into Table A and referencing the newly created primary key as foreign key into Table B. 我想要的是,通过向表A中插入新数据并将新创建的主键作为外键引用到表B中,表B中的所有记录都获得了对表A PK 的唯一引用

What I have done so far: I can now insert new data via following SQL: 到目前为止,我已经完成了什么:现在可以通过以下SQL插入新数据:

INSERT INTO TABLE_A(ID, UNIT, VALUE) VALUES (TABKE_A_SEQ.nextval, 'SOME_STRING', 1);

And I can update by hand the refernce to Table B 我可以手动更新对表B的引用

UPDATE TABLE_B SET FK_TABLE_A = 123; //123 is just an example PK

But I do not want to query for each record everytime the DB, but instead want to combine somehow the first insert with the second update in one query. 但是我不想每次DB都查询每个记录,而是想以某种方式将第一个insert与第二个update结合在一起。 So that the update takes the newly created PK in Table A as reference. 这样更新就可以参考表A中新创建的PK。

Is this possible? 这可能吗?

I am using Oracle as DB. 我正在使用Oracle作为数据库。

Once you've used the sequence in your session, you can use the currval pseudocolumn to get the last sequence value issued in your session, by the last nextval call: 在会话中使用了序列后,可以使用currval伪列通过上一个nextval调用来获取会话中发布的最后一个序列值:

INSERT INTO TABLE_A(ID, UNIT, VALUE) VALUES (TABKE_A_SEQ.nextval, 'SOME_STRING', 1);
UPDATE TABLE_B SET FK_TABLE_A = TABKE_A_SEQ.currval;

(Although as you don't have a filter, that will update all rows in table B to the same FK value; presumably you're doing something more complicated to identify the relevant rows...) (尽管您没有过滤器,但会将表B中的所有行更新为相同的FK值;想必您正在做一些复杂的事情来标识相关行...)


If you want a one-to-one relationship and don't care which row gets which PK value, and you can make the constraint deferrable, you could approach it the other way around; 如果您想要一对一的关系,而不关心哪一行获得哪个PK值,并且可以使约束可延期,则可以采用其他方法。 update all the table B rows using the sequence, then create the table A rows using those. 使用序列更新表B的所有行,然后使用这些表创建表A的行。

With a quick demo table: 使用快速演示表:

create table table_a (id number primary key, unit varchar2(20), value number);
create table table_b (id number,
  fk_table_a number references table_a(id) initially deferred deferrable);
create sequence table_a_seq;
create sequence table_b_seq start with 50;

insert into table_b (id) select table_b_seq.nextval from dual connect by level <= 5;

Then, in a single transaction, update all the rows and do a single insert: 然后,在单个事务中,更新所有行并进行一次插入:

update table_b set fk_table_a = table_a_seq.nextval;

insert into table_a (id, unit, value)
select fk_table_a, 'SOME_STRING', 1
from table_b;

The constraint has to be deferrable to allow the update to happen first; 约束必须是可延迟的,以允许更新首先发生; otherwise you'd get ORA-02291. 否则,您会得到ORA-02291。

If the unit/value are coming from table_a you can include those in the query instead of using fixed literals. 如果单位/值来自table_a ,则可以在查询中包括这些单位/值,而不必使用固定文字。 It's hard to tell what you actually need for those, and you said they could even be left null. 很难说出您实际需要的东西,并且您说它们甚至可能为空。

Now you have: 现在您有了:

select * from table_a;

        ID UNIT                      VALUE
---------- -------------------- ----------
         1 SOME_STRING                   1
         2 SOME_STRING                   1
         3 SOME_STRING                   1
         4 SOME_STRING                   1
         5 SOME_STRING                   1

select * from table_b;

        ID FK_TABLE_A
---------- ----------
        50          1
        51          2
        52          3
        53          4
        54          5

Use a trigger (on TABLE_A) to create the row in TABLE_B. 使用触发器(在TABLE_A上)在TABLE_B中创建行。

For example (assuming you are using a SEQUENCE to generate the PK) 例如(假设您正在使用SEQUENCE生成PK)

 CREATE OR REPLACE TRIGGER TR_TABLE_A_AI
 AFTER INSERT
 ON TABLE_A
 FOR EACH ROW
BEGIN
  INSERT INTO TABLE_B VALUES (SEQ_TABLE_B.NEXTVAL, :NEW.ID);
END;

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

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