ne peuvent pas fusionner une union all vue
-
26-09-2019 - |
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é]
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.