Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating a Join View without getting Non Key-Preserved Error

I have a view created in an Oracle 11g database that is comprised of two joined tables like so:

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;

where both source tables have two primary keys named key1 and key2. The data is being aggregated correctly, but I cannot update any of the columns from table2 directly from the view.

If I were to execute the following update,

UPDATE my_dataview SET column_from_table2 = 'Hello, world' 
WHERE key1 = 1234
     AND key2 = 12;

the error it gives is ORA-01779 cannot modify a column which maps to a non key-preserved table. It also highlights column_from_table2. If I were to execute the same command, but set column_from_table1 instead, it works. I think that may be because table1 is the required table in the join.

I first thought that maybe since I'm joining on the primary keys, and there is only one resulting column in the view, that would explain my problem. But even adding in the separate table2.key1 and table2.key2 columns to the view did not change anything, except replicating data unnecessarily.

I know it is possible to update a view using an INSTEAD OF trigger, but I would prefer to keep this as clean I can -- that seems more like a hack than a solution anyways.

So to summarize my question, what is the best plan of action for enabling insert, update, and delete on a join view so as to not even be able to tell it is a view comprised of two separate tables at all?

Table definitions as requested:

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);
like image 364
helrich Avatar asked Nov 19 '25 16:11

helrich


1 Answers

You cannot update column_from_table2 in this view, it's not updatable.
To check whether some column is updatable or not, run this query:

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   

Why it is not updatable ? It's a big question.
There is a whole chapter in documentation on this topic:
http://docs.oracle.com/cd/B28359_01/server.111/b28310/views001.htm#i1006234
find "Updating Views That Involve Outer Joins", there is an example of a view with outer join and detailed explanation which columns in this view can and cannot be updated and why.

like image 152
krokodilko Avatar answered Nov 22 '25 06:11

krokodilko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!