¿Está bien tener una clave externa como clave principal?

102

Tengo dos mesas:

  • Usuario (nombre de usuario, contraseña)
  • Perfil (ID de perfil, sexo, fecha de nacimiento, ...)

Actualmente estoy usando este enfoque: cada registro de perfil tiene un campo llamado "userId" como clave externa que enlaza con la tabla de usuarios. Cuando un usuario se registra, su registro de perfil se crea automáticamente.

Estoy confundido con la sugerencia de mi amigo: tener el campo "userId" como clave externa y primaria y eliminar el campo "profileId". ¿Qué enfoque es mejor?

Duc Tran
fuente
3
Entity Framework genera eso (con el código primero) para las relaciones zeroOrOne (y uno)-a- uno. Entonces ... es posible. ¿Es la mejor forma ...? Ésa es otra cuestión. Pero es válido. Nunca hice eso mientras creaba mis propias bases de datos (pero nunca pensé en eso).
Raphaël Althaus

Respuestas:

132

Las claves externas casi siempre son "Permitir duplicados", lo que las haría inadecuadas como claves primarias.

En su lugar, busque un campo que identifique de forma única cada registro de la tabla o agregue un campo nuevo (ya sea un entero de incremento automático o un GUID) para que actúe como clave principal.

La única excepción a esto son las tablas con una relación de uno a uno , donde la clave externa y la clave principal de la tabla vinculada son una y la misma.

Robert Harvey
fuente
73
Una clave primaria compuesta que consta de dos claves externas también es perfecta para implementar relaciones de muchos a muchos.
Derecha
1
@rezadru: Lejos de mí estar en desacuerdo con rightfold, pero una clave sustituta es casi siempre una mejor opción.
Robert Harvey
4
Nada acerca de una clave externa dicta que sea de 1 a muchos (o "permitir duplicados" como está escrito). Las restricciones clave y la unicidad son dos conceptos separados en una base de datos y se pueden mezclar fácilmente con la misma facilidad que agregar un índice (que sería un tercer concepto separado).
blindguy
40

Las claves primarias siempre deben ser únicas, las claves externas deben permitir valores no únicos si la tabla es una relación de uno a varios. Está perfectamente bien utilizar una clave externa como clave principal si la tabla está conectada mediante una relación uno a uno, no una relación uno a varios. Si desea que el mismo registro de usuario tenga la posibilidad de tener más de 1 registro de perfil relacionado, elija una clave primaria separada; de lo contrario, quédese con lo que tiene.

kotekzot
fuente
11

Sí, es legal que una clave principal sea una clave externa. Esta es una construcción rara, pero se aplica a:

  • una relación 1: 1. Las dos tablas no se pueden fusionar en una debido a los diferentes permisos y los privilegios solo se aplican a nivel de tabla (a partir de 2017, dicha base de datos sería extraña).

  • una relación 1: 0..1. El perfil puede existir o no, según el tipo de usuario.

  • el rendimiento es un problema y el diseño actúa como una partición: rara vez se accede a la tabla de perfiles, se aloja en un disco separado o tiene una política de fragmentación diferente en comparación con la tabla de usuarios. No tendría sentido si el almacenamiento de subrayado es columnar.


fuente
Habría un rendimiento negativo si las tablas se unieran con frecuencia, lo que conduce a la recomendación normal de que 1 tabla es mejor. En algunos casos, siempre se accede a los datos por separado, no unidos, y puede haber beneficios organizativos al tener dos tablas con una relación 1: 1.
blindguy
4

Generalmente se considera una mala práctica tener una relación de uno a uno. Esto se debe a que podría tener los datos representados en una tabla y lograr el mismo resultado.

Sin embargo, hay casos en los que es posible que no pueda realizar estos cambios en la tabla a la que hace referencia. En este caso, no hay ningún problema al utilizar la clave externa como clave principal. Puede ser útil tener una clave compuesta que consista en una clave primaria única de incremento automático y la clave externa.

Actualmente estoy trabajando en un sistema donde los usuarios pueden iniciar sesión y generar un código de registro para usar con una aplicación. Por razones que no voy a entrar, no puedo simplemente agregar las columnas requeridas a la tabla de usuarios. Así que voy por una ruta uno a uno con la tabla de códigos.

Tshsmith
fuente
2
Estoy de acuerdo con usted principalmente en que hay muchas ventajas en tener todos los datos en la misma tabla como columnas adicionales. Aunque wrt this .. "podría tener los datos representados en una tabla y lograr el mismo resultado" ..: tener una tabla separada puede ser útil, por ejemplo aquí si la entrada de la tabla de perfil es opcional. Por ejemplo, es posible que todos los clientes de un banco no tengan un registro de banca por Internet. En ese caso, la tabla de registro del IB podría usarse para restringir que otras tablas tengan más registros secundarios. Nuevamente, aquí también se podría hacer con un nuevo PK para la mesa de registro del IB.
Teddy
1
@Teddy Del mismo modo, estoy mayormente de acuerdo con lo que dijiste. Sin embargo, en la pregunta original dicen "... su registro de perfil se crea automáticamente ...", lo que implica que la tabla de perfil no es opcional. En una situación en la que la tabla de perfiles era opcional, sí, tenerla como una tabla separada es factible. Pero, de nuevo, podrían usar columnas anulables en la misma tabla.
Tshsmith
1
Usando una segunda tabla separada, podemos evitar la entrada en una tercera tabla que solo está permitida para las personas que tienen una entrada en la segunda tabla.
Teddy
Por supuesto, pero si fusionamos las tablas 1 a 1 podemos evitar que las personas con valores nulos accedan a la tercera (técnicamente la segunda ahora) tabla. Pero la pregunta que hizo OP contiene la línea "... al registrarse ... ... su registro de perfil se crea automáticamente ...", lo que hace que esto sea redundante.
Tshsmith
Mi principal razón para considerar esto es que en el almacenamiento de datos, es una buena práctica separar las tablas de hechos y de dimensiones. Las tablas de hechos y dimensiones separadas son pistas útiles cuando se trabaja con software como PowerPivot, PowerBI y Tableau.
Marco Rosas
4

Sí, una clave externa puede ser una clave principal en el caso de una relación uno a uno entre esas tablas

Riaj Ferdous
fuente
2
esto también es útil para el diseño de supertipo-subtipo. La clave principal de las tablas de subtipos debe ser una referencia de clave externa a la tabla de supertipo.
axelioo
2

Yo no haría eso. Mantendría la profileIDclave principal de la tabla.Profile

Una clave externa es solo una restricción referencial entre dos tablas

Se podría argumentar que una clave primaria es necesaria como destino de cualquier clave externa que se refiera a ella desde otras tablas. Una clave externa es un conjunto de una o más columnas en cualquier tabla (no necesariamente una clave candidata, y mucho menos la clave primaria, de esa tabla) que puede contener los valores que se encuentran en la (s) columna (s) de clave primaria de algunos otra mesa. Por lo tanto, debemos tener una clave principal que coincida con la clave externa. ¿O debemos? El único propósito de la clave primaria en el par de clave primaria / clave externa es proporcionar una combinación inequívoca, para mantener la integridad referencial con respecto a la tabla "externa" que contiene la clave primaria referenciada. Esto asegura que el valor al que se refiere la clave externa siempre será válido (o nulo, si se permite).

http://www.aisintl.com/case/primary_and_foreign_key.html

Massimiliano Peluso
fuente
1
Quizás, si tiene la restricción FK entre User.UserID y Profile.UserID, se recomienda encarecidamente tener un índice en Profile.UserID. ¿Por qué no convertirlo en el índice agrupado principal en el perfil de la tabla, ahorrando un segundo índice y una gran cantidad de trabajo innecesario para el motor de la base de datos?
Ingeniero
1

Depende del negocio y del sistema.

Si su userId es único y será único todo el tiempo, puede usar userId como su clave principal. Pero si alguna vez desea expandir su sistema, le resultará difícil. Le aconsejo que agregue una clave externa en el usuario de la tabla para establecer una relación con el perfil de la tabla en lugar de agregar una clave externa en el perfil de la tabla.

Vincent Cai
fuente
0

Respuesta corta: DEPENDE .... En este caso particular, podría estar bien. Sin embargo, los expertos recomendarán no hacerlo casi siempre; incluyendo su caso.

¿Por qué?

Las claves rara vez son únicas en las tablas cuando son ajenas (originadas en otra tabla) a la tabla en cuestión. Por ejemplo, un ID de artículo puede ser único en una tabla ARTÍCULOS, pero no en una tabla PEDIDOS, ya que lo más probable es que el mismo tipo de artículo exista en otro pedido. Del mismo modo, los ID de pedido pueden ser únicos (podrían) en la tabla ORDERS, pero no en alguna otra tabla como ORDER_DETAILS, donde puede existir un pedido con varias líneas de pedido y, para consultar un artículo en particular en un pedido en particular, necesita la concatenación de dos FK (order_id y item_id) como PK para esta tabla.

No soy un experto en DB, pero si puede justificar lógicamente tener un valor generado automáticamente como su PK, lo haría. Si esto no es práctico, entonces una concatenación de dos (o quizás más) FK podría servir como su PK. PERO, no puedo pensar en ningún caso en el que un único valor de FK pueda justificarse como PK.

hfontanez
fuente