Oracle - 更新连接 - 非键保留表
我正在尝试复制 Ingres从 tbl2 更新 tbl1"命令,该命令在 Oracle 中并不完全存在.
I'm trying to replicate an Ingres "update tbl1 from tbl2" command, which doesn't exactly exist in Oracle.
所以我使用更新(选择 tbl1 加入 tbl2...)"命令.两个表都定义了主键,我认为我的连接是唯一标识行,但我仍然收到ORA-01779:无法修改映射到非键保留表的列".
So I use "update (select tbl1 join tbl2...)" command. Both tables have primary keys defined and I thought that my join was uniquely identifying rows, but I'm still getting "ORA-01779: cannot modify a column which maps to a non key-preserved table".
以下是适当的匿名表定义和我尝试执行的更新:
Here are suitably anonymized table definitions and the update I'm trying to execute:
CREATE TABLE tbl1
(
ID decimal(11) NOT NULL,
A varchar2(3) NOT NULL,
B float(7),
CONSTRAINT tbl1_pk PRIMARY KEY (ID,A)
)
;
CREATE TABLE tbl2
(
ID decimal(11) NOT NULL,
A varchar2(3) NOT NULL,
B float(15),
C float(15),
D char(1) NOT NULL,
CONSTRAINT tbl2_PK PRIMARY KEY (ID,A,D)
)
;
UPDATE
(select tbl1.b, tbl2.c
from tbl1 inner join tbl2
on tbl1.id=tbl2.id
and tbl1.a=tbl2.a
and tbl1.b=tbl2.b
and tbl1.a='foo'
and tbl2.D='a')
set b=c;
如何定义我的选择,以便 Oracle 对我没有违反唯一性感到满意?
How can I define my select such that Oracle will be satisfied that I have no uniqueness violations?
推荐答案
您应该能够使用相关子查询来做到这一点
You should be able to do this with a correlated subquery
UPDATE tbl1 t1
SET t1.b = (SELECT c
FROM tbl2 t2
WHERE t1.id = t2.id
AND t1.a = t2.a
AND t1.b = t2.b
AND t2.d = 'a')
WHERE t1.a = 'foo'
AND EXISTS( SELECT 1
FROM tbl2 t2
WHERE t1.id = t2.id
AND t1.a = t2.a
AND t1.b = t2.b
AND t2.d = 'a')
您编写的 UPDATE
的问题在于 Oracle 无法保证有 1 个 tbl2.c
值对应于单个 tbl1.b
值.如果tbl2
中有多个行用于tbl1
中的任何特定行,则相关更新将抛出一个错误,表明单行子查询返回了多行.在这种情况下,您需要向子查询添加一些逻辑,以指定在这种情况下使用 tbl2
中的哪一行.
The problem with the UPDATE
that you've written is that Oracle cannot guarantee that there is exactly 1 tbl2.c
value that corresponds to a single tbl1.b
value. If there are multiple rows in tbl2
for any particular row in tbl1
, the correlated update is going to throw an error indicating that a single-row subquery returned multiple rows. In that case, you'd need to add some logic to the subquery to specify which row from tbl2
to use in that case.
相关文章