¿Por qué no se utilizan coincidencias de clave principal / clave externa para las uniones?


48

Por lo que pude descubrir, muchos DBMS (por ejemplo, mysql, postgres, mssql) usan combinaciones fk y pk solo para restringir los cambios en los datos, pero rara vez se usan de forma nativa para seleccionar automáticamente columnas para unir (como la combinación natural hace con nombres). ¿Porqué es eso? Si ya ha definido una relación entre 2 tablas con un pk / fk, ¿por qué la base de datos no puede darse cuenta de que si me uno a esas tablas quiero unirlas en las columnas pk / fk?

EDITAR: para aclarar esto un poco:

supongamos que tengo una tabla1 y una tabla2. la tabla 1 tiene una clave externa en la columna a, que hace referencia a la clave primaria en la tabla 2, la columna b. Ahora, si me uno a estas tablas, tendré que hacer algo como esto:

SELECT * FROM table1
JOIN table2 ON table1.a = table2.b

Sin embargo, ya definí usando mis claves que table1.a hace referencia a table2.b, por lo que me parece que no debería ser difícil hacer que un sistema DBMS use automáticamente table1.a y table2.b como columnas de unión, tal que uno simplemente puede usar:

SELECT * FROM table1
AUTO JOIN table2

Sin embargo, muchos DBMS no parecen implementar algo como esto.

Respuestas:


32

En muchos casos, hay más de una forma de unir dos tablas; Vea las otras respuestas para muchos ejemplos. Por supuesto, se podría decir que sería un error utilizar la 'unión automática' en esos casos. Entonces solo quedaría un puñado de casos simples donde se puede usar.

Sin embargo, hay un grave inconveniente! ¡Las consultas que son correctas hoy, podrían convertirse en un error mañana simplemente agregando un segundo FK a la misma tabla!

Permítanme decirlo nuevamente: al agregar columnas, las consultas que no usan esas columnas podrían pasar de 'correcto' a 'error'.

Esa es una pesadilla de mantenimiento, que cualquier guía de estilo sensata prohibiría usar esta función. ¡La mayoría ya lo prohíbe select *por la misma razón!

Todo esto sería aceptable si se mejorara el rendimiento. Sin embargo, ese no es el caso.

En resumen, esta función podría usarse solo en un conjunto limitado de casos simples, no aumenta el rendimiento y la mayoría de las guías de estilo prohibirían su uso de todos modos.

Por lo tanto, no es sorprendente que la mayoría de los proveedores de bases de datos elijan dedicar su tiempo a cosas más importantes.


1
Probablemente habría un pequeño impacto en el rendimiento, ya que tiene que descubrir las columnas de unión en lugar de especificarlas.
HLGEM

1
@HLGEM, eso podría almacenarse en caché, y también sería irrelevante para consultas más grandes. La ventaja es que podemos estar seguros de que no se pierden claves debido a algún error humano.
Pacerier

Agregar y modificar columnas también podría romperse NATURAL JOIN(por lo que generalmente las evito), pero no creo que eso en sí mismo deba significar que un dbms no podría implementar una forma automática de unir tablas basadas en claves foráneas.
Jay K

2
¿Muchos casos? En una base de datos de mil tablas, solo tengo algunos pocos casos de relación de más de 1 entre dos tablas. De todos modos, eso no es un problema, sería suficiente agregar un nombre de relación como AUTO JOIN mytable THROUGH myrelation, sería muy bueno.
Teejay

Eso es lo que hacemos en nuestro generador de SQL personalizado .NET, con intellisense, comoInnerJoin(SRC_TABLE.rDEST_TABLE.REL_NAME_F01)
Teejay

27

Una clave foránea está destinada a restringir los datos. es decir, hacer cumplir la integridad referencial. Eso es. Nada más.

  1. Puede tener varias claves externas para la misma tabla. Considere lo siguiente cuando un envío tiene un punto de inicio y un punto final.

    table: USA_States
    StateID
    StateName
    
    table: Shipment
    ShipmentID
    PickupStateID Foreign key
    DeliveryStateID Foreign key
    

    Es posible que desee unirse en función del estado de recogida. Quizás quieras unirte al estado de entrega. ¡Quizás quieras realizar 2 uniones para ambos! El motor sql no tiene forma de saber lo que quieres.

  2. A menudo cruzará valores escalares de unión. Aunque los escalares generalmente son el resultado de cálculos intermedios, a veces tendrá una tabla de propósito especial con exactamente 1 registro. Si el motor intentara detectar una clave extranjera para la unión ... no tendría sentido porque las uniones cruzadas nunca coinciden con una columna.

  3. En algunos casos especiales, se unirá en columnas donde ninguna de las dos es única. Por lo tanto, la presencia de un PK / FK en esas columnas es imposible.

  4. Usted puede pensar que los puntos 2 y 3 anteriores no son relevantes ya que sus preguntas acerca de cuándo es allí ES una relación única PK / FK entre las mesas. Sin embargo, la presencia de un solo PK / FK entre las tablas no significa que no pueda tener otros campos para unirse además del PK / FK. El motor sql no sabría en qué campos desea unirse.

  5. Digamos que tiene una tabla "USA_States" y otras 5 tablas con un FK para los estados. Las "cinco" tablas también tienen algunas claves externas entre sí. ¿Debería el motor SQL unir automáticamente las "cinco" tablas con "USA_States"? ¿O debería unir los "cinco" entre sí? ¿Ambos? Puede configurar las relaciones para que el motor sql entre en un bucle infinito tratando de unir cosas. En esta situación, es imposible para el motor SQL adivinar lo que quiere.

En resumen: PK / FK no tiene nada que ver con las uniones de tabla. Son cosas separadas no relacionadas. Es solo un accidente de la naturaleza que a menudo te unes en las columnas PK / FK.

¿Desea que el motor SQL adivine si es una unión completa, izquierda, derecha o interna? No lo creo. Aunque podría decirse que sería un pecado menor que adivinar las columnas para unirse.


77
Considero que las claves externas y la normalización son muy relevantes para las uniones de tabla.

3
Sus argumentos se mantienen cuando la palabra clave normal JOIN siempre intenta hacer coincidir eso (como hice mal en mi ejemplo, lo arreglaré). Sin embargo, muchas combinaciones pueden derivarse directamente solo de las combinaciones, por lo que no veo ninguna razón por la que no pueda haber una sintaxis explícita para unirlas. Muchos DBMS tienen una unión natural, que básicamente hace lo mismo pero con nombres de columna (= malo). Lo mismo podría hacerse con este tipo de unión, por ejemplo, especificando una operación de UNIÓN AUTOMÁTICA.

55
"Es solo un accidente de la naturaleza que a menudo te unes en las columnas PK / FK" - ¡No estoy convencido!
cuando el

2
"¿Normalización?" Creo que el pensamiento aquí es que si comenzaste con un relvar 1NF y luego te descomponías en relvars 6NF, entonces las posibilidades son a) tendrían claves foráneas en la implementación yb) se unirían con frecuencia en consultas.
cuando el

44
Votaría si no hubiera "PK / FK no tiene nada que ver con las uniones de mesa".
ypercubeᵀᴹ

11

El concepto de "jobility". Las relaciones r1y se r2pueden unir si y solo si los atributos con el mismo nombre son del mismo tipo ... este concepto se aplica no solo para unirse como tal sino también para otras operaciones [como union].

SQL y teoría relacional: cómo escribir código SQL preciso por fecha CJ

El SQL estándar ya tiene dicha característica, conocida como NATURAL JOIN, y se ha implementado en mySQL.

Aunque su sugerencia no es tan valiosa, parece razonable. Con SQL Server (que carece de soporteNATURAL JOIN ), uso SQL Prompt en Management Studio: cuando escribo un, INNER JOINsu InteliSense sugiere ONcláusulas basadas en nombres de atributos comunes y claves foráneas y me parece muy útil. Sin embargo, no tengo muchas ganas de ver un nuevo tipo de combinación SQL (estándar) para esto.


1
La unión natural y la unión en columnas comunes es distinta y ortogonal a la noción de unión en FK-PK. (Vea mi respuesta.)
philipxy

@philipxy: de acuerdo, no tenía la intención de implicar lo contrario. (¡La
suya

9

¡SQL vino primero!

Las restricciones de Claves externas y Claves externas llegaron más tarde y son esencialmente una optimización para aplicaciones de estilo de "transacción".

Las bases de datos relacionales se concibieron originalmente como un método para aplicar consultas complejas en conjuntos de datos de manera matemáticamente demostrable utilizando álgebra relacional. IE para un conjunto dado de datos y una consulta dada siempre hay una única respuesta correcta.

Las bases de datos relacionales han recorrido un largo camino desde entonces, y su uso principal como la capa de persistencia para los sistemas transaccionales no fue lo que CODD et. Todo previsto.

Sin embargo, el organismo de estándares ANSI para todos sus objetivos en conflicto y políticas de proveedores siempre se ha esforzado por preservar las propiedades "matemáticamente demostrables" de SQL.

Si permitía que la base de datos dedujera las propiedades de unión a partir de datos de clave externa "ocultos", perdería esta propiedad (tenga en cuenta la ambigüedad si hubiera más de un conjunto de claves externas definidas).

Además, un programador que lea el SQL no necesariamente sabría qué claves externas se definieron actualmente para las dos tablas y necesitaría examinar el esquema de la base de datos para determinar qué estaba haciendo la consulta.


3
¡Gracias, esto tenía sentido para mí! Sin embargo, ¿las uniones naturales no tienen los mismos problemas? Aunque las uniones naturales incluso tienen problemas más grandes, muchos DBMS los admiten. En mi opinión, una unión basada en pk / fk sería una unión natural bien hecha.

1
En lo que respecta a la mayoría de los motores de bases de datos, no existe una diferencia entre una unión natural y un "JOIN ... ON" explícito. El motor analiza la consulta y realiza la unión lo mejor que puede en función de los diversos predicados. El uso de una unión explícita no fuerza el uso de un índice o ruta de acceso particular, está allí principalmente para admitir la sintaxis de unión "IZQUIERDA, EXTERNA, INTERNA" que necesita conocer los predicados de unión explícita para saber cuándo insertar una fila "faltante" .

66
¡SQL no vino primero! El modelo relacional (que incluía el concepto de claves foráneas, por supuesto) fue primero esbozado por EFCodd en 1969. SEQUEL, como era entonces, no vio la luz hasta alrededor de 1974. Sus inventores dejaron en claro desde el principio que SEQUEL / SQL estaba destinado a basarse en el modelo relacional preexistente, aunque SQL no fue un lenguaje verdaderamente relacional.
nvogel

@sqlvogel: ¡cierto! Debería haberlo redactado "SQL se implementó primero".
James Anderson

CJ Date en 'Una introducción a los sistemas de bases de datos' (p276) dice que Codd inventó el concepto de la clave externa; no dice cuándo, pero supongo que fue antes de la primera implementación de SQL.
cuando el

7

Si bien ha definido una relación de clave externa que no significa que es así como desea unir las tablas en todas las consultas. Es el método más probable para unir las tablas, pero hay casos en los que no es correcto.

  • Es posible que desee utilizar un producto cartesiano de las dos tablas o parte de ellas para algún propósito.
  • Puede haber otros campos en los que puede unirse para otro propósito.
  • Si está uniendo tres o más tablas, una de las tablas puede estar relacionada con dos o más de las tablas. En este caso, generalmente solo una de las posibles relaciones FK puede ser apropiada en la consulta.

7

Puede estar operando con una suposición falsa. Dices "hasta donde puedes averiguar" pero no das ninguna prueba empírica o probatoria. Si pk o fk son el mejor índice para una consulta, se utilizará. No sé por qué estás viendo esto, pero supongo que son consultas mal formadas.


Edite ahora que la pregunta se ha reescrito por completo: el caso que está describiendo sería solo para un conjunto muy pequeño de consultas. ¿Qué pasa si hay 12 mesas unidas? ¿Qué pasa si no hay FKs? ... Incluso si hubiera una unión predeterminada, siempre especificaría la unión solo para facilitar la lectura. (No quiero tener que mirar los datos y luego tratar de averiguar en qué se está uniendo)

Algunas herramientas de consulta realmente hacen una unión automática por usted y luego le permiten eliminar o editar la unión. Creo que el generador de consultas de MS Access hace esto.

Por último, el estándar ANSII establece que la unión debe especificarse. Esa es razón suficiente para no permitirlo.


3
Lo siento, tal vez no fui lo suficientemente claro. No estoy hablando de índices, estoy hablando de uniones. Supongamos que tengo table1 y table2, con un fk en table1.a que apunta a table2.b. Si me uno a estas tablas, tendré que decir explícitamente que quiero unirlas en las columnas ayb (por ejemplo, 'SELECCIONAR * DE la tabla1 UNIRSE a la tabla2 EN la tabla1.a = tabla2.b '), mientras que ya definí en mi base de datos esquema de que esos dos están relacionados. La pregunta es por qué no puedo hacer 'SELECT * FROM table1 JOIN table2' y dejar que el DBMS elija automáticamente las columnas de unión en función de fk / pk.

44
¡Especialmente la legibilidad tenía sentido para mí! Sin embargo, eso dice que el estándar no es realmente un buen argumento de la OMI. Muchos estándares han tomado decisiones incorrectas antes (HTML, por ejemplo).

3

Hay muchas razones por las cuales la base de datos no puede hacer esto de manera segura, incluido el hecho de que agregar / eliminar claves externas cambiará el significado de las consultas preescritas, incluidas las consultas en el código fuente de la aplicación. La mayoría de las bases de datos tampoco tienen un buen conjunto de claves foráneas que cubran todas las combinaciones posibles que probablemente desee. También para bien o para mejor, las claves externas a menudo se eliminan para acelerar los sistemas y no se pueden usar en tablas que se cargan en el orden "incorrecto" del archivo.

Sin embargo, no hay ninguna razón por la cual una herramienta de diseño de consultas o el editor de texto no puedan completar automáticamente una combinación con la ayuda de Foreign Keys de la misma manera que le dan inteligencia sobre el nombre de la columna. Puede editar la consulta si la herramienta se equivocó y guardar una consulta completamente definida. Tal herramienta también podría hacer uso útil de la convención de nombrar columnas Foreign Keys por el nombre de la tabla "padre" y las columnas con el mismo nombre en la tabla padre / hijo, etc.

(¡Mi esposa todavía no puede entender la diferencia entre Management Studio y Sql Server y habla sobre iniciar el servidor SQL cuando inicia Management Studio!)


3

La unión natural se une "automáticamente" a la igualdad de las columnas comunes, pero solo debe escribir eso si eso es lo que desea en función de los significados de la tabla y el resultado deseado. No hay forma "automática" de saber cómo dos tablas "deberían" unirse o de cualquier otra forma que cualquier tabla "debería" aparecer en una consulta. No necesitamos conocer restricciones para consultar. Su presencia solo significa que las entradas pueden ser limitadas y, en consecuencia, la salida también puede serlo. Podría definir algún tipo de operador join_on_fk_to_pk que se una "automáticamente" a las restricciones declaradas; pero si desea que el significado de la consulta permanezca igual si solo cambian las restricciones pero no los significados de la tabla, entonces tendría que cambiar esa consulta para no usar las nuevas constaciones declaradas.ya deja el significado igual a pesar de cualquier cambio de restricción .

Las restricciones (incluyendo PK, FK, UNIQUE y CHECK) no afectan el significado de las tablas. Por supuesto, si los significados de la tabla cambian, las restricciones podrían cambiar. Pero si las restricciones cambian, no significa que las consultas deberían cambiar.

No es necesario conocer las restricciones para consultar. Conocer las restricciones significa que podemos usar expresiones adicionales que sin la retención de la restricción no devolverían la misma respuesta. Por ejemplo, esperar a través de UNIQUE que una tabla tiene una fila, por lo que podemos usarla como escalar. Estas consultas pueden romperse si se asumió la restricción pero no se declaró. Pero declarar una restricción que la consulta no asumió no puede romperla.

¿Existe alguna regla general para construir una consulta SQL a partir de una descripción legible por humanos?


2

La razón es que existe el IDIOMA, y luego están los principios subyacentes. El lenguaje es escaso y carece de muchas características que esperaría ver en un lenguaje de propósito general. Esto simplemente es una buena característica que no se ha agregado al idioma y que probablemente no se agregará. No es un idioma muerto, así que hay algo de esperanza, pero no sería optimista.

Como otros han señalado, algunas implementaciones usan una extensión donde join (column) une dos tablas basadas en un nombre de columna común, que es algo similar. Pero no está muy extendido. Tenga en cuenta que esta extensión es diferente de la SELECT * FROM employee NATURAL JOIN department;sintaxis, que no incluye una forma de especificar qué columnas usar. Tampoco se basan en una relación entre las tablas, lo que las hace poco confiables (la sintaxis de unión natural más que la extensión).

No hay ningún obstáculo fundamental para la "tabla de unión interna en PKFK", donde PKFK es una palabra clave que significa "la relación de clave externa definida entre las dos tablas", puede haber problemas con múltiples fk en la misma tabla, pero eso podría simplemente causar un error. La pregunta es si las personas que diseñan el idioma consideran que a) es una buena idea yb) es mejor trabajar que algún otro cambio de idioma ...


3
Esto supone que es una buena idea que ya deberían haberlo hecho. También es probable que ya lo hayan considerado y hayan decidido no hacerlo. Quizás sea una muy mala idea en la práctica: Sjoerd mencionó un ejemplo, donde una consulta podría romperse simplemente al agregar una nueva columna y una relación FK. Lord Tydus también explica que las claves externas tienen una responsabilidad diferente de dictar las formas en que se deben unir las tablas.

1
@JonathanHobbs: quise decir que mi respuesta era generalmente neutral, pero abandonar la neutralidad, la lógica de Joerd es defectuosa, los cambios en las tablas ya rompen las consultas, agregar una nueva columna a una clave principal de las tablas va a romper las consultas o comenzar a devolver resultados incorrectos. De hecho, esto lo aislaría hasta cierto punto, siempre que se mantuviera la relación de la tabla, los cambios en la columna se podrían hacer de forma segura. Esto probablemente aumentaría el uso de las relaciones FK, ya que sería útil para algo distinto de RI. están en el PK o incluyen el Pk. Para manejar múltiples fk, use el nombre de la columna.
jmoreno

1

Si se supone que omitir la cláusula ON sigue los campos en función de la integridad referencial, ¿cómo haría un producto cartesiano?

Editar: usar AUTO Las ventajas de esto es escribir un poco menos y no es necesario saber cómo se unen ni recordar una combinación complicada. Si la relación cambia, se maneja automáticamente, pero eso rara vez ocurre, excepto en el desarrollo temprano.

Lo que debe hacer ahora es decidir si todas sus uniones AUTO se mantienen durante un cambio de relación para que coincida con la intención de su declaración de selección.


1
@JeffO: la principal ventaja es que expresa la intención con mayor precisión, de una manera declarativa muy clara. Las uniones en los nombres de columna no le dicen nada, aparte del hecho de que algunos de los contenidos de las columnas son similares a los de otra (pero pueden no ser del mismo tipo). Una combinación en una ref FK, le dice que no es un ref FK, sin lista de columnas significaría que había sólo 1 FK entre las mesas, o por el contrario que hay 1+ (considere una clave de varias columnas con más de 1 ref lo que sucede cuando mezcla las columnas c1 = fk1_c1 y c2 = fk2_c2). Incluso con más tipeo en promedio, esto sería bueno.
jmoreno

Usar (INNER) JOIN sin ON no es SQL estándar. Coma, CROSS JOIN & (INNER o any OUTER) JOIN ON 0 = 0 devuelve producto cartesiano.
philipxy

-1

¿por qué la base de datos no puede darse cuenta de que si me uno a esas tablas quiero unirlas en las columnas pk / fk?

Partes de la razón son:

1: en teoría, puede unir tablas en columnas arbitrarias de las dos tablas. Si bien esto no es una práctica común, es válido. Recuerde que SQL es como un lenguaje de programación, no comprende qué información hay dentro de las columnas del curso y los nombres, para SQL, no significan mucho en este sentido.

2: existen diferentes tipos de combinaciones (izquierda, derecha, interior): las combinaciones internas son solo 1 de ellas.

3 - El estándar SQL puede guiarse por el principio de ser un lenguaje de nivel inferior que permite que los dialectos de nivel superior formen inteligencia al usarlo. La comparación es algo más clara si piensa en un lenguaje de cuarta generación frente a un lenguaje de tercera generación. De hecho, una herramienta que he usado, IEF, le permitió escribir algo como esto:

ReadEach Customer 
Where Customer Places Orders and That Customer LivesIn "California" 
and OrderValue > 100.00

En resumen, su sugerencia es interesante y podría implementarse como parte de la norma o como un procedimiento almacenado (por defecto sería una unión interna).


-10

Tiddo, creo que tienes toda la razón, SQL sobre ese tema es bastante tonto , y recuerdo haber pensado lo mismo que hiciste sobre las claves externas mientras aprendías SQL hace unos diez años.

Ok, dado eso, eventualmente tuve que aprobar ese examen; y para pasarlo, tuve que dejarlo ir . SQL es más un desastre de lo que cualquiera puede admitir, su ruta de estandarización es un completo desastre y algunas implementaciones son amenazantes . Aún así es bastante útil, en general. (No soy un ludita K / V)

Claves foráneas, entonces ... no es tan útil en absoluto. Son un concepto importante en el modelo relacional , está bien, pero la función SQL con el mismo nombre no se compara bien.

Decirle recta: no utilice esta característica SQL llamada Foreign Keyen absoluto , hasta llegar a algún gran sistema con problemas de rendimiento. Explícitamente decirle al motor de qué campo es una clave externa y que no se está sólo se utiliza para la indexación, y es invisible para el usuario db.

¿Es engañoso?
Si.

¿Lo van a hacer más poderoso ahora, después de 30 años de personas engañadas?
De ninguna manera.

Ignorando completamente las claves foráneas hasta que sea necesario ... ¿ solucionó SQL para mí?
¡Si!

¿Y por qué diablos todo esto sucedió en primer lugar?
Bueno, la característica que llamamos claves foráneas se agregó más tarde a SQL; SQL es un estándar que evolucionó con el tiempo, de abajo hacia arriba. Los vendedores implementaron características absurdas, mientras que los cuerpos estándar se pusieron en la cara.

Las claves foráneas, como se dijo, solo estaban destinadas a la indexación y no había una construcción JOIN disponible. (las uniones donde se realizan con SELECTconsultas, las JOINconsultas son bastante recientes y solo están destinadas a la SELECTfuncionalidad de alias ) Probablemente, aunque llamar a ese indicador de indexación FOREIGN KEY, fue un ingenioso truco de nombres sobre conceptos de teoría de base de datos relacional.


13
Con respecto a las claves externas, ¿supongo que solo ha tocado el motor MyISAM en MySQL? Porque incluso sin tener en cuenta esa pequeña queja, cada cosa en esta respuesta está mal.

Los Fk no se usan para indexar, de hecho, un problema común es no tener un índice en la columna fk que pueda tener un impacto dramático en el rendimiento.
jmoreno
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.