我有一个在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
的主键。数据正在正确汇总,但我无法直接从视图更新table2
中的任何列。
如果我要执行以下更新,
UPDATE my_dataview SET column_from_table2 = 'Hello, world'
WHERE key1 = 1234
AND key2 = 12;
它给出的错误是ORA-01779 cannot modify a column which maps to a non key-preserved table
。它还突出显示column_from_table2
。如果我要执行相同的命令,而是设置column_from_table1
,那么它可以工作。我想这可能是因为table1是连接中必需的表。
我首先想到的可能是因为我正在加入主键,并且视图中只有一个结果列,这可以解释我的问题。但即使在视图中添加单独的table2.key1
和table2.key2
列,也不会改变任何内容,除非不必要地复制数据。
我知道可以使用INSTEAD OF触发器来更新视图,但我更愿意保持这种清洁 - 无论如何,这似乎更像是一个黑客而不是解决方案。
总结一下我的问题,在连接视图上启用插入,更新和删除的最佳操作方案是什么,以便甚至无法告诉它是一个由两个独立的表组成的视图?< / p>
所要求的表定义:
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);
答案 0 :(得分:3)
您无法在此视图中更新column_from_table2
,它无法更新
要检查某个列是否可更新,请运行以下查询:
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
为什么它不可更新?这是一个很大的问题
关于这个主题的文档有一整章:
http://docs.oracle.com/cd/B28359_01/server.111/b28310/views001.htm#i1006234
找到“更新涉及外部联接的视图”,有一个带有外部联接的视图示例和详细解释,该视图中的哪些列可以更新,也无法更新。
答案 1 :(得分:0)
尝试将您的观点更改为:
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;