ORA-30926: impossible d'obtenir un ensemble stable de lignes dans les tables source

129

Je reçois

ORA-30926: impossible d'obtenir un ensemble stable de lignes dans les tables source

dans la requête suivante:

  MERGE INTO table_1 a
      USING 
      (SELECT a.ROWID row_id, 'Y'
              FROM table_1 a ,table_2 b ,table_3 c
              WHERE a.mbr = c.mbr
              AND b.head = c.head
              AND b.type_of_action <> '6') src
              ON ( a.ROWID = src.row_id )
  WHEN MATCHED THEN UPDATE SET in_correct = 'Y';

Je l'ai exécuté table_1avec des données et j'ai également exécuté la requête interne ( src) qui contient également des données.

Pourquoi cette erreur surviendrait-elle et comment peut-elle être résolue?

Omniprésent
la source

Réponses:

202

Cela est généralement dû à des doublons dans la requête spécifiée dans la clause USING. Cela signifie probablement que TABLE_A est une table parent et que le même ROWID est renvoyé plusieurs fois.

Vous pouvez rapidement résoudre le problème en utilisant un DISTINCT dans votre requête (en fait, si «Y» est une valeur constante, vous n'avez même pas besoin de la mettre dans la requête).

En supposant que votre requête est correcte (ne connaissez pas vos tables), vous pouvez faire quelque chose comme ceci:

  MERGE INTO table_1 a
      USING 
      (SELECT distinct ta.ROWID row_id
              FROM table_1 a ,table_2 b ,table_3 c
              WHERE a.mbr = c.mbr
              AND b.head = c.head
              AND b.type_of_action <> '6') src
              ON ( a.ROWID = src.row_id )
  WHEN MATCHED THEN UPDATE SET in_correct = 'Y';
Pop
la source
1
C'est probablement pourquoi d'autres approches (pour moi) ont également renvoyé d'autres erreurs pour moi (comme `` procédure, fonction, package ou type n'est pas autorisé ici '' et `` Impossible de modifier une colonne qui correspond à une erreur de table non conservée par clé en essayant de insérer dans une vue '). ~ Si cela aide quelqu'un d'autre, j'ai eu la même erreur même après avoir ajouté distinct jusqu'à ce que je réorganise les jointures de ma requête interne, alors j'ai commencé avec la table qui recevait plus d'une ligne renvoyée et qui était jointe en interne à partir de là ... si cela logique.
jinglesthula
40

Vous essayez probablement de mettre à jour plusieurs fois la même ligne de la table cible. Je viens de rencontrer le même problème dans une déclaration de fusion que j'ai développée. Assurez-vous que votre mise à jour ne touche pas le même enregistrement plus d'une fois lors de l'exécution de la fusion.

DCookie
la source
1
+1, merci, cela m'est arrivé sur une table cible avec un petit nombre de doublons (au moins en fonction des clés utilisées dans la fusion).
tbone
6

Comment dépanner les erreurs ORA-30926? (Doc ID 471956.1)

1) Identifiez l'instruction défaillante

modifier les événements d'ensemble de session '30926 nom de trace niveau de pile d'erreurs 3';

ou

modifier les événements d'ensemble du système '30926 trace name errorstack off';

et surveillez les fichiers .trc dans UDUMP quand cela se produit.

2) Après avoir trouvé l'instruction SQL, vérifiez si elle est correcte (peut-être en utilisant le plan explicatif ou tkprof pour vérifier le plan d'exécution de la requête) et analysez ou calculez des statistiques sur les tables concernées si cela n'a pas été fait récemment. La reconstruction (ou la suppression / la recréation) des index peut également aider.

3.1) L'instruction SQL est-elle une MERGE? évaluez les données renvoyées par la clause USING pour vous assurer qu'il n'y a pas de valeurs en double dans la jointure. Modifiez l'instruction de fusion pour inclure une clause where déterministe

3.2) S'agit-il d'une instruction UPDATE via une vue? Si tel est le cas, essayez de remplir le résultat de la vue dans une table et essayez de mettre à jour la table directement.

3.3) Y a-t-il un déclencheur sur la table? Essayez de le désactiver pour voir s'il échoue toujours.

3.4) L'instruction contient-elle une vue non fusionnable dans une «sous-requête IN»? Cela peut entraîner le renvoi de lignes en double si la requête comporte une clause "FOR UPDATE". Voir le bogue 2681037

3.5) Le tableau contient-il des colonnes inutilisées? Les supprimer peut empêcher l'erreur.

4) Si la modification du SQL ne résout pas l'erreur, le problème peut provenir de la table, surtout s'il y a des lignes chaînées. 4.1) Exécutez l'instruction 'ANALYZE TABLE VALIDATE STRUCTURE CASCADE' sur toutes les tables utilisées dans le SQL pour voir s'il y a des corruptions dans la table ou ses index. 4.2) Vérifiez et éliminez toutes les RANGÉES EN CHAÎNE ou migrées sur la table. Il existe des moyens de minimiser cela, comme le réglage correct de PCTFREE. Remarque d'utilisation 122020.1 - Chaînage de lignes et migration 4.3) Si le tableau est également organisé par index, voir: Note 102932.1 - Surveillance des lignes chaînées sur les IOT

Tagar
la source
5

Il y avait l'erreur aujourd'hui sur un 12c et aucune des réponses existantes ne correspondait (pas de doublons, pas d'expressions non déterministes dans la clause WHERE). Mon cas était lié à cette autre cause possible de l'erreur, selon le texte du message d'Oracle (souligné ci-dessous):

ORA-30926: impossible d'obtenir un ensemble stable de lignes dans les tables source
Cause: Un ensemble stable de lignes n'a pas pu être obtenu en raison d'une importante activité dml ou d'une clause where non déterministe.

La fusion faisait partie d'un lot plus important et a été exécutée sur une base de données en direct avec de nombreux utilisateurs simultanés. Il n'était pas nécessaire de modifier la déclaration. Je viens de valider la transaction avant la fusion, puis j'ai exécuté la fusion séparément et je l'ai validée à nouveau. La solution a donc été trouvée dans l'action suggérée du message:

Action: supprimez toutes les clauses where non déterministes et relancez le fichier dml .

Cee McSharpface
la source
Je recevais ce message d'erreur lors d'une importation DataPump via le réseau (en utilisant un NETWORK_LINKparamètre qui se connecte directement à la base de données source) pendant l'étape de collecte des statistiques, et votre note en surbrillance l'explique probablement. Heureusement, seules les statistiques ont été affectées.
Mark Stewart
1
SQL Error: ORA-30926: unable to get a stable set of rows in the source tables
30926. 00000 -  "unable to get a stable set of rows in the source tables"
*Cause:    A stable set of rows could not be got because of large dml
           activity or a non-deterministic where clause.
*Action:   Remove any non-deterministic where clauses and reissue the dml.

Cette erreur s'est produite pour moi en raison d'enregistrements en double (16 Ko)

J'ai essayé avec unique cela a fonctionné .

mais encore une fois, quand j'ai essayé de fusionner sans unique, le même problème s'est produit La deuxième fois, il devait commettre

après la fusion si la validation n'est pas effectuée, la même erreur sera affichée.

Sans unique, Query fonctionnera si la validation est donnée après chaque opération de fusion.

v8-E
la source
-1

Une clarification supplémentaire sur l'utilisation de DISTINCT pour résoudre l'erreur ORA-30926 dans le cas général:

Vous devez vous assurer que l'ensemble de données spécifié par la clause USING () n'a pas de valeurs en double des colonnes de jointure , c'est-à-dire les colonnes de la clause ON () .

Dans l'exemple d'OP où la clause USING sélectionne uniquement une clé, il suffisait d'ajouter DISTINCT à la clause USING. Cependant, dans le cas général, la clause USING peut sélectionner une combinaison de colonnes clés à mettre en correspondance et de colonnes d'attribut à utiliser dans la clause UPDATE ... SET. Par conséquent, dans le cas général, l'ajout de DISTINCT à la clause USING autorisera toujours différentes lignes de mise à jour pour les mêmes clés, auquel cas vous obtiendrez toujours l'erreur ORA-30926.

Ceci est une élaboration de la réponse de DCookie et du point 3.1 de la réponse de Tagar, ce qui, d'après mon expérience, n'est peut-être pas immédiatement évident.

Durban_legend
la source