Convención de nomenclatura de clave principal / clave externa [cerrado]

95

En nuestro grupo de desarrollo, tenemos un intenso debate sobre la convención de nomenclatura de claves primarias y externas. Básicamente, hay dos escuelas de pensamiento en nuestro grupo:

1:

Primary Table (Employee)   
Primary Key is called ID

Foreign table (Event)  
Foreign key is called EmployeeID

o

2:

Primary Table (Employee)  
Primary Key is called EmployeeID

Foreign table (Event)  
Foreign key is called EmployeeID

Prefiero no duplicar el nombre de la tabla en ninguna de las columnas (así que prefiero la opción 1 anterior). Conceptualmente, es consistente con muchas de las prácticas recomendadas en otros lenguajes, donde no se usa el nombre del objeto en sus nombres de propiedad. Creo que nombrar la clave externa EmployeeID(o Employee_IDpodría ser mejor) le dice al lector que es la IDcolumna de la EmployeeTabla.

Algunos otros prefieren la opción 2, en la que se nombra la clave principal con el prefijo del nombre de la tabla para que el nombre de la columna sea el mismo en toda la base de datos. Veo ese punto, pero ahora no puede distinguir visualmente una clave primaria de una clave externa.

Además, creo que es redundante tener el nombre de la tabla en el nombre de la columna, porque si piensa en la tabla como una entidad y una columna como una propiedad o atributo de esa entidad, piensa en ella como el atributo de ID del Employee, no el EmployeeIDatributo de un empleado. No voy a preguntarle a mi compañero de trabajo qué es PersonAgeo qué PersonGenderes. Le pregunto cuál es su edad.

Entonces, como dije, es un debate furioso y seguimos y seguimos al respecto. Estoy interesado en obtener nuevas perspectivas.

Jeremy
fuente
1
pregunta duplica esto stackoverflow.com/questions/208580/…
Mike Henke
1
Leí más de 10 preguntas similares y finalmente encontré que las 3 respuestas principales aquí son buenas: stackoverflow.com/a/465146/781695
usuario
Solo una nota al margen: la opción 2 le permitiría una 'unión natural'. Diablos, ¿por qué no hacerlo aún en la opción 1 agregando 'Employee.ID como EmployeeID'. Pero la mejor forma de práctica parece ser 'Unirse' usando 'ON Employee.ID = Event.EmployeeID'.
Leo
En ambas situaciones, tendrá que usar un alias (o 'table_name.column_name') en una o más consultas porque, en ambos casos, está repitiendo nombres de columna.
Please_Dont_Bully_Me_SO_Lords

Respuestas:

52

Realmente no importa. Nunca me he encontrado con un sistema en el que haya una diferencia real entre la opción 1 y la opción 2.

Jeff Atwood tenía un gran artículo hace un tiempo sobre este tema. Básicamente, las personas debaten y discuten con más furia aquellos temas en los que no se puede demostrar que estén equivocados. O desde un ángulo diferente, esos temas que solo se pueden ganar a través del estilo filibustero basados ​​en argumentos de último hombre en pie.

Elija uno y dígales que se concentren en los problemas que realmente afectan su código.

EDITAR: Si desea divertirse, pídales que especifiquen detalladamente por qué su método es superior para las referencias de tablas recursivas.

Russell Steen
fuente
26
+1, por sentido común ... Hay cosas más importantes sobre las que discutir ... Entonces, hazlo a mi manera (opción 2)
Charles Bretana
5
Y, para autorreferenciar DRI, cuando hay más de un FK que autorreferencia al mismo PK, TIENE que violar ambos "estándares", ya que las dos columnas FK no pueden tener el mismo nombre ... por ejemplo, EmployeeTable con EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, etc.etc ...
Charles Bretana
75

Si las dos columnas tienen el mismo nombre en ambas tablas (convención n. ° 2), puede usar la sintaxis USING en SQL para ahorrar algo de escritura y algo de ruido repetitivo:

SELECT name, address, amount
  FROM employees JOIN payroll USING (employee_id)

Otro argumento a favor de la convención n. ° 2 es que es la forma en que se diseñó el modelo relacional .

La importancia de cada columna se transmite parcialmente etiquetándola con el nombre del dominio correspondiente.

Steven Huwig
fuente
4
La sintaxis y la semántica de SQL en realidad dan una pista bastante buena sobre cómo debe usarse. Por ejemplo, USAR sintaxis significa que las columnas con el mismo dominio deben tener el mismo nombre, NULL = NULL -> NULL significa que NULL es "desconocido" en lugar de "no aplicable", y ON UPDATE CASCADE significa que las claves solo deben ser únicas, no inmutables.
Steven Huwig
6
Aún mejor, se permite esto: SELECT name, address, amount FROM employees NATURAL JOIN payroll.
cuando
5
No usaría la combinación natural en el código implementado, porque es más británico en el caso de adiciones de esquema. Pero para las consultas interactivas, es genial.
Steven Huwig
3
+1 pero siempre hay una excepción. Por ejemplo, si tiene dos columnas en la nómina que son claves externas para el empleado (una referencia a la persona a la que se le paga, la segunda al gerente con autoridad presupuestaria, por ejemplo). Pero no podemos nombrar ambas claves externas employee_id.
Bill Karwin
1
La palabra clave "using" es específica de MySql. No funciona en T-SQL, desafortunadamente.
birdus
12

Creo que depende de cómo esté preparada la solicitud. Si usa ORM o diseña sus tablas para representar objetos, la opción 1 puede ser para usted.

Me gusta codificar la base de datos como su propia capa. Yo controlo todo y la aplicación solo llama a los procedimientos almacenados. Es bueno tener conjuntos de resultados con nombres de columna completos, especialmente cuando hay muchas tablas unidas y muchas columnas devueltas. Con este tipo de aplicación, me gusta la opción 2. Realmente me gusta ver que los nombres de las columnas coincidan en las combinaciones. Trabajé en sistemas antiguos en los que no coincidían y fue una pesadilla,

KM.
fuente
4
+1 por tener que averiguar las uniones con nombres de columna que no coinciden
Raj More
4
en los "sistemas antiguos", la desventaja de los nombres de 8 caracteres que duele mucho más que esto. Estoy dispuesto a arriesgarme y especular que tener la ID con nombre PK no fue la causa principal de la pesadilla en los sistemas antiguos con los que estaba tratando. Además, "apestaba en sistemas antiguos" se usa muy a menudo en el desarrollo de software, especialmente en bases de datos. Habitualmente veo personas que justifican cualquier práctica A dada, según la forma en que funcionó en su experiencia en un sistema de base de datos lanzado hace más de 10 años.
Russell Steen
2
Las aplicaciones de vanguardia de hoy en día serán basura en unos pocos años. incluso podría reescribir la interfaz o usar los datos en otra plataforma, pero sus datos (incluidos los nombres de sus columnas) deberán resistir la prueba del tiempo.
KM.
2
Entonces, la gente de hace 20 años debería haber usado de alguna manera nombres de columna que tuvieran sentido hoy, a pesar de que solo tenían 8 caracteres. Los formatos de almacenamiento de datos han cambiado drásticamente en los últimos 20 años y volverán a cambiar en los próximos 20. No hay forma de demostrar que su preferencia resistirá la prueba del tiempo mejor que el otro método mencionado. Los "nombres de columna" pueden ser en sí mismos "basura" para cuando la gente tenga esta discusión dentro de 20 años, ya que nuestra capacidad para almacenar y manipular datos mejora. Las tablas son una construcción humana que representa de manera imperfecta las relaciones de datos ...
Russell Steen
1
Gracias por la respuesta intelectual bien razonada.
Russell Steen
3

Ninguna convención funciona en todos los casos, entonces, ¿por qué tener una? Usa el sentido común...

Por ejemplo, para la tabla de autorreferencia, cuando hay más de una columna FK que hace referencia al PK de la misma tabla, TIENE que violar ambos "estándares", ya que las dos columnas FK no pueden tener el mismo nombre ... , EmployeeTable con EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, ...

Charles Bretana
fuente
1
+1 para la respuesta del objetivo técnico real
DVK
Una respuesta buena y aplicable, pero los argumentos de la respuesta de los demócratas pierden el sentido.
JYelton
3

Estoy de acuerdo en que hay poco para elegir entre ellos. Para mí, una cosa mucho más significativa acerca de cualquiera de los estándares es la parte "estándar".

Si la gente comienza a 'hacer lo suyo', sus nethers deberían colgarlos. EN MI HUMILDE OPINIÓN :)

MatBailie
fuente
3
+1 por reconocer que la consistencia es más importante que tener "razón" (en este caso)
Russell Steen
-1 por intentar aplicar una "consistencia tonta". El viejo proverbio chino dice: "Una coherencia tonta es un duende para las mentes simples".
Charles Bretana
@charles: en un mundo donde diferentes personas mantienen el código de los demás, a menudo cuando el escritor se ha ido y la documentación es obsoleta o inexistente, esto no es una consistencia tonta. Estoy tan contento de no trabajar contigo ...
MatBailie
@Dems, sin intención de ofender, pero esto es una tontería, por dos razones. 1) Hay escenarios comunes, claramente entendidos, en los que CUALQUIER estándar TIENE que ser violado. (vea mi respuesta para ver ejemplos y 2) porque en este tema, al menos, un estándar agregaría muy poco valor, excepto para hacer que las personas a quienes les gustan los estándares se sientan más cómodas ...
Charles Bretana
1
podría argumentar que "ID" es más consistente, porque tan pronto como introduce el idioma inglés "carID" en la tabla "cars" o en la tabla "car". "sheepID" en la tabla "sheep" o "sheeps": las cosas empiezan a volverse inconsistentes. Si se adhiere a "ID" y nombres de tablas singulares, esto no solo es consistente sino que funciona bien con muchos ORM / también requiere menos configuración (por ejemplo, Dapper Contrib)
niico
3

¿Ha considerado lo siguiente?

Primary Table (Employee)   
Primary Key is PK_Employee

Foreign table (Event)  
Foreign key is called FK_Employee
Wouter
fuente
3
No puedo soportar cuando la gente vota en contra y no da una razón. Esta es una respuesta completamente válida, ya sea que sea aceptable para algunos o no, es una pregunta diferente, pero es subjetiva y no requiere un voto negativo.
Jeremy
1
Gracias por señalar esto. También me interesaría conocer las razones por las que no utilizaría este formato. Y estoy bastante seguro de que habrá buenas razones ...
Wouter
Esta es la mejor salida, ya que no tendrá que usar table_name.column_nameen consultas y no tendrá que usar alias para los nombres de las columnas si no tiene nombres repetidos ...
Please_Dont_Bully_Me_SO_Lords
1
Esto podría considerarse una forma de notación húngara. Así que considere los argumentos a favor y en contra.
Fred
2

La convención que usamos donde trabajo es bastante cercana a A, con la excepción de que nombramos tablas en forma plural (es decir, "empleados") y usamos guiones bajos entre el nombre de la tabla y la columna. El beneficio de esto es que para hacer referencia a una columna, es "empleados _ id" o "empleados.id", dependiendo de cómo desee acceder a ella. Si necesita especificar de qué tabla proviene la columna, "employee.employees _ id" definitivamente es redundante.

Jarett Millard
fuente
No he decidido si me gustan los nombres de tablas en plural. Al usar el singular, las consultas parecen leer mejor ("empleado.nombre" en lugar de "empleados.nombre"). Incluso en las combinaciones, parece leer mejor a medida que une registros individuales a otra tabla. Pero los nombres de las tablas en plural parecen más precisos cuando se piensa en la tabla que en la consulta. Me quedaré con el singular, ya que eso es lo que usamos, pero creo que también es el camino correcto a seguir (aunque nuevamente, muchos no están de acuerdo)
MatBailie
Si. Es más una preferencia personal y / o lo que sea que estés acostumbrado a ver, supongo.
Jarett Millard
2

Si está mirando el código de la aplicación, no solo las consultas de la base de datos, algunas cosas me parecen claras:

  1. Las definiciones de tabla generalmente se asignan directamente a una clase que describe un objeto, por lo que deben ser singulares. Para describir una colección de un objeto, generalmente agrego "Matriz" o "Lista" o "Colección" al nombre singular, ya que más claramente que el uso de plurales indica no solo que es una colección, sino qué tipo de colección. es. En esa vista, veo el nombre de una tabla no como el nombre de la colección, sino como el nombre del tipo de objeto del que es una colección. Un DBA que no escribe código de aplicación podría perder este punto.

  2. Los datos que trato a menudo utilizan "ID" para fines de identificación no clave. Para eliminar la confusión entre los "ID" de clave y los "ID" que no son de clave, para el nombre de la clave principal, usamos "Clave" (eso es lo que es, ¿no es así?) Prefijado con el nombre de la tabla o una abreviatura de el nombre de la tabla. Este prefijo (y lo reservo solo para la clave principal) hace que el nombre de la clave sea único, lo cual es especialmente importante porque usamos nombres de variables que son los mismos que los nombres de las columnas de la base de datos, y la mayoría de las clases tienen un padre, identificado por el nombre de la clave principal. Esto también es necesario para asegurarse de que no se trata de una palabra clave reservada, que sólo es "Clave". Para facilitar la coherencia de los nombres de las variables clave y proporcionar programas que realicen uniones naturales, las claves externas tienen el mismo nombre que se utiliza en la tabla en la que son la clave principal. Más de una vez he encontrado programas que funcionan mucho mejor de esta manera usando uniones naturales. Sobre este último punto, admito un problema con las tablas de autorreferencia, que he utilizado. En este caso, haría una excepción a la regla de denominación de claves foráneas. Por ejemplo, usaría ManagerKey como una clave externa en la tabla Empleado para apuntar a otro registro en esa tabla.

Bruce Patin
fuente
Muchos mapeadores relacionales de objetos (ORM), como Entity Framework, le permiten asignar una tabla a una clase con un nombre diferente. Esto le permite tener una clase llamada "Usuario" y una tabla llamada "Usuarios".
Fred
2

Me gusta la convención n. ° 2: al investigar este tema y encontrar esta pregunta antes de publicar la mía, me encontré con el problema donde:

Estoy seleccionando * de una tabla con una gran cantidad de columnas y uniéndolo a una segunda tabla que también tiene una gran cantidad de columnas. Ambas tablas tienen una columna "id" como clave principal, y eso significa que tengo que seleccionar específicamente cada columna (hasta donde yo sé) para que esos dos valores sean únicos en el resultado, es decir:

SELECT table1.id AS parent_id, table2.id AS child_id

Aunque usar la convención n. ° 2 significa que todavía tendré algunas columnas en el resultado con el mismo nombre, ahora puedo especificar qué identificación necesito (padre o hijo) y, como sugirió Steven Huwig, la USINGdeclaración simplifica aún más las cosas.

JYelton
fuente
2
SELECT *es un no-no para (la mayoría) de las consultas de producción, de todos modos, por lo que no es una gran razón para elegir un estándar de nomenclatura.
P Daddy
1
No estoy en desacuerdo: ¿podría proporcionar un enlace a una razón por la que esto es así? No me gusta la idea de tener que mantener los nombres de 80 columnas en mi consulta.
JYelton
No puedo encontrar un vínculo en este momento (es difícil de buscar en Google para "*"), pero describiré los puntos básicos: (1) los cambios en las tablas pueden afectar negativamente su aplicación, (2) puede ser perjudicial para el rendimiento, y (3) especificar explícitamente qué datos realmente necesita puede hacer que su código sea más fácil de entender. Estos puntos podrían expandirse y hay excepciones (como mencioné) pero eso no es apropiado aquí. Si publica esto como una nueva pregunta, yo (y otros) estaría encantado de desarrollar más.
P Daddy
2
Puedo hacer eso. Me doy cuenta del beneficio de rendimiento, pero tengo que considerar la inversión de tiempo al editar el código. Siempre estoy buscando formas de mejorar la interacción entre la aplicación y la base de datos. Gracias.
JYelton
1
No estoy tan seguro de que SELECT *sea ​​un no-no para la mayoría de las consultas de producción. Si aumenta significativamente su velocidad de desarrollo y hace que su código sea mucho más conciso y legible, lo que le permite concentrarse en asuntos más importantes, ¿por qué no SELECT *? Depende en gran medida de las circunstancias de cada situación y es una compensación entre muchos factores. Una regla rara vez se ajusta a todo.
niico
2

Siempre he usado userId como PK en una tabla y userId en otra tabla como FK. Estoy pensando seriamente en usar userIdPK y userIdFK como nombres para identificar uno del otro. Me ayudará a identificar PK y FK rápidamente cuando mire las tablas y parece que borrará el código cuando use PHP / SQL para acceder a los datos, lo que facilita su comprensión. Especialmente cuando alguien más mira mi código.

Ross
fuente
1

Yo uso la convención n. ° 2. Ahora estoy trabajando con un modelo de datos heredado en el que no sé qué significa en una tabla determinada. ¿Dónde está el daño en ser prolijo?

Ponis dios mio
fuente
1

¿Qué tal nombrar la clave externa?

Identificación del rol

donde rol es el rol que la entidad referenciada tiene en relación con la mesa en cuestión. Esto resuelve el problema de la referencia recursiva y múltiples fks a la misma tabla.

En muchos casos será idéntico al nombre de la tabla referenciada. En estos casos se vuelve idéntico a una de sus propuestas.

En cualquier caso, tener largas discusiones es una mala idea.

Jens Schauder
fuente
0

"¿En qué parte de" pedido INNER JOIN del empleado EN order.employee_id = employee.id "hay una necesidad de calificación adicional?".

No hay necesidad de una calificación adicional porque la calificación de la que hablé ya está ahí.

"la razón por la que un usuario empresarial se refiere a la ID de pedido o la ID de empleado es para proporcionar contexto, pero a nivel de base de datos ya tiene contexto porque está haciendo referencia a la tabla".

Por favor, dígame, si la columna se llama 'ID', entonces ¿cómo se hace exactamente esa "referencia [sic] a la tabla", a menos que califique esta referencia a la columna de ID exactamente de la forma en que hablé?


fuente