- ¿Qué es una unión interna?
- ¿Qué es una combinación externa?
- Realización de uniones externas con el símbolo (+)
Como prácticamente todas las bases de datos relacionales, Oracle permite generar consultas que combinan o JOIN
filas de dos o más tablas para crear el conjunto de resultados final. Si bien existen numerosos tipos de uniones que se pueden realizar, las más comunes son las INNER JOIN
y la OUTER JOIN
.
En este tutorial, exploraremos brevemente la diferencia entre el INNER
y OUTER JOIN
y luego examine el método abreviado que proporciona Oracle para realizar OUTER JOINS
específicamente usando el +
símbolo del operador.
¿Qué es una unión interna?
Una INNER JOIN
en una base de datos relacional es simplemente la unión de dos o más tablas en las que el resultado solo contendrá datos que satisfagan todas las condiciones de unión .
Por ejemplo, aquí tenemos una library
básica esquema con dos tablas:books
y languages
. Los languages
la tabla es solo una lista de posibles nombres de idiomas y un idioma único id
:
SELECT * FROM library.languages;
id name
1 English
2 French
3 German
4 Mandarin
5 Spanish
6 Arabic
7 Japanese
8 Russian
9 Greek
10 Italian
Mientras tanto, nuestros books
la tabla tiene un language_id
fila que para la mayoría de los libros, pero no para todos, simplemente contiene el language_id
asociado con el idioma original publicado del libro:
SELECT * FROM
books
ORDER BY
id
FETCH FIRST 10 ROWS ONLY;
id title author year_published language_id
1 In Search of Lost Time Marcel Proust 1913 2
2 Ulysses James Joyce 1922 1
3 Don Quixote Miguel de Cervantes 1605 5
4 Moby Dick Herman Melville 1851 1
5 Hamlet William Shakespeare 1601 (null)
6 War and Peace Leo Tolstoy 1869 8
7 The Odyssey Homer -700 9
8 The Great Gatsby F. Scott Fitzgerald 1925 1
9 The Divine Comedy Dante Alighieri 1472 10
10 Madame Bovary Gustave Flaubert 1857 2
En muchos casos, es posible que deseemos realizar una INNER JOIN
de los books
y languages
tablas por lo que en lugar de ver el sin sentido language_id
valor de cada libro, en realidad podemos ver el language name
en su lugar.
SELECT
b.id,
b.title,
b.author,
b.year_published,
l.name language
FROM
books b
INNER JOIN
library.languages l
ON
b.language_id = l.id
ORDER BY
b.id
FETCH FIRST 10 ROWS ONLY;
id title author year_published language
1 In Search of Lost Time Marcel Proust 1913 French
2 Ulysses James Joyce 1922 English
3 Don Quixote Miguel de Cervantes 1605 Spanish
4 Moby Dick Herman Melville 1851 English
6 War and Peace Leo Tolstoy 1869 Russian
7 The Odyssey Homer -700 Greek
8 The Great Gatsby F. Scott Fitzgerald 1925 English
9 The Divine Comedy Dante Alighieri 1472 Italian
10 Madame Bovary Gustave Flaubert 1857 French
11 The Brothers Karamazov Fyodor Dostoyevsky 1880 Russian
Lo que es fundamental tener en cuenta aquí es que nuestro conjunto de resultados fue ligeramente diferente en las dos consultas anteriores. En el primero, simplemente enumeramos el primer 10
libros, pero en el INNER JOIN
consulta, solo devolvemos resultados que cumplen todas las condiciones de ambas tablas. Por ello, el registro de Hamlet
(que tiene un language_id
valor de null
o vacío) se ignora y no se devuelve en el resultado de nuestro INNER JOIN
.
¿Qué es una unión externa?
En lugar de devolver exclusivamente resultados que satisfagan todas las condiciones de unión de una INNER JOIN
, una OUTER JOIN
devuelve no solo resultados que satisfacen todas las condiciones, sino también devuelve las filas de una tabla que no cumplieron la condición. La tabla que se elige para esta "omisión" de los requisitos condicionales está determinada por la direccionalidad o el "lado" de la combinación, normalmente denominada LEFT
o RIGHT
uniones externas.
Al definir un lado de su OUTER JOIN
, está especificando qué tabla siempre devolverá su fila incluso si el opuesto falta la tabla en el otro lado de la combinación o null
valores como parte de la condición de unión.
Por lo tanto, si realizamos el mismo JOIN
básico como arriba para recuperar books
y language names
, sabemos que nuestros books
la tabla siempre debe devolver datos, por lo que nuestro JOIN
el lado debe "apuntar hacia" nuestros books
tabla, lo que hace que los languages
tabla el OUTER
tabla que le adjuntamos.
Para lograr esto, simplemente cambiamos:
books b INNER JOIN library.languages l
…a esto:
books b LEFT OUTER JOIN library.languages l
Por lo tanto, toda la consulta y el conjunto de resultados se ven casi idénticos a INNER JOIN
excepto esa alteración menor:
SELECT
b.id,
b.title,
b.author,
b.year_published,
l.name language
FROM
books b
LEFT OUTER JOIN
library.languages l
ON
b.language_id = l.id
ORDER BY
b.id
FETCH FIRST 10 ROWS ONLY;
id title author year_published language
1 In Search of Lost Time Marcel Proust 1913 French
2 Ulysses James Joyce 1922 English
3 Don Quixote Miguel de Cervantes 1605 Spanish
4 Moby Dick Herman Melville 1851 English
5 Hamlet William Shakespeare 1601 (null)
6 War and Peace Leo Tolstoy 1869 Russian
7 The Odyssey Homer -700 Greek
8 The Great Gatsby F. Scott Fitzgerald 1925 English
9 The Divine Comedy Dante Alighieri 1472 Italian
10 Madame Bovary Gustave Flaubert 1857 French
Como era de esperar, mediante el uso de LEFT OUTER JOIN
en lugar del anterior INNER JOIN
, obtenemos lo mejor de ambos mundos:no nos saltamos ningún books
registros (como Hamlet
) simplemente porque el language_id
el valor es null
para ese registro, pero para todos los registros donde language_id
existe, obtenemos el language name
bien formateado obtenido de nuestros languages
mesa.
Realizar uniones externas usando el símbolo (+)
Como se indica en la documentación oficial, Oracle proporciona un outer join operator
especial (el +
símbolo) que es una forma abreviada de realizar OUTER JOINS
.
En la práctica, el +
el símbolo se coloca directamente en el condicional declaración y en el lado de la tabla opcional (la que puede contener vacío o null
valores dentro del condicional).
Por lo tanto, podemos volver a escribir nuestra anterior LEFT OUTER JOIN
declaración usando el +
operador así:
SELECT
b.id,
b.title,
b.author,
b.year_published,
l.name language
FROM
books b,
library.languages l
WHERE
l.id (+)= b.language_id
ORDER BY
b.id
FETCH FIRST 10 ROWS ONLY;
Los resultados son los mismos que los de LEFT OUTER JOIN
estándar ejemplo anterior, por lo que no los incluiremos aquí. Sin embargo, hay un aspecto crítico a tener en cuenta sobre la sintaxis usando +
operador para OUTER JOINS
.
El +
el operador debe estar en el lado izquierdo del condicional (a la izquierda de los iguales =
señal). Por lo tanto, en este caso, porque queremos asegurarnos de que nuestros languages
table es la tabla opcional que puede devolver null
valores durante esta comparación, intercambiamos el orden de las tablas en este condicional, por lo que languages
está a la izquierda (y es opcional) mientras que books
está a la derecha.
Por último, debido a este reordenamiento de los lados de la tabla en el condicional cuando se usa +
operador, es importante darse cuenta de que lo anterior es simplemente una abreviatura de RIGHT OUTER JOIN
. Esto significa que este fragmento de la consulta:
FROM
books b,
library.languages l
WHERE
l.id (+)= b.language_id
…es efectivamente idéntico a esto:
FROM
library.languages l
RIGHT OUTER JOIN
books b
ON
b.language_id = l.id