Oracle - 更新连接 - 非键保留表

Posted

技术标签:

【中文标题】Oracle - 更新连接 - 非键保留表【英文标题】:Oracle - update join - non key-preserved table 【发布时间】:2012-03-09 06:47:21 【问题描述】:

我正在尝试复制 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 对我没有违反唯一性感到满意?

【问题讨论】:

【参考方案1】:

您应该能够使用相关子查询来做到这一点

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 中的哪一行。

【讨论】:

这似乎解决了问题——感谢您的进一步解释。这是有道理的。【参考方案2】:

此语句失败并出现错误(ORA-01779 无法修改映射到非键保留表的列),因为它尝试修改基本 tbl1 表,而 tbl1 表在视图中未保留键。 因为(ID,A)虽然是dept表的key,但不是join的key。

【讨论】:

链接已不存在,能否请您更新或总结正确页面的信息? 它仍然存在,但现在是docs.oracle.com/cd/E11882_01/server.112/e25494/…。它指的是:Oracle 11.2 数据库管理员指南 -> § 24 管理视图、序列和同义词 -> §§ 保留键的表【参考方案3】:

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

【讨论】:

以上是关于Oracle - 更新连接 - 非键保留表的主要内容,如果未能解决你的问题,请参考以下文章

更新表不能修改映射到非键保留表的列

使用具有和 MIN 函数非键保留表错误进行更新

SQL 错误:ORA-01779:无法修改映射到非键保留表的列

ORA-01779 无法修改映射到非键保留表的列

Oracle:使用其他表中的值进行更新

具有多个非键列的继承连接策略