¿Cuál es la mejor práctica para las claves primarias en las tablas? [cerrado]

Resuelto Lloyd Cotten asked hace 15 años • 21 respuestas

Al diseñar tablas, he desarrollado el hábito de tener una columna que sea única y que sea la clave principal. Esto se logra de tres maneras dependiendo de los requisitos:

  1. Columna de números enteros de identidad que se incrementa automáticamente.
  2. Identificador único (GUID)
  3. Una columna de carácter corto (x) o de número entero (u otro tipo numérico relativamente pequeño) que puede servir como columna de identificador de fila.

El número 3 se usaría para búsquedas bastante pequeñas, en su mayoría tablas de lectura que podrían tener un código de cadena de longitud estática único o un valor numérico como un año u otro número.

En su mayor parte, todas las demás tablas tendrán un número entero que se incrementa automáticamente o una clave primaria de identificador único.

La pregunta :-)

Recientemente comencé a trabajar con bases de datos que no tienen un identificador de fila consistente y las claves primarias actualmente están agrupadas en varias columnas. Algunos ejemplos:

  • fechahora/carácter
  • fechahora/entero
  • fechahora/varchar
  • carbón/nvarchar/nvarchar

¿Existe un caso válido para esto? Siempre habría definido una columna de identidad o identificador único para estos casos.

Además, hay muchas tablas sin claves primarias. ¿Cuáles son las razones válidas, si las hay, para esto?

Estoy tratando de entender por qué las tablas se diseñaron como estaban y me parece un gran desastre, pero tal vez hubo buenas razones para ello.

Una tercera pregunta para ayudarme a descifrar las respuestas: en los casos en los que se utilizan varias columnas para componer la clave primaria compuesta, ¿hay alguna ventaja específica en este método frente a una clave sustituta/artificial? ¿Estoy pensando principalmente en lo que respecta al rendimiento, mantenimiento, administración, etc.?

Lloyd Cotten avatar Dec 03 '08 22:12 Lloyd Cotten
Aceptado

Sigo algunas reglas:

  1. Las claves primarias deben ser tan pequeñas como sea necesario. Prefiera un tipo numérico porque los tipos numéricos se almacenan en un formato mucho más compacto que los formatos de caracteres. Esto se debe a que la mayoría de las claves primarias serán claves externas en otra tabla y también se utilizarán en múltiples índices. Cuanto más pequeña sea su clave, más pequeño será el índice y menos páginas en el caché utilizará.
  2. Las claves primarias nunca deberían cambiar. Actualizar una clave primaria siempre debería estar fuera de discusión. Esto se debe a que es más probable que se utilice en varios índices y como clave externa. La actualización de una única clave primaria podría provocar un efecto dominó de los cambios.
  3. NO utilice "la clave principal de su problema" como clave principal de su modelo lógico. Por ejemplo, el número de pasaporte, el número de seguro social o el número de contrato del empleado, ya que estas "claves naturales" pueden cambiar en situaciones del mundo real. Asegúrese de agregar restricciones ÚNICAS para estos cuando sea necesario para imponer la coherencia.

Sobre la clave sustituta versus la clave natural, me refiero a las reglas anteriores. Si la clave natural es pequeña y nunca cambia, se puede utilizar como clave principal. Si la clave natural es grande o es probable que cambie, utilizo claves sustitutas. Si no hay una clave principal, todavía creo una clave sustituta porque la experiencia muestra que siempre agregará tablas a su esquema y desearía implementar una clave principal.

Logicalmind avatar Dec 03 '2008 19:12 Logicalmind

Claves naturales versus claves artificiales es una especie de debate religioso entre la comunidad de bases de datos; consulte este artículo y otros a los que enlaza. No soy partidario de tener siempre claves artificiales, ni de no tenerlas nunca. Yo decidiría caso por caso, por ejemplo:

  • Estados de EE. UU.: elegiría state_code ('TX' para Texas, etc.), en lugar de state_id=1 para Texas
  • Empleados: normalmente crearía un Employee_id artificial, porque es difícil encontrar algo más que funcione. El SSN o equivalente puede funcionar, pero podría haber problemas como que un nuevo miembro aún no haya proporcionado su SSN.
  • Historial de salarios de los empleados: (employee_id, start_date). No crearía un Employee_salary_history_id artificial. ¿Para qué serviría (aparte de "consistencia tonta" )?

Dondequiera que se utilicen claves artificiales, siempre se deben declarar también restricciones únicas en las claves naturales. Por ejemplo, use state_id si es necesario, pero entonces será mejor que declare una restricción única en state_code; de ​​lo contrario, seguramente terminará con:

state_id    state_code   state_name
137         TX           Texas
...         ...          ...
249         TX           Texas
Tony Andrews avatar Dec 03 '2008 16:12 Tony Andrews

Evito el uso de claves naturales por una sencilla razón: error humano. Aunque los identificadores únicos naturales suelen estar disponibles (SSN, VIN, número de cuenta, etc.), requieren que un humano los ingrese correctamente. Si está utilizando SSN como clave principal, alguien transpone un par de números durante la entrada de datos y el error no se descubre de inmediato, entonces tendrá que cambiar su clave principal.

Todas mis claves principales son manejadas por el programa de base de datos en segundo plano y el usuario nunca las conoce.

Paul avatar Jul 12 '2011 20:07 Paul

Sólo un comentario extra sobre algo que muchas veces se pasa por alto. A veces, no utilizar una única clave sustituta como principal tiene beneficios en las tablas secundarias. Digamos que tenemos un diseño que le permite administrar varias empresas dentro de una base de datos (tal vez sea una solución alojada o lo que sea).

Digamos que tenemos estas tablas y columnas:

Company:
  CompanyId   (primary key)

CostCenter:
  CompanyId   (primary key, foreign key to Company)
  CostCentre  (primary key)

CostElement
  CompanyId   (primary key, foreign key to Company)
  CostElement (primary key)

Invoice:
  InvoiceId    (primary key)
  CompanyId    (primary key, in foreign key to CostCentre, in foreign key to CostElement)
  CostCentre   (in foreign key to CostCentre)
  CostElement  (in foreign key to CostElement)

En caso de que el último bit no tenga sentido, Invoice.CompanyIdes parte de dos claves externas, una para la tabla CostCentre y otra para la tabla CostElement . La clave principal es ( InvoiceId , CompanyId ).

En este modelo, no es posible equivocarse y hacer referencia a un CostElement de una empresa y a un CostCentre de otra empresa. Si se usara una única clave sustituta como principal en las tablas CostElement y CostCentre , y sin las relaciones de clave externa en la tabla Invoice , así sería.

Cuantas menos posibilidades de cometer un error, mejor.

WW. avatar Dec 05 '2008 10:12 WW.