Oracle - 更新连接 - 非密钥保留表

时间:2012-02-17 21:17:28

标签: oracle

我正在尝试复制Ingres“从tbl2更新tbl1”命令,这在Oracle中并不完全存在。

所以我使用“update(select tbl1 join tbl2 ...)”命令。两个表都定义了主键,我我的连接是唯一标识行的,但我仍然得到“ORA-01779:无法修改映射到非密钥保留表的列”。

以下是适当的匿名表定义和我正在尝试执行的更新:

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确信我没有唯一性违规?

3 个答案:

答案 0 :(得分:23)

您应该可以使用相关子查询

来执行此操作
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无法保证只有一个tbl2.c值与单个tbl1.b值对应。如果tbl2tbl1中的任何特定行的tbl2中有多行,则相关更新将抛出一个错误,指示单行子查询返回多行。在这种情况下,您需要向子查询添加一些逻辑,以指定在{{1}}中使用哪一行。

答案 1 :(得分:1)

此语句失败并显示错误(ORA-01779无法修改映射到非密钥保留表的列),因为它尝试修改基本tbl1table,并且tbl1表未在视图中进行密钥保留。  因为虽然(ID,A)是dept表的一个键,但它不是连接的键。

答案 2 :(得分:0)

根据(http://www.orafaq.com/tuningguide/updateable%20view.html),您的视图似乎不是密钥保留的视图。实际上,你加入的不是主键,这似乎是不允许的。