我有一个包含3个属性的表A:
ID(PK),UNIT(varchar2),VALUE(数字)
我还有另一个表B通过外键引用表A的PK。
ID,FK_TABLE_A
表B中已有记录,但属性 FK_TABLE_A 的值为空。我想要的是,通过将新数据插入表A并将新创建的主键作为外键引用到表中,表B中的所有记录都获得自己的唯一引用到表A的PK乙
到目前为止我做了什么: 我现在可以通过以下SQL插入新数据:
INSERT INTO TABLE_A(ID, UNIT, VALUE) VALUES (TABKE_A_SEQ.nextval, 'SOME_STRING', 1);
我可以手动更新参考表B
UPDATE TABLE_B SET FK_TABLE_A = 123; //123 is just an example PK
但我不希望每次都在DB中查询每条记录,而是希望在一个查询中以某种方式将第一个insert
与第二个update
结合起来。
因此,更新将表A中新创建的PK作为参考。
这可能吗?
我使用Oracle作为数据库。
答案 0 :(得分:0)
在您的会话中使用序列后,您可以use the currval
pseudocolumn通过上次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;
(虽然你没有过滤器,但是会将表B中的所有行更新为相同的FK值;可能你正在做一些更复杂的事情来识别相关的行...)< / p>
如果你想要一对一的关系并且不关心哪一行获得哪个PK值,并且你可以使约束可以推迟,你可以反过来接近它;使用序列更新所有表B行,然后使用这些行创建表A行。
使用快速演示表:
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;
然后,在单个事务中,更新所有行并执行单个插入:
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;
约束必须是可延迟的,以允许更新首先发生;否则你会得到ORA-02291。
如果单位/值来自table_a
,您可以在查询中包含这些内容而不是使用固定文字。很难说出你真正需要的是什么,你说它们甚至可以留空。
现在你有:
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
答案 1 :(得分:0)
使用触发器(在TABLE_A上)在TABLE_B中创建行。
例如(假设您使用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;