Question

Je sais que Oracle SGBDR ne peut pas fusionner une vue qui a un opérateur de jeu en elle. Je veux savoir pourquoi est-ce.

Par exemple, ceci:

SELECT u.*
FROM
 (
  SELECT a.a1    A,
        a.a2    B
   FROM tab_a a
UNION ALL
  SELECT b.b1    A,
         b.b2    B
    FROM tab_b b
)     u,
tab_p p
WHERE p.a = u.a

pourrait être transformé en ceci:

SELECT *
FROM
 (
  SELECT a.a1    A,
         a.a2    B
    FROM tab_a a,
         tab_p p
   WHERE p.a = a.a1
UNION ALL
  SELECT b.b1    A,
         b.b2    B
    FROM tab_b b,
         tab_p p
   WHERE p.a = b.b1
)

Ces deux requêtes sont équivalentes, non? [Édité]

Était-ce utile?

La solution

La transformation que vous décrivez dans votre question apparaît valide éditée moi.

Il existe beaucoup de différentes transformations de requête que l'optimiseur Oracle pourrait en théorie effectuer, mais dans la pratique, cela se limite aux transformations que l'équipe Oracle ont travaillé effectivement pris la peine de mettre en œuvre .

Chaque transformation, si ajouté, nécessiterait un investissement important dans le codage et le test, et ne sera fait si une demande suffisante a été détectée sur le marché payant.

Alors, ce n'est pas qu'il « ne peut pas », nécessairement; il n'a tout simplement pas encore.

Autres conseils

Les requêtes produira le même ResultSet, mais le plan d'exécution est susceptible d'être différent. J'attends la première requête d'être plus efficace, car il compare contre tab_p une fois, contre les deux fois dans la deuxième requête.


Auparavant, les deux requêtes utilisées SELECT *, aucun alias de table dans l'un d'eux.

Non, ces requêtes ne sont pas équivalents.

La première renvoie des colonnes à la fois la table dérivée (déclaration UNION'd) et la table de tab_p. La deuxième requête renvoie uniquement les valeurs de la table dérivée (déclaration UNION'd), et aucune colonne de la table tab_p. Il est plus évident si vous remplacez les alias de table dans le lieu de SELECT *:

Première requête:

SELECT u.*, p.*
  FROM (SELECT a.a1    A,
               a.a2    B
          FROM tab_a a
        UNION ALL
        SELECT b.b1    A,
               b.b2    B
          FROM tab_b b) u,
       tab_p p
 WHERE p.a = u.a

Deuxième requête:

SELECT x.*
 FROM (SELECT a.a1    A,
              a.a2    B
         FROM tab_a a,
              tab_p p
        WHERE p.a = a.a
       UNION ALL
       SELECT b.b1    A,
              b.b2    B
         FROM tab_b b,
              tab_p p
        WHERE p.a = b.a) x

Il n'y a pas de colonnes tab_p dans la clause SELECT de la requête interne pour la requête externe pour fournir à l'ensemble de résultats final.

SELECT *
  FROM (SELECT a.a1    A,
               a.a2    B
          FROM tab_a a
        UNION ALL
        SELECT b.b1    A,
               b.b2    B
          FROM tab_b b) u
  JOIN tab_p p ON p.a = u.a

.. est équivalente à la première requête. Il utilise la norme ANSI-92 syntaxe de jointure vs la syntaxe ANSI-89 utilisé dans la première requête.

Ils ne sont pas équivalents. La deuxième requête échouera, comme u n'est pas défini.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top