¿Por qué cambiaría un valor clave principal?

18

He estado investigando el concepto de ROWGUID recientemente y me encontré con esta pregunta. Esta respuesta me dio una idea, pero me ha llevado a un agujero de conejo diferente con la mención de cambiar el valor de la clave primaria.

Siempre he entendido que una clave principal debe ser inmutable, y mi búsqueda desde que leí esta respuesta solo ha proporcionado respuestas que reflejan lo mismo que una mejor práctica.

¿En qué circunstancias necesitaría modificarse un valor de clave principal después de crear el registro?

5 lleno
fuente
77
Cuando se elige una clave primaria que no es inmutable?
ypercubeᵀᴹ
2
Solo un pequeño detalle para todas las respuestas a continuación hasta ahora. Cambiar un valor en la clave primaria no es tan importante a menos que la clave primaria también sea el índice agrupado. Solo importa si los valores del índice agrupado cambian.
Kenneth Fisher
66
@KennethFisher o si hace referencia a uno (o muchos) FK en otra o la misma tabla y un cambio tiene que conectarse en cascada a muchas (posiblemente millones o miles de millones) de filas.
ypercubeᵀᴹ
99
Pregunta Skype. Cuando me registré hace varios años, escribí mi nombre de usuario incorrectamente (dejé una letra de mi apellido). Intenté corregirlo muchas veces, pero no pudieron cambiarlo porque se usó para la clave principal y no admitían cambiarlo. Esa es una instancia en la que el cliente desea que se cambie la clave principal, pero Skype no lo admitió. Ellos podrían apoyar ese cambio si querían (o podrían crear un mejor diseño), pero no hay nada actualmente en marcha para permitirlo. Entonces mi nombre de usuario sigue siendo incorrecto.
Aaron Bertrand
3
Todos los valores del mundo real pueden cambiar (por una variedad de causas). Esta fue una de las motivaciones originales para las claves sustitutas / sintéticas: poder generar valores artificiales en los que se pueda confiar para que nunca cambien.
RBarryYoung

Respuestas:

24

Si estaba usando el nombre de una persona como clave principal y su nombre cambió, necesitaría cambiar la clave primaria. Esto es para lo que ON UPDATE CASCADEse usa, ya que esencialmente conecta el cambio a todas las tablas relacionadas que tienen relaciones de clave externa con la clave primaria.

Por ejemplo:

USE tempdb;
GO

CREATE TABLE dbo.People
(
    PersonKey VARCHAR(200) NOT NULL
        CONSTRAINT PK_People
        PRIMARY KEY CLUSTERED
    , BirthDate DATE NULL
) ON [PRIMARY];

CREATE TABLE dbo.PeopleAKA
(
    PersonAKAKey VARCHAR(200) NOT NULL
        CONSTRAINT PK_PeopleAKA
        PRIMARY KEY CLUSTERED
    , PersonKey VARCHAR(200) NOT NULL
        CONSTRAINT FK_PeopleAKA_People
        FOREIGN KEY REFERENCES dbo.People(PersonKey)
        ON UPDATE CASCADE
) ON [PRIMARY];

INSERT INTO dbo.People(PersonKey, BirthDate)
VALUES ('Joe Black', '1776-01-01');

INSERT INTO dbo.PeopleAKA(PersonAKAKey, PersonKey)
VALUES ('Death', 'Joe Black');

A SELECTcontra ambas tablas:

SELECT *
FROM dbo.People p
    INNER JOIN dbo.PeopleAKA pa ON p.PersonKey = pa.PersonKey;

Devoluciones:

ingrese la descripción de la imagen aquí

Si actualizamos la PersonKeycolumna y volvemos a ejecutar el SELECT:

UPDATE dbo.People
SET PersonKey = 'Mr Joe Black'
WHERE PersonKey = 'Joe Black';

SELECT *
FROM dbo.People p
    INNER JOIN dbo.PeopleAKA pa ON p.PersonKey = pa.PersonKey;

vemos:

ingrese la descripción de la imagen aquí

Al UPDATEobservar el plan para la declaración anterior , vemos claramente que ambas tablas se actualizan mediante una sola declaración de actualización en virtud de la clave externa definida como ON UPDATE CASCADE:

ingrese la descripción de la imagen aquí haga clic en la imagen de arriba para verla con mayor claridad

Finalmente, limpiaremos nuestras tablas temporales:

DROP TABLE dbo.PeopleAKA;
DROP TABLE dbo.People;

La 1 forma preferida de hacer esto usando claves sustitutas sería:

USE tempdb;
GO

CREATE TABLE dbo.People
(
    PersonID INT NOT NULL IDENTITY(1,1)
        CONSTRAINT PK_People
        PRIMARY KEY CLUSTERED
    , PersonName VARCHAR(200) NOT NULL
    , BirthDate DATE NULL
) ON [PRIMARY];

CREATE TABLE dbo.PeopleAKA
(
    PersonAKAID INT NOT NULL IDENTITY(1,1)
        CONSTRAINT PK_PeopleAKA
        PRIMARY KEY CLUSTERED
    , PersonAKAName VARCHAR(200) NOT NULL
    , PersonID INT NOT NULL
        CONSTRAINT FK_PeopleAKA_People
        FOREIGN KEY REFERENCES dbo.People(PersonID)
        ON UPDATE CASCADE
) ON [PRIMARY];

INSERT INTO dbo.People(PersonName, BirthDate)
VALUES ('Joe Black', '1776-01-01');

INSERT INTO dbo.PeopleAKA(PersonID, PersonAKAName)
VALUES (1, 'Death');

SELECT *
FROM dbo.People p
    INNER JOIN dbo.PeopleAKA pa ON p.PersonID = pa.PersonID;

UPDATE dbo.People
SET PersonName = 'Mr Joe Black'
WHERE PersonID = 1;

Para completar, el plan para la declaración de actualización es muy simple y muestra una ventaja para sustituir claves, es decir, solo se necesita actualizar una sola fila en lugar de cada fila que contiene la clave en un escenario de clave natural:

ingrese la descripción de la imagen aquí

SELECT *
FROM dbo.People p
    INNER JOIN dbo.PeopleAKA pa ON p.PersonID = pa.PersonID;

DROP TABLE dbo.PeopleAKA;
DROP TABLE dbo.People;

Los resultados de las dos SELECTdeclaraciones anteriores son:

ingrese la descripción de la imagen aquí

Esencialmente, el resultado es aproximadamente el mismo. Una diferencia importante es que la clave natural amplia no se repite en todas las tablas donde se produce la clave externa. En mi ejemplo, estoy usando una VARCHAR(200)columna para contener el nombre de la persona, lo que requiere usar un en VARCHAR(200) todas partes . Si hay muchas filas y muchas tablas que contienen la clave foránea, eso agregará mucha memoria desperdiciada. Tenga en cuenta que no estoy hablando de que se desperdicie espacio en disco, ya que la mayoría de las personas dicen que el espacio en disco es tan barato como para ser esencialmente libre. La memoria, sin embargo, es costosa y merece ser apreciada. El uso de un entero de 4 bytes para la clave ahorrará una gran cantidad de memoria si considera la longitud promedio del nombre de alrededor de 15 caracteres.

Tangencial a la pregunta sobre cómo y por qué las claves pueden cambiar es la pregunta sobre por qué elegir claves naturales en lugar de claves sustitutas, que es una pregunta interesante y quizás más importante, especialmente cuando el rendimiento es un objetivo de diseño. Vea mi pregunta aquí sobre eso.


1 - http://weblogs.sqlteam.com/mladenp/archive/2009/10/06/Why-I-prefer-surrogate-keys-instead-of-natural-keys-in.aspx

Max Vernon
fuente
3
Para evitar CASCADE (que tiene problemas en ciertos escenarios) también puede hacer que las columnas FK sean anulables, por lo que si necesita cambiar el PK, puede actualizar las filas relacionadas a NULL (en fragmentos, si hay mucho, o por tabla , si hay muchas tablas, o ambas), y luego cambie el valor PK, y luego cambie los FK nuevamente.
Aaron Bertrand
8

Si bien puede usar una clave que es natural y / o mutable como su PK, en mi experiencia eso genera problemas, que a menudo se pueden evitar mediante el uso de un PK que cumpla estas condiciones:

 Guaranteed Unique, Always Exists, Immutable, and Concise.

Por ejemplo, muchas compañías en los EE. UU. Intentan usar los números de la Seguridad Social como números de identificación personal (y PK) en sus sistemas. Luego se topan con los siguientes problemas: errores de entrada de datos que conducen a múltiples registros que deben repararse, personas que no tienen un SSN, personas cuyo SSN ha sido cambiado por el gobierno, personas que tienen SSN duplicados.

He visto cada uno de esos escenarios. También he visto compañías que no querían que sus clientes fueran "solo un número", lo que significaba que su PK terminó siendo 'primero + medio + último + DOB + zip' o alguna tontería similar. Si bien agregaron suficientes campos para casi garantizar la unicidad, sus consultas fueron horrendas, y actualizar cualquiera de esos campos significó perseguir problemas de consistencia de datos.

En mi experiencia, un PK generado por la base de datos es casi siempre una mejor solución.

Recomiendo este artículo para sugerencias adicionales: http://www.agiledata.org/essays/keys.html

Byron Jones
fuente
66
Un buen consejo del artículo de Scott Ambler al que se hace referencia en su respuesta: "Algunas personas le dirán que siempre debe usar claves naturales y otras le dirán que siempre debe usar claves sustitutivas. Estas personas siempre demuestran estar equivocadas, por lo general están haciendo poco más que compartir los prejuicios de su "religión de datos" con usted. La realidad es que las claves naturales y sustitutas tienen sus ventajas y desventajas, y que ninguna estrategia es perfecta para todas las situaciones ".
nvogel
7

La clave primaria podría ser alterada cuando la sincronización está involucrada. Este podría ser el caso cuando tiene un cliente desconectado y sincroniza los datos con el servidor a ciertos intervalos.

Hace unos años, trabajé en un sistema donde todos los datos de eventos en la máquina local tenían ID de fila negativos, como -1, -2, etc. Cuando los datos se sincronizaron con el servidor, se aplicó el ID de fila en el servidor. cliente. Digamos que el ID de la siguiente fila en el servidor era 58. Entonces -1 se convertiría en 58, -2 59 y así sucesivamente. Ese cambio de ID de fila se conectaría en cascada a todos los registros FK secundarios en la máquina local. El mecanismo también se utilizó para determinar qué registros se sincronizaron previamente.

No estoy diciendo que este fue un buen diseño, pero es un ejemplo de la clave principal que cambia con el tiempo.

Jon Raynor
fuente
5

Cualquier diseño que implique cambiarlo PRIMARY KEYregularmente es una receta para el desastre. La única buena razón para cambiarlo sería una fusión de dos bases de datos previamente separadas.

Como lo señaló @MaxVernon, pueden ocurrir cambios ocasionales; luego ON UPDATE CASCADE, use , aunque la mayoría de los sistemas hoy en día usan una ID como sustituto PRIMARY KEY.

Los puristas como Joe Celko y Fabian Pascal (un sitio que vale la pena seguir) no están de acuerdo con el uso de claves sustitutas, pero creo que han perdido esta batalla en particular.

Vérace
fuente
3

La estabilidad es una propiedad deseable para una clave, pero es una cosa relativa y no una regla absoluta. En la práctica, a menudo es útil cambiar los valores de las claves. En términos relacionales, los datos son identificables solo por sus (super) claves. Se deduce que si solo hay una clave en una tabla dada, entonces la distinción entre A) cambiar un valor clave, o B) reemplazar el conjunto de filas en una tabla con un conjunto similar o diferente de filas que contienen otros valores clave, es esencialmente un problema de semántica en lugar de lógica.

Un ejemplo más interesante es el caso de una tabla que tiene varias claves donde los valores de una o más de esas claves podrían tener que cambiar en relación con otros valores clave. Tome el ejemplo de una tabla de empleados con dos claves: Nombre de inicio de sesión y Número de insignia. Aquí hay una fila de muestra de esa tabla:

+---------+--------+
|LoginName|BadgeNum|
+---------+--------+
|ZoeS     |47832   |
+---------+--------+

Si ZoeS pierde su insignia, entonces tal vez se le asigne una nueva y obtenga un nuevo número de insignia:

+---------+--------+
|LoginName|BadgeNum|
+---------+--------+
|ZoeS     |50282   |
+---------+--------+

Más tarde, ella podría decidir cambiar su nombre de usuario:

+---------+--------+
|LoginName|BadgeNum|
+---------+--------+
|ZSmith   |50282   |
+---------+--------+

Ambos valores clave cambiaron, en relación uno con el otro. Tenga en cuenta que no necesariamente hace ninguna diferencia cuál se considera "primario".

En la práctica, la "inmutabilidad", es decir, que nunca cambia un valor, es inalcanzable o al menos imposible de verificar. En la medida en que el cambio haga alguna diferencia, el curso más seguro es asumir que cualquier clave (o cualquier atributo) podría necesitar cambiar.

nvogel
fuente
Rechacé su comentario debido a la siguiente declaración: "En la práctica, la" inmutabilidad ", es decir, nunca cambiar un valor, es inalcanzable o al menos imposible de verificar". La inmutabilidad ES posible, y es una de las razones más importantes para usar claves sustitutas.
Byron Jones
3
¿Cómo puede saber que alguien no cambiará un valor clave la próxima semana o dentro de 10 años? Puede suponer que no lo harán, pero no puede evitar de manera realista que eso suceda (si usted está a cargo, podría poner barreras para mantener a todos los demás a perpetuidad, supongo, pero eso parece un caso marginal). Lo que realmente importa es que los cambios son muy poco frecuentes, no es que nunca sucedan.
nvogel
3

Curiosamente, la pregunta vinculada sobre ROWGUID proporciona su propio caso de uso: cuando tiene claves primarias en conflicto en bases de datos que deben sincronizarse. Si tiene dos bases de datos que deben conciliarse y usan secuencias para las claves principales, querrá que cambie una de las claves para que siga siendo única.

En un mundo ideal, esto nunca sucedería. Para empezar, usaría GUID para las claves principales. Sin embargo, de manera realista, es posible que ni siquiera tenga una base de datos distribuida cuando comience a diseñar, y convertirla en GUID puede haber sido un esfuerzo que se priorizó a continuación para que se distribuya porque se consideró que tenía un mayor impacto que implementar la actualización clave. Esto podría suceder si tiene una base de código grande que depende de claves enteras y requeriría una revisión importante para convertir a GUID. También existe el hecho de que los GUID dispersos (GUID que no están muy cerca uno del otro, lo que sucede si los genera aleatoriamente como debería) también pueden causar problemas para ciertos tipos de índices, lo que significa que quiere evitar el uso ellos como claves principales (mencionado por Byron Jones ).

jpmc26
fuente
0

Un escenario posible es digamos que tiene afiliados que tienen una identificación única y sabe que no se duplicarán entre los afiliados, ya que tienen un carácter inicial único. Los afiliados cargan datos en una tabla maestra. Allí se procesan los registros y luego se les asigna una ID maestra. Los usuarios necesitan acceso a los registros tan pronto como se cargan, incluso si aún no se han procesado. Desea que la ID maestra se base en el pedido procesado y no siempre procesará en el orden en que se cargaron los registros. Sé un poco fabricado.

paparazzo
fuente
-1

Imagine una situación en la que alguien elige el Número de seguro nacional (NIN) como clave principal y de alguna manera un operador inserta una fila con el NIN incorrecto. Después de insertar el valor, hay dos formas de corregir el error:

  1. Elimine el registro equivocado e inserte uno nuevo
  2. Actualice el valor al correcto y use On Update Cascade si hay una restricción de integridad referencial en esa columna
Behrouz Sameny
fuente