3

我在 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;

其中两个源表都有两个名为key1and的主键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.key1table2.key2列也没有改变任何东西,除了不必要地复制数据。

我知道可以使用 INSTEAD OF 触发器来更新视图,但我更愿意尽可能保持清洁——这似乎更像是一种 hack,而不是一种解决方案。

所以总结一下我的问题,在连接视图上启用插入、更新和删除的最佳行动计划是什么,以至于根本无法判断它是由两个单独的表组成的视图?

根据要求的表定义:

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);
4

2 回答 2

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
找到“更新涉及外部连接的视图”,有一个例子带有外部连接的视图的详细说明,该视图中的哪些列可以更新,哪些列不能更新,以及为什么。

于 2013-09-05T20:16:36.223 回答
0

Try to change your view to this:

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;
于 2013-09-05T20:04:31.263 回答