Sql 更新联接视图而不获取非键保留错误

Sql 更新联接视图而不获取非键保留错误,sql,oracle,Sql,Oracle,我在Oracle 11g数据库中创建了一个视图,该数据库由两个连接表组成,如下所示: CREATE FORCE VIEW my_dataview ( key1, key2, column_from_table1, column_from_table2 ) AS SELECT key1, key2, column_from_table1, column_from_table2 FROM table1

我在Oracle 11g数据库中创建了一个视图,该数据库由两个连接表组成,如下所示:

CREATE FORCE VIEW my_dataview
(
   key1,
   key2,
   column_from_table1,
   column_from_table2
)
AS
   SELECT key1,
          key2,
          column_from_table1,
          column_from_table2
     FROM table1
          NATURAL LEFT OUTER JOIN table2;
其中两个源表都有两个主键,分别名为
key1
key2
。数据聚合正确,但我无法直接从视图中更新表2中的任何列

如果我要执行以下更新

UPDATE my_dataview SET column_from_table2 = 'Hello, world' 
WHERE key1 = 1234
     AND key2 = 12;
它给出的错误是
ORA-01779无法修改映射到非键保留表的列
。它还突出显示表2中的
列。如果我执行相同的命令,但从表1中设置
column\u,它就会工作。我认为这可能是因为table1是联接中所需的表

我首先想到的可能是,因为我加入了主键,并且视图中只有一个结果列,这可以解释我的问题。但是,即使将单独的
table2.key1
table2.key2
列添加到视图中,除了不必要地复制数据之外,也没有任何改变

我知道使用替代触发器更新视图是可能的,但我更愿意尽可能保持干净——这看起来更像是一种黑客行为,而不是一种解决方案

因此,总结一下我的问题,在连接视图上启用insert、update和delete的最佳行动计划是什么,这样就不会知道它是由两个单独的表组成的视图了

按要求提供的表格定义:

CREATE TABLE table1
(
   key1                 NUMBER(5)    NOT NULL,
   key2                 NUMBER(2)    NOT NULL,
   column_from_table_1  DATE  
);

CREATE UNIQUE INDEX pk_table1_index ON table1
(key1, key2);

ALTER TABLE table1 ADD (
   CONSTRAINT table1_Pkey
   PRIMARY KEY
   (key1, key2)
   USING INDEX pk_table1_index
   ENABLE VALIDATE);

CREATE TABLE table2
(
   key1                 NUMBER(5)    NOT NULL,
   key2                 NUMBER(2)    NOT NULL,
   column_from_table_2  VARCHAR2(20)
);

CREATE UNIQUE INDEX pk_table2_index ON table2
(key1, key2);

ALTER TABLE table2 ADD (
   CONSTRAINT table2_Pkey
   PRIMARY KEY
   (key1, key2)
   USING INDEX pk_table2_index
   ENABLE VALIDATE);

尝试将您的视图更改为:

CREATE FORCE VIEW my_dataview
(
   key1,
   key2,
   column_from_table1,
   column_from_table2
)
AS
   SELECT t1.key1,
          t1.key2,
          t1.column_from_table1,
          t2.column_from_table2
     FROM table1 t1
     LEFT OUTER JOIN table2 t2 on t1.key1 = t2.key1
                               and  t1.key2 = t2.key2;

在此视图中,您无法从表2中更新列,因为它不可更新。
要检查某些列是否可更新,请运行以下查询:

SELECT * FROM USER_UPDATABLE_COLUMNS
WHERE table_name = 'MY_DATAVIEW';

OWNER                          TABLE_NAME                     COLUMN_NAME                    UPDATABLE INSERTABLE DELETABLE
------------------------------ ------------------------------ ------------------------------ --------- ---------- ---------
TEST                           MY_DATAVIEW                    KEY1                           YES       YES        YES       
TEST                           MY_DATAVIEW                    KEY2                           YES       YES        YES       
TEST                           MY_DATAVIEW                    COLUMN_FROM_TABLE1             YES       YES        YES       
TEST                           MY_DATAVIEW                    COLUMN_FROM_TABLE2             NO        NO         NO   
为什么它不可更新?这是个大问题。
关于这个主题的文档中有整整一章:


查找“更新包含外部联接的视图”,这里有一个带有外部联接的视图示例,详细解释了此视图中哪些列可以更新,哪些列不能更新以及为什么要更新。

您说“数据正在正确聚合”,但我在您发布的视图中没有看到任何聚合。你能发布
表1
表2
的定义吗?什么是自然连接?@JustinCave抱歉,我的意思是聚合这个词的一般意义,它是按照我的预期连接两个表,而不是SQL相关的词:-)我用表定义更新了这个问题。事实上,两个表的列数都比这些表的列数多,但我觉得这个实证例子说明了这种情况。如果你愿意,我可以扩展。这个线程对你来说可能很有趣:@Parado将更新更新到了更新中@PrR3顶部的答案有些混乱,根据定义,联接中的列是唯一的,因此我不知道我的情况哪里出了问题。我可能最终不得不写一个程序来让它正常工作。谢谢你的链接!不幸的是,这不起作用。事实上,我试着用各种不同的方式来搞乱它,甚至包括做一个内部连接来踢和咯咯笑,在所有情况下,我都不能碰表2中的任何一列!我相信我可能必须更改我的数据模型才能工作。我想更新两个表中的列。我理解通过视图在一条语句中插入/删除两个表中的列的问题。但是我的插入发生在其他地方(在实际的表上),因此我只能选择/更新这个视图。