¿Debo usar claves principales de varias columnas o agregar una nueva columna?

15

El diseño de mi base de datos actual hace uso de una clave principal de múltiples columnas para usar datos existentes (que de todos modos serían únicos) en lugar de crear una columna adicional que asigne a cada entrada una clave arbitraria. Sé que esto está permitido, pero me preguntaba si esta es una práctica que podría querer usar con precaución y posiblemente evitar (al igual que goto en C).

Entonces, ¿cuáles son algunas de las desventajas que podría ver en este enfoque o las razones por las que podría querer una sola clave de columna?

Covar
fuente
2
No sé, creo que esto habría sido mejor en SO.
FrustratedWithFormsDesigner
2
@FrustratedWithFormsDesigner Podría ir a SO, pero creo que también funciona aquí, ya que el foco de la pregunta parece estar en "cuáles son los pros y los contras de este enfoque" en lugar de "¿cómo hago X?".
Adam Lear
@Anna Lear ♦: Es un "pros y contras" sobre las decisiones de diseño que tendrán un impacto directo y definitivo en la codificación, por lo que creo que SO sería un lugar mejor.
FrustratedWithFormsDesigner

Respuestas:

8

Por lo general, cuando tiene una tabla con una clave primaria de varias columnas, es el resultado de una tabla de unión (muchos a muchos) que se ha elevado para ser su propia entidad (y, por lo tanto, merece su propia clave principal). Hay muchos que argumentan que cualquier tabla de unión DEBE ser una entidad por defecto, pero eso es una discusión para otro día.

Veamos una relación hipotética de muchos a muchos:

Estudiante * --- * Clase

(un estudiante puede estar en varias clases, una clase puede tener varios estudiantes).

Entre esas dos tablas habrá una tabla de unión llamada StudentClass (o ClassStudent dependiendo de cómo la escriba). A veces, desea realizar un seguimiento de cosas como cuando el estudiante estaba en la clase. Entonces lo agregará a la tabla StudentClass. En este punto, StudentClass se ha convertido en una entidad única ... y se le debe dar un nombre para reconocerlo como tal, por ejemplo, inscripción.

Estudiante 1 --- * Matrícula * --- 1 Clase

(un estudiante puede tener muchas Inscripciones, cada Inscripción es para una clase (o en sentido contrario, una Clase puede tener muchas Inscripciones, cada Inscripción es para un Estudiante).

Ahora puede consultar cosas como, ¿cuántos estudiantes se inscribieron en la clase de Química 101 el año pasado? ¿O en qué clases se inscribió el estudiante John Doe mientras asistía a la Universidad de Acme? Esto fue posible sin la clave primaria separada, pero una vez que tenga una clave primaria para la inscripción, una consulta más fácil sería de estas inscripciones (por id), ¿cuántos estudiantes recibieron una calificación aprobatoria?

La determinación de si una entidad merece un PK se reduce a la cantidad de consultas (o manipulación) que hará para esa entidad. Digamos, por ejemplo, que desea adjuntar las tareas completadas para un estudiante en una clase. El lugar lógico para adjuntar esta entidad (Asignación) sería en la entidad de Inscripción. Darle a la inscripción su propia clave principal facilitaría las consultas de Asignación.

Michael Brown
fuente
1
Entonces lo agregará a la tabla StudentClass. En este punto, StudentClass se ha convertido en una entidad única ... y se le debe dar un nombre para reconocerlo como tal, por ejemplo, inscripción. Es algo muy simple, ¡pero hay mucho valor en hacer esto!
Botis
8

Tiene sentido tener una columna de identificación separada. Cuando desea obtener algo de su tabla de base de datos, es más fácil hacer:

SELECT whatever FROM table WHERE id=13

que SELECCIONE lo que sea de la tabla DONDE col1 = 'val1' Y col2 = 'val2' Y col3 = 'val3'

Por ejemplo, en una aplicación web se traduce en una URL que se ve así:

www.somewebsite.com/somepage.php?id=13

o así:

www.somewebsite.com/somepage.php?col1=val1&col2=val2&col3=val3
infrarrojo
fuente
44
Y es mucho más fácil agregar una tabla relacionada cuando se puede vincular en un Id, en lugar de varias columnas
CaffGeek
3
Lo siento, en este punto tengo que -1, ya que A) no es blanco y negro. Agregar una columna de identificación viene con aspectos negativos como dónde y cuándo genera esa nueva identificación. Además, podría dar lugar a uniones o SELECTconsultas adicionales . Y, B) , no tengo idea de cómo esto realmente causa algún tipo de requisito de URL (a menos que esté trabajando con un mal marco). Mis URL no tienen ninguna cadena de consulta ?id=13, y mucho menos ?col1=val1&col2=val2&col3=val3.
Nicole
2
@renesis: este sitio tiene preguntas y usuarios únicos, que se encuentran en las URL. Aunque, este es un caso especial, ya que esos datos particulares no cambian.
Michael K
1
@Renesis, la mayoría de los db modernos (tal vez todos) tienen tipos de columnas enteras de aumento automático que pueden generar los ID de forma automática y segura, y reportarlos a través de consultas SQL o llamadas a funciones de biblioteca. O en un entorno distribuido, utiliza un hash aleatorio grande. Algunos DB incluso crearán una columna de identificación oculta para usted si aún no tiene una en la tabla.
GrandmasterB
@ Michael - No dije que las ID nunca estén en las URL. Por supuesto que lo son. Si tiene URL que representan una fila de datos, entonces sí, esos datos probablemente deberían tener una ID única. A menos que alguna otra parte de la URL ya proporcione las otras partes de la clave múltiple. @GrandmasterB Ninguna de las dos últimas empresas en las que he trabajado (más de 6 años), que usan MySQL (una también admite Oracle y SQL Server) pudieron usar el incremento automático, ni un gran hash aleatorio.
Nicole
8

Básicamente, se pregunta si debe usar teclas sustitutas o naturales (en su caso, suena como teclas naturales compuestas ). Aquí hay un gran artículo: http://www.agiledata.org/essays/keys.html

Prefiero las claves sustitutas porque simplifican la administración durante la vida útil de la base de datos (nunca debe preocuparse por la implicación de que las claves cambien el significado, lo que nunca debería suceder, pero ocurre en cualquier sistema real donde los humanos estén involucrados). Sin embargo , si hay muchas tablas de "búsqueda" en la base de datos (es decir, tablas que son básicamente pares clave: valor), las claves sustitutas pueden volverse engorrosas porque tiene que unir esas tablas en la consulta para obtener resultados significativos.

Por ejemplo, supongamos que tiene dos entidades: Dirección y País.

  • La relación es: Dirección * ----- 1 País
  • La entidad del país es básicamente un par clave: valor (por ejemplo, EE. UU .: Estados Unidos, CA: Canadá, MX: México, etc.)
  • Para consultar esta estructura para todas las direcciones en los Estados Unidos:

select * from Address where CountryCode = 'US'

  • Para realizar la misma consulta con claves sustitutas:

select Address.* from Address join Country on Address.CountryID = Country.ID where Country.Code = 'US'

Me siento cómodo exigiendo claves naturales para tablas de búsqueda y claves sustitutas para todo lo demás, si estoy bastante seguro de que las claves naturales no cambiarán con demasiada frecuencia, si es que alguna vez lo hacen.

Curtis Batt
fuente
5

Depende de cómo acceda a los datos. Si realiza muchas búsquedas de clave parcial (donde selecciona registros basados ​​en digamos solo dos de las tres claves), entonces querrá conservar las claves de varias partes. OTOH, si tiene muchas relaciones 1: 1 con otras tablas, probablemente tenga más sentido tener una clave sustituta.

TMN
fuente
1

Siempre me gusta tener una clave primaria sustituta para cada tabla. Pero no hay muchas razones "difíciles" para hacer cumplir esto que he escuchado.

La única vez que tuve una mordedura de clave natural de varias columnas fue con ORM. Ocasionalmente tendría problemas con una clave principal de múltiples columnas usando Linq To Entities.

Mike M.
fuente
1

Nunca digas nunca, pero unirte en 4 columnas es una molestia. Cuantas más columnas tenga con datos inteligentes, mayores serán las posibilidades de que esos valores cambien. Las bases de datos se pueden configurar para mantener la integridad referencial con actualizaciones en cascada.

Siempre puede crear otro índice para manejar los valores únicos.

El rendimiento es probablemente insignificante en la mayoría de los casos, pero puede probar sus consultas con y sin la clave sustituta.

JeffO
fuente
0

Me resulta difícil encontrar una buena razón para ordenar una clave por separado, pero como dijiste, mucha gente la introdujo.

No encuentro esto de ayuda (especialmente con el almacenamiento) cuando trato con tablas de hechos / detalles. Ejemplo canónico: una tabla de hechos de ventas con una (clave_cliente, clave_tienda, clave_producto) con cantidad no tiene mucho sentido tener una clave de nivel de registro.

Jé Queue
fuente
0

Tener PK como autoincremento int reduce la molestia si encuentra que su clave compuesta puede tener duplicados.

Paul Nathan
fuente
0

Hay una buena discusión desde 2002 sobre Ask Tom . Es específico de Oracle, pero la discusión más amplia es relevante independientemente de la base de datos que esté utilizando.

Rhys Gibson
fuente