2009-12-09 18 views
46

Cuando estudias teoría relacional, las claves externas son, por supuesto, obligatorias. Pero en la práctica, en cada lugar que trabajé, los productos de tabla y las uniones se realizan siempre especificando las claves explícitamente en la consulta, en lugar de confiar en claves externas en el DBMS.¿Por qué las claves externas son más utilizadas en teoría que en la práctica?

De esta forma, podría unir dos tablas por campos que no están destinados a ser claves externas, con resultados inesperados.

¿Por qué crees que es así? ¿No deberían los SGBD exigir que las uniones y productos se realicen solo mediante claves externas?

EDIT: Gracias por todas las respuestas. Ahora me queda claro que la razón principal de FK es la integridad de referencia. Pero si diseña un DB, todas las relaciones en el modelo (flechas I.E. en el ERD) se convierten en claves foráneas, al menos en teoría, ya sea que las defina como tales en su DBMS, semánticamente son FK. No me puedo imaginar la necesidad de unir tablas por campos que no son FK. ¿Alguien puede dar un ejemplo que tenga sentido?

PD: Soy consciente de que las relaciones N: M se convierten en tablas separadas y no en claves externas, simplemente se omite por motivos de simplicidad.

+1

Las reglas de integridad referencial no son una relación de 1 a 1 con lo que debería permitirse para las uniones. Manzanas y naranjas. – Joe

+19

No entiendes para qué se diseñan las claves externas. Unirse a columnas que no son clave es muy útil en el mundo real. – DaveE

+1

community wiki esto! – CheeseConQueso

Respuesta

38

La razón por la que existen restricciones de clave externa es para garantizar que existan las filas a las que se hace referencia.

"La clave externa identifica una columna o un conjunto de columnas en una tabla que hace referencia a una columna o un conjunto de columnas en otra tabla Los valores en una fila de las columnas de referencia deben aparecer en una sola fila en el tabla referenciada

Por lo tanto, una fila en la tabla de referencia no puede contener valores que no existen en la tabla referenciada (excepto potencialmente NULL). De esta manera se pueden hacer referencias para vincular información y es una parte esencial de normalización de la base de datos."(Wikipedia)


RE: Su pregunta: 'No me puedo imaginar la necesidad de unir las tablas de campos que no son FKs':

Al definir una restricción de clave externa, la columna (s) en la tabla de referencia debe ser la clave primaria de la tabla referenciada, o al menos una clave candidata.

al hacer combinaciones, no hay necesidad de unirse con las claves primarias o claves candidatas.

T lo siguiente es un ejemplo que podría tener sentido:

CREATE TABLE clients (
    client_id  uniqueidentifier NOT NULL, 
    client_name  nvarchar(250)  NOT NULL, 
    client_country char(2)   NOT NULL 
); 

CREATE TABLE suppliers (
    supplier_id  uniqueidentifier NOT NULL, 
    supplier_name  nvarchar(250)  NOT NULL, 
    supplier_country char(2)   NOT NULL 
); 

Y entonces se le pregunta de la siguiente manera:

SELECT 
    client_name, supplier_name, client_country 
FROM 
    clients 
INNER JOIN 
    suppliers ON (clients.client_country = suppliers.supplier_country) 
ORDER BY 
    client_country; 

Otro caso en el que estas uniones sentido se encuentra en las bases de datos que ofrecen características geoespaciales, como SQL Server 2008 o Postgres con PostGIS. Usted será capaz de hacer preguntas como éstas:

SELECT 
    state, electorate 
FROM 
    electorates 
INNER JOIN 
    postcodes on (postcodes.Location.STIntersects(electorates.Location) = 1); 

Fuente: ConceptDev - SQL Server 2008 Geography: STIntersects, STArea

Se puede ver otro ejemplo geoespacial similar en la respuesta aceptada para el post "Sql 2008 query problem - which LatLong’s exists in a geography polygon?":

SELECT 
    G.Name, COUNT(CL.Id) 
FROM 
    GeoShapes G 
INNER JOIN 
    CrimeLocations CL ON G.ShapeFile.STIntersects(CL.LatLong) = 1 
GROUP BY 
    G.Name; 

Estos son todas combinaciones válidas de SQL que no tienen nada que ver con claves externas y claves candidatas, y aún pueden ser útiles en la práctica.

+0

Sí, tienes razón. Aunque la referencia del país es de hecho una clave externa a una tabla de países teórica omitida en su ejemplo. – Petruza

+0

Sí teóricamente. Pero en la práctica, es posible que no necesite una tabla para países. En lugar de país, podría haber sido "código postal". –

+5

@Petruza: incluso si el 'client_country' es una clave externa (a la tabla de países), ciertamente no es una clave externa para' supplier_country'. –

8

No, la ejecución es innecesaria; no permitiría alguna funcionalidad útil, como la posible sobrecarga de columnas. Si bien este tipo de uso no es ideal, ES útil en algunas situaciones del mundo real.

El uso apropiado para las restricciones de clave externa es así; una restricción sobre los valores agregados a una columna dada que asegura que sus filas referenciadas existen.

Cabe señalar que una falta significativa de restricciones de clave externa en un esquema dado es un mal "olor" y puede indicar algunos problemas graves de diseño.

34

Las claves externas tienen menos que ver con las uniones que con mantener la integridad de la base de datos. Prueba de ello es que puede unir mesas de la forma que desee, incluso de formas que no necesariamente tienen sentido.

+5

¿Estás diciendo que no debería intentar 'SELECT * FROM book INNER JOIN persona EN book.ISBN = person.Phone'? – Powerlord

+2

Si eso es lo que necesita, hágalo de todos modos. Incluso puede establecer un FK entre book.ISBN y person.Phone si así lo requieren los requisitos de su empresa. –

+0

@ R.Bemrose: Esa consulta es SQL válido, aunque ¿tiene sentido? ¿es útil para un sistema? Creo que no deberías intentar eso. – Petruza

2

Los DBMS están diseñados para permitir la mayor cantidad de soluciones sin dejar de funcionar de acuerdo con sus reglas básicas.

Restringir las uniones a claves externas definidas limitaría la funcionalidad enormemente, especialmente porque la mayoría del desarrollo no ocurre con un DBA dedicado o una revisión de SQL/procedimientos almacenados.

Dicho esto, dependiendo de su capa de acceso a datos, es posible que se le solicite que configure las claves externas para usar la funcionalidad. Por ejemplo, Linq a SQL.

3

Las claves foráneas que se utilizan de la manera que se describe no son cómo se deben usar. Pretenden asegurarse de que si un registro lógicamente depende de un registro correspondiente existe en otro lugar, ese registro correspondiente está realmente allí.

Creo que si los desarrolladores/dbas tienen tiempo para (A) buenos nombres de desarrollador para sus tablas y campos, o (B) definir restricciones extensas de clave externa, la opción A es la opción más fácil. He trabajado en ambas situaciones. Donde se dependía de grandes restricciones para mantener el orden y evitar que la gente arruinara las cosas, realmente puede convertirse en un desastre.

Hace falta un gran esfuerzo para mantener todas sus restricciones de clave externa actualizadas durante el desarrollo, tiempo que podría dedicar a otras tareas de alto valor para las que apenas tiene tiempo. Por el contrario, en situaciones en las que tiene buenas convenciones de nomenclatura, las claves externas son instantáneamente claras. Los desarrolladores no tienen que buscar claves externas, o intentar una consulta para ver si funciona; ellos solo pueden ver las relaciones.

Creo que las restricciones de claves externas se vuelven útiles rápidamente a medida que crece la cantidad de equipos diferentes que usan una base de datos. Se hace difícil imponer nombres consistentes; el conocimiento del DB se fragmenta; es fácil para las acciones de DB tener consecuencias imprevistas para otro equipo.

+2

Pero sin restricciones, nunca puede estar seguro de que los datos satisfagan la integridad referencial, por lo que debe perder tiempo ejecutando consultas para buscar duplicados o huérfanos. –

+1

Sí, esa es la ventaja que las restricciones le otorgan. (1) Como con cualquier buena práctica, evalúe qué tan importante es en una situación particular. (2) Equilibre el ROI de hacer esta buena práctica en comparación con los demás, con tiempo limitado. (3) Considere si la buena práctica en cuestión, a pesar de las ventajas que trae, puede ser una ** muleta ** que permita a los desarrolladores pensar que pueden ** evitar ** otras buenas prácticas, que en realidad podrían ser más importantes. En múltiples instancias, he visto un buen diseño de DB/nomenclatura que ocupa el segundo lugar en cuanto a las restricciones. Desastre. El reverso, generalmente no tan malo. –

6

Puede unir cualquier expresión. Ya sea que defina claves externas en su base de datos o no es inmaterial. Las claves foráneas restringen INSERT/UPDATE/DELETE, no SELECT.

Entonces, ¿por qué muchos proyectos omiten la definición de claves externas?Hay varias razones:

  • El modelo de datos está diseñado mal y requiere referencias rotas (ejemplos: asociaciones polimórficas, EAV).

  • Los codificadores pueden haber escuchado que "las claves externas son lentas" por lo que las sueltan. De hecho, el trabajo extra que tiene que hacer para garantizar la coherencia de los datos cuando no puede confiar en claves externas hace que su aplicación sea mucho menos eficiente. La optimización prematura sin medir realmente el beneficio es un problema común.

  • Las restricciones se interponen en el camino de algunas tareas de limpieza de datos. Algunas veces necesita romper referencias temporalmente mientras refactoriza datos. Muchos RDBMS permiten que las restricciones se deshabiliten, pero a veces los programadores deciden que es más fácil dejarlas deshabilitadas. Si hay una necesidad frecuente de deshabilitar las restricciones, esto probablemente indica un diseño de base de datos seriamente roto.

+1

hay algunas optimizaciones que el motor de consultas puede realizar si sabe que existen ciertas restricciones y en las que se puede confiar, por lo que una restricción (clave externa, verificación) también puede afectar a los SELECT. Por ejemplo (SQL Server específico) http://sqlblog.com/blogs/hugo_kornelis/archive/2007/03/29/can-you-trust-your-constraints.aspx –

+0

@Remus: Gracias, esa es una buena información sobre la optimización. Pero lo que quise decir es que no está * prohibido * unirse a columnas sin una relación de clave externa. –

+0

'@Bill Karwin': en realidad,' FOREING KEY's son lentos en 'Oracle' al menos a partir de' 10g' (debido a la forma en que se implementan). Si utiliza un procedimiento almacenado como punto de entrada único para sus tablas y establece todas las comprobaciones antes de emitir operaciones 'DML', esto es mucho más rápido en' Oracle'. 'SQL Server', por otro lado, optimiza' FOREING KEY'-implied 'DML'. – Quassnoi

3

Debido a que en la práctica, la teoría no es suficiente;)

En serio, en mi experiencia es principalmente porque la teoría no es lo suficientemente flexible como para considerar todas las posibilidades que hay que manejar en el mundo real. Solo con un caso extremadamente extraño que debe almacenar en su base de datos (o algo más común, como sobrecargar columnas), debe sacar el FK e implementarlo en el DAL.

Puede ser que usted pueda desarrollar alguna solución que se pueda archivar de una manera totalmente normalizada (por ejemplo), pero en muchos casos el trabajo necesario y/o los resultados finales no son suficientes.

Mis dos centavos.

2

Las claves foráneas no se usan con la frecuencia que sugiere la teoría relacional porque las personas de tipo DB/relacional no escriben gran parte del código ni siquiera diseñan las tablas. Los programadores escriben el código/tablas de diseño o tienen mucha influencia sobre cómo se diseñan las tablas.

+2

Un profesional de TI debe conocer la teoría relacional Y la programación, ser un programador no debe ser una excusa para ser un diseñador de base de datos pésimo. – Petruza

2

¿En qué tipo de aplicaciones de base de datos trabaja? La teoría que ve con frecuencia se trata de usar la base de datos en bruto, en cuyo caso las restricciones pueden ser muy útiles. En la práctica, las bases de datos se utilizan a menudo como el back-end de aplicaciones más grandes. En muchos casos, estas aplicaciones tienen que validar transacciones por sí mismas, y sería un esfuerzo desperdiciado repetirlas en la base de datos.

Considere una aplicación de ventas, por ejemplo. Cuando alguien ingresa un pedido, tal vez busque al cliente en la base de datos para obtener la dirección o la información de la tarjeta de crédito. Cuando no encuentra un cliente, será programado para hacer algo razonable. Si esperaba hasta que intentara insertar una fila en la tabla de pedidos para descubrir que no había un cliente, recibiría comentarios más lentos y menos convenientes.

Algo tiene que mantener la integridad de la base de datos, pero hacerlo dentro del mismo DBMS no siempre es la mejor manera.

-1

No conozco un dialecto SQL que se una automáticamente a todas las tablas de claves foráneas implícitamente. He visto herramientas de generación de código y diccionario de datos para generar informes de inferirlas, pero el SQL siempre es explícito.

Es por eso que está viendo que, en la práctica, en SQL, TODAS las uniones son explícitas.

En la práctica, las bases de datos sin restricciones FK tienden a tener problemas de integridad, ya que no hay ninguna restricción para exigir que la clave exista.Por lo tanto, es una buena práctica tener tantas restricciones como sea posible: protege la integridad y ayuda al optimizador y a otros usuarios. Al igual que con cualquier práctica recomendada, saber cuándo (si alguna vez) se rompe la regla también es importante.

En cuanto a por qué puede hacer una combinación que no concuerde con una restricción de clave externa entre esas tablas, hay innumerables ejemplos. Particularmente en el caso de las claves compuestas con combinaciones parciales, creo que esto a menudo es necesario. A menudo nos unimos a tablas que utilizan versiones parciales de sus claves principales en el almacenamiento de datos.

También le puede interesar this article sobre eliminación de unión de clave externa por el optimizador.

+0

Sí, sé que todos los productos y combinaciones son explícitos, mi inglés es limitado, lo que quise decir es que los campos utilizados para las uniones no tienen distinción de otros campos, como ser un FK, solo sus nombres (con suerte) se parecen a su significado. – Petruza

+0

Una columna es una columna es una columna. Nombrar es básicamente una preferencia del usuario. Las restricciones son lo que define la base de datos en los metadatos. A menudo hay toneladas de cosas no especificadas en restricciones que son simplemente "conocidas", pero no explícitas. p.ej. "Nunca hay transacciones con valor negativo en una determinada combinación de código GL/centro de costo". Muchas combinaciones de claves no foráneas se incluyen en estas categorías. –

1

Las claves foráneas son extremadamente importantes, especialmente en las bases de datos que tienen consultas manuales que se ejecutan sobre ellas, o que tienen un software desarrollado activamente para ellas. Cada consulta no probada que se ejecuta en la base de datos tiene la posibilidad de contener un error. Las restricciones, como las claves externas, sirven para resaltar estos errores antes de que se introduzca la inconsistencia en los datos.

Estas restricciones son aplicadas por el diseñador del esquema, y ​​aseguran que los datos permanezcan en el modelo que concibió. Si las restricciones no están ahí, tarde o temprano una consulta presentará alguna incoherencia. La inconsistencia dará lugar a resultados impredecibles de las consultas, y es muy difícil de revertir.

0

Buena pregunta. Siempre me he preguntado por qué SQL no tiene una sintaxis como

SELECT tbl1.col1, tbl2.col2 
    FROM tbl1 
    JOIN tbl2 USING(FK_tbl1_tbl2) 

donde FK_tbl1_tbl2 alguna restricción de clave externa entre las tablas. Esto sería mucho más útil que NATURAL JOIN o Oracle's USING (col1, col2).

10

No puedo imaginar la necesidad de unir tablas por campos que no son FK. ¿Alguien puede dar un ejemplo que tenga sentido?

FOREIGN KEY s sólo pueden ser utilizados para hacer cumplir la integridad referencial si la relación entre las entidades del modelo ER se refleja con un equijoin entre dos relaciones en el modelo relacional.

Esto no siempre es cierto.

He aquí un ejemplo del artículo en mi blog que escribí hace algún tiempo:

Este modelo describe productos y precios:

Y aquí está la implementación relacional del modelo:

CREATE TABLE Goods (ID, Name, Price) 
CREATE TABLE PriceRange (Price, Bonus) 

Como se puede ver, la tabla PriceRange tiene sólo un atributo relacionado con los precios, Price, pero el modelo tiene dos atributos: StartPrice y EndPrice.

Esto se debe a que el modelo relacional permite transformar los conjuntos y la entidad PriceRange se puede reconstruir fácilmente utilizando las operaciones SQL.

Goods 
ID Name    Price 
1 Wormy apple  0.09 
2 Bangkok durian  9.99 
3 Densuke watermelon 999.99 
4 White truffle  99999.99 

PriceRange 
Price Bonus 
0.01  1% 
1.00  3% 
100.00 10% 
10000.00 30% 

Almacenamos solamente el límite inferior de cada rango. El límite superior se puede deducir fácilmente.

Aquí está la consulta para encontrar el bono para cada bien:

SELECT * 
FROM Goods 
JOIN PriceRange 
ON  PriceRange.Price = 
     (
     SELECT MAX(Price) 
     FROM PriceRange 
     WHERE PriceRange.Price <= Goods.Price 
     ) 

Vemos que éstas modelo relacional implementa el modelo ER bastante bien, pero sin clave externa puede ser declarado entre estas relaciones, ya que la operación utilizó atarlos no es una equijoin.

0

La razón principal es que no hay manera de ponerlos en marcha sin una consulta en la mayoría de las herramientas visuales de MySQL (Navicat, MySQL, etc.)

suena estúpido, pero yo soy culpable de esto también desde que Don 't tiene la sintaxis memorizado:/

0

Parte de ello es que para mí (y sí, esto es una excusa poco convincente) la interfaz de usuario en SQL Server Management Studio de MS para añadir claves externas es horrible .

Una clave externa es una restricción de que "cualquier valor en la columna x de la tabla a debe aparecer en la columna y en la tabla b", pero la interfaz de usuario para especificarlo en SSMS no indica claramente con qué tabla está jugando , que es la tabla principal, que es la tabla secundaria, y así sucesivamente.

Cada vez que he tenido que crear una clave externa, ha sido de prueba y error hasta que pareció funcionar.

2

He estado programando durante un par de décadas, desde mucho antes de que las bases de datos relacionales se convirtieran en la norma. Cuando comencé a trabajar con MySQL cuando aprendí PHP, vi la opción Foreign Key y el primer pensamiento fue "Wow! Eso es retardado". La razón es que solo un tonto cree que el laboratorio dicta la realidad. Era obvio de inmediato que, a menos que estuviera codificando una aplicación que nunca, alguna vez, se cambiaría, está envolviendo su aplicación en un molde de acero donde la única opción es construir más tablas o encontrar soluciones creativas.

Esta evaluación inicial nació en todas las aplicaciones de producción reales que he encontrado. La restricción no solo ralentiza significativamente todas y cada una de las modificaciones, sino que hace casi imposible el crecimiento de la aplicación, algo que se requiere para una empresa.

La única razón que he encontrado para cualquier restricción en la tabla son los codificadores perezosos. No está dispuesto a escribir código limpio para verificar la integridad de los datos.

Michael

-1

Clave externa es acoplamiento. En la programación, el acoplamiento raramente es bueno.

Cuestiones relacionadas