3 votes

Mise à jour d'une vue commune sans erreur de non-préservation des clés

J'ai une vue créée dans une base de données Oracle 11g qui est composée de deux tables jointes comme suit :

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;

où les deux tables sources ont deux clés primaires nommées key1 y key2 . Les données sont agrégées correctement, mais je ne peux mettre à jour aucune des colonnes de table2 directement de la vue.

Si je devais exécuter la mise à jour suivante,

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

l'erreur qu'il donne est la suivante ORA-01779 cannot modify a column which maps to a non key-preserved table . Il met également l'accent sur column_from_table2 . Si j'exécute la même commande, mais en définissant column_from_table1 au lieu de cela, cela fonctionne. Je pense que cela est dû au fait que table1 est la table requise dans la jointure.

J'ai d'abord pensé que, puisque je fais une jointure sur les clés primaires et qu'il n'y a qu'une seule colonne résultante dans la vue, cela expliquerait mon problème. Mais même en ajoutant la colonne table2.key1 y table2.key2 à la vue n'a rien changé, si ce n'est de répliquer les données inutilement.

Je sais qu'il est possible de mettre à jour une vue en utilisant un trigger INSTEAD OF, mais je préférerais garder cela aussi propre que possible - cela ressemble plus à un hack qu'à une solution de toute façon.

Pour résumer ma question, quel est le meilleur plan d'action pour permettre l'insertion, la mise à jour et la suppression sur une vue de jointure de manière à ce qu'on ne puisse même pas dire qu'il s'agit d'une vue composée de deux tables distinctes ?

Définitions des tableaux comme demandé :

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

3voto

krokodilko Points 27099

Vous ne pouvez pas mettre à jour column_from_table2 dans cette vue, il n'est pas possible de le mettre à jour.
Pour vérifier si une colonne est actualisable ou non, exécutez la requête suivante :

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   

Pourquoi n'est-il pas actualisable ? C'est une grande question.
Un chapitre entier de la documentation est consacré à ce sujet :
http://docs.oracle.com/cd/B28359_01/server.111/b28310/views001.htm#i1006234
Dans la section "Mise à jour des vues impliquant des jointures externes", vous trouverez un exemple de vue avec jointure externe et une explication détaillée des colonnes de cette vue qui peuvent ou ne peuvent pas être mises à jour et pourquoi.

0voto

Parado Points 13763

Essayez de changer votre point de vue en ce sens :

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;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X