¿Puedo tener varias claves principales en una sola tabla?

Respuestas:

559

Una tabla puede tener una clave primaria compuesta, que es una clave primaria hecha de dos o más columnas. Por ejemplo:

CREATE TABLE userdata (
  userid INT,
  userdataid INT,
  info char(200),
  primary key (userid, userdataid)
);

Actualización: Aquí hay un enlace con una descripción más detallada de las claves primarias compuestas.

Adam Pierce
fuente
2
En este ejemplo, AMBOS userid y userdataid son necesarios para identificar / encontrar una fila única. No estoy seguro de cuál era la intención del OP, pero vine aquí para ver si podía identificar de manera única una fila con una de las claves. Por ejemplo, me gustaría identificar a un usuario único con un nombre de usuario O un ID de usuario, sin necesidad de ambos. Supongo que la respuesta de RB de índices únicos haría el truco allí.
Burrito
1
@Benitok Como se menciona en la respuesta de RB. , Puede usar índices únicos para hacer lo que está buscando (una columna indexada única independiente de otras columnas indexadas únicas en la misma tabla). Asegúrese de consultar su versión específica del manual de SQL para obtener detalles sobre la sintaxis de idioma exacta utilizada.
4AM
195

Solo puede tener una clave principal, pero puede tener varias columnas en su clave principal.

También puede tener índices únicos en su tabla, que funcionarán un poco como una clave principal, ya que impondrán valores únicos y acelerarán la consulta de esos valores.

RB.
fuente
39

Una tabla puede tener múltiples claves candidatas. Cada clave candidata es una columna o conjunto de columnas que son ÚNICAS, tomadas juntas, y también NO NULAS. Por lo tanto, especificar valores para todas las columnas de cualquier clave candidata es suficiente para determinar que hay una fila que cumple con los criterios, o ninguna fila.

Las claves candidatas son un concepto fundamental en el modelo de datos relacionales.

Es una práctica común, si hay varias claves presentes en una tabla, designar una de las claves candidatas como clave principal. También es una práctica común hacer que las claves externas de la tabla hagan referencia a la clave primaria, en lugar de cualquier otra clave candidata.

Recomiendo estas prácticas, pero no hay nada en el modelo relacional que requiera seleccionar una clave primaria entre las claves candidatas.

Walter Mitty
fuente
55
Convenido. Todas las claves son iguales (ninguna es 'primaria') en el modelo lógico. La elección de qué clave en la implementación física obtiene la designación PRIMARY KEY depende del arbitraje y depende del proveedor / producto.
cuando el
3
Yo diría que depende del diseñador de la base de datos.
Walter Mitty
Acabo de encontrar un caso de uso donde se requiere. Tengo una tabla que será creada / administrada por Entity Framework, que, por lo que puedo reunir, no admite restricciones compuestas únicas de clave no primaria en la actualidad. Sin embargo, admite claves primarias compuestas. Los datos también se vincularán a un sistema de base de datos remoto que no admite claves compuestas en absoluto. He seguido creando un PK compuesto en EF pero también agregué una columna GUID no anulable que el otro sistema puede usar para identificarse de forma exclusiva.
Chris Nevill
2
Chris, dije que el modelo relacional no requiere claves primarias. No dije nada sobre si alguna herramienta podría requerirlos. Pero entiendo tu punto.
Walter Mitty
Creo que hay un requisito de que el PK sea mínimo, es decir, use el menor número de columnas para identificar de forma única cada registro.
Gary
14

Esta es la respuesta tanto para la pregunta principal como para la pregunta de @ Kalmi de

¿Cuál sería el punto de tener múltiples columnas autogeneradoras?

Este código a continuación tiene una clave primaria compuesta. Una de sus columnas se incrementa automáticamente. Esto solo funcionará en MyISAM. InnoDB generará un error " ERROR 1075 (42000): Definición de tabla incorrecta; solo puede haber una columna automática y debe definirse como una clave ".

DROP TABLE IF EXISTS `test`.`animals`;
CREATE TABLE  `test`.`animals` (
  `grp` char(30) NOT NULL,
  `id` mediumint(9) NOT NULL AUTO_INCREMENT,
  `name` char(30) NOT NULL,
  PRIMARY KEY (`grp`,`id`)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;

Which returns:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+
Ojo
fuente
2
Esto funciona si especifica la columna de incremento automático primero en la definición de clave primaria. (Tal vez esto cambió, solo lo probé en 5.6)
CTarczon
11

(He estado estudiando esto, mucho)

Claves candidatas : se requiere una combinación de columnas mínima para identificar de forma exclusiva una fila de la tabla.
Teclas compuestas : 2 o más columnas.

  • Pueden existir múltiples claves de candidato en una tabla.
    • CLAVE primaria : solo una de las claves candidatas elegida por nosotros
    • Claves alternativas : todas las demás claves candidatas
      • Tanto la clave primaria como las claves alternativas pueden ser claves compuestas

Fuentes:
https://en.wikipedia.org/wiki/Superkey
https://en.wikipedia.org/wiki/Candidate_key
https://en.wikipedia.org/wiki/Primary_key
https://en.wikipedia.org / wiki / Compound_key

Manohar Reddy Poreddy
fuente
6

Como señalaron los demás, es posible tener claves primarias de varias columnas. Sin embargo, debe tenerse en cuenta que si tiene algunas dependencias funcionales que no son introducidas por una clave, debería considerar normalizar su relación.

Ejemplo:

Person(id, name, email, street, zip_code, area)

Puede haber una dependencia funcional entre id -> name,email, street, zip_code and area Pero a menudo zip_codese asocia a a areay por lo tanto hay una dependencia funcional interna entre zip_code -> area.

Por lo tanto, uno puede considerar dividirlo en otra tabla:

Person(id, name, email, street, zip_code)
Area(zip_code, name)

Para que sea consistente con la tercera forma normal .

Otro geek
fuente
6

La clave primaria es una notación muy desafortunada, debido a la connotación de "primaria" y la asociación subconsciente en consecuencia con el modelo lógico. Así evito usarlo. En su lugar, me refiero a la clave sustituta del modelo físico y las claves naturales del modelo lógico.

Es importante que el Modelo Lógico para cada Entidad tenga al menos un conjunto de "atributos comerciales" que comprendan una Clave para la entidad. Boyce, Codd, Date et al se refieren a estos en el Modelo Relacional como Candidate Keys. Cuando creamos tablas para estas Entidades, sus Claves candidatas se convierten en Claves naturales en esas tablas. Es solo a través de esas Claves naturales que los usuarios pueden identificar de forma exclusiva las filas en las tablas; como claves sustitutas siempre deben ocultarse a los usuarios. Esto se debe a que las claves sustitutas no tienen sentido comercial.

Sin embargo, el modelo físico para nuestras tablas en muchos casos será ineficiente sin una clave sustituta. Recuerde que las columnas no cubiertas para un índice no agrupado solo se pueden encontrar (en general) a través de una búsqueda clave en el índice agrupado (ignore las tablas implementadas como montones por un momento). Cuando nuestras Claves naturales disponibles son anchas, esto (1) amplía el ancho de nuestros nodos hoja no agrupados, lo que aumenta los requisitos de almacenamiento y los accesos de lectura para búsquedas y escaneos de ese índice no agrupado; y (2) reduce el despliegue de nuestro índice agrupado aumentando la altura del índice y el tamaño del índice, nuevamente aumentando las lecturas y los requisitos de almacenamiento para nuestros índices agrupados; y (3) aumenta los requisitos de caché para nuestros índices agrupados. persiguiendo otros índices y datos fuera de la memoria caché.

Aquí es donde una pequeña clave sustituta, designada para el RDBMS como "la clave primaria" resulta beneficiosa. Cuando se establece como la clave de agrupación, para usarse para búsquedas de clave en el índice agrupado de índices no agrupados y búsquedas de clave externa de tablas relacionadas, desaparecen todas estas desventajas. Nuestros despliegues de índice agrupado aumentan nuevamente para reducir la altura y el tamaño del índice agrupado, reducir la carga de caché para nuestros índices agrupados, disminuir las lecturas al acceder a los datos a través de cualquier mecanismo (ya sea exploración de índice, búsqueda de índice, búsqueda de clave no agrupada o búsqueda de clave externa) y disminuir los requisitos de almacenamiento para los índices agrupados y no agrupados de nuestras tablas.

Tenga en cuenta que estos beneficios solo se producen cuando la clave sustituta es pequeña y la clave de agrupación. Si se utiliza un GUID como clave de agrupamiento, la situación a menudo será peor que si se hubiera utilizado la Clave natural más pequeña disponible. Si la tabla está organizada como un montón, entonces el RowID de 8 bytes (montón) se usará para búsquedas de claves, que es mejor que un GUID de 16 bytes pero menos eficaz que un entero de 4 bytes.

Si se debe utilizar un GUID debido a restricciones comerciales, vale la pena buscar una clave de agrupación mejor. Si, por ejemplo, es posible un pequeño identificador de sitio y un "número de secuencia de sitio" de 4 bytes, entonces ese diseño podría proporcionar un mejor rendimiento que un GUID como clave sustituta.

Si las consecuencias de un montón (quizás una combinación hash) hacen que el almacenamiento preferido sea entonces los costos de una clave de agrupamiento más amplia deben equilibrarse en el análisis de compensación.

Considere este ejemplo ::

ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)

donde la tupla " (P_Id, LastName) " requiere una restricción de unicidad, y puede ser un largo Unicode LastName más un entero de 4 bytes, sería deseable (1) aplicar declarativamente esta restricción como " ADD CONSTRAINT pk_PersonID UNIQUE NONCLUStered (P_Id , Apellido) "y (2) declaran por separado que una pequeña clave sustituta es la" clave principal "de un índice agrupado. Vale la pena señalar que Anita posiblemente solo desea agregar el Apellido a esta restricción para que sea un campo cubierto, lo cual es innecesario en un índice agrupado porque TODOS los campos están cubiertos por él.

La capacidad en SQL Server para designar una clave primaria como no agrupada es una circunstancia histórica desafortunada, debido a una combinación del significado "clave natural o candidata preferida" (del Modelo lógico) con el significado "clave de búsqueda en almacenamiento" del Físico Modelo. Tengo entendido que originalmente SYBASE SQL Server siempre usaba un RowID de 4 bytes, ya sea en un montón o en un índice agrupado, como la "clave de búsqueda en el almacenamiento" del Modelo físico.

Pieter Geerkens
fuente
3
¿Puedes traducir esto al inglés?
Jasir
3

Algunas personas usan el término "clave primaria" para referirse exactamente a una columna entera que obtiene sus valores generados por algún mecanismo automático. Por ejemplo AUTO_INCREMENTen MySQL o IDENTITYen Microsoft SQL Server. ¿Estás usando la clave primaria en este sentido?

Si es así, la respuesta depende de la marca de la base de datos que esté utilizando. En MySQL, no puede hacer esto, obtiene un error:

mysql> create table foo (
  id int primary key auto_increment, 
  id2 int auto_increment
);
ERROR 1075 (42000): Incorrect table definition; 
there can be only one auto column and it must be defined as a key

En algunas otras marcas de bases de datos, puede definir más de una columna de generación automática en una tabla.

Bill Karwin
fuente
55
¿Cuál sería el punto de tener múltiples columnas autogeneradoras?
Tarnay Kálmán el
No tengo un caso de uso en mente, pero si alguna vez fuera necesario, algunas marcas de bases de datos lo admitirían y otras no. Eso es todo lo que digo.
Bill Karwin el
1
Aquí hay un caso: en una tabla de órdenes, tengo una ID (autoincrementada) y una ID externa (cadenas tipo hash), ambas deberían ser únicas, por lo que teóricamente se podría decir que ambas son "primarias". por supuesto, esto se puede hacer con un índice único secundario, pero aún así es un caso legítimo (en mi humilde opinión)
Nir
2

Tener dos claves principales al mismo tiempo no es posible. Pero (suponiendo que no haya desordenado el caso con la clave compuesta), lo que podría necesitar es hacer que un atributo sea único.

CREATE t1(
c1 int NOT NULL,
c2 int NOT NULL UNIQUE,
...,
PRIMARY KEY (c1)
);

Sin embargo, tenga en cuenta que en la base de datos relacional, una 'súper clave' es un subconjunto de atributos que identifican de forma única una tupla o fila en una tabla. Una 'clave' es una 'superclave' que tiene una propiedad adicional que al eliminar cualquier atributo de la clave, hace que esa clave ya no sea una 'superclave' (o simplemente una 'clave' es una superclave mínima). Si hay más claves, todas ellas son claves candidatas. Seleccionamos una de las claves candidatas como clave principal. Es por eso que hablar de varias claves principales para una relación o tabla es un conflicto.

Rusiru Adithya Samarasinghe
fuente
Wikipedia no tiene una definición para 'clave'. Además, "eliminar cualquier atributo de la clave, hace que esa clave ya no sea una 'súper clave'" no significó nada para mí, ya que cuando eliminar un atributo de la súper clave todavía puede ser súper clave.
Manohar Reddy Poreddy
@ManoharReddyPoreddy Sí, en ese caso, su conjunto de atributos no es una 'clave' sino una 'superclave'. Lo que quiero decir es que si un conjunto de atributos es una 'clave', el conjunto debe ser mínimo, o el conjunto debe tener una propiedad adicional de que eliminar cualquier atributo del conjunto hace que el conjunto resultante no sea más una 'superclave'.
Rusiru Adithya Samarasinghe
Parece que su significado real de 'clave' es Candidate_key ( en.wikipedia.org/wiki/Candidate_key ), puede mencionarse así.
Manohar Reddy Poreddy
@ManoharReddyPoreddy Sí, ya lo he mencionado en mi respuesta. "Si hay más claves, todas ellas son claves candidatas". De todos modos, gracias por tu comentario.
Rusiru Adithya Samarasinghe
1. Cuando menciona "Si hay más claves, todas ellas son claves candidatas", ... ¿Quiere decir que de lo contrario / no son claves candidatas? ... 2. ¿Dónde está la parte más? ... ¿Somos la misma página?
Manohar Reddy Poreddy
1

Una clave primaria es la clave que identifica de forma exclusiva un registro y se utiliza en todos los índices. Por eso no puedes tener más de uno. También es generalmente la clave que se utiliza para unirse a tablas secundarias, pero esto no es un requisito. El verdadero propósito de una PK es asegurarse de que algo le permita identificar un registro de manera única para que los cambios en los datos afecten al registro correcto y para que se puedan crear índices.

Sin embargo, puede colocar varios campos en una clave primaria (una PK compuesta). Esto hará que sus uniones sean más lentas (especialmente si son campos de tipo cadena más grandes) y sus índices más grandes, pero puede eliminar la necesidad de hacer uniones en algunas de las tablas secundarias, en lo que respecta al rendimiento y el diseño, tómelo en un caso por base de caso Cuando hace esto, cada campo en sí no es único, pero la combinación de ellos sí lo es. Si uno o más de los campos en una clave compuesta también deben ser únicos, entonces necesita un índice único en él. Sin embargo, es probable que si un campo es único, este sea un mejor candidato para el PK.

Ahora, a veces, tienes más de un candidato para el PK. En este caso, elige una como PK o utiliza una clave sustituta (personalmente prefiero las claves sustitutas para esta instancia). Y (¡esto es crítico!) Agrega índices únicos a cada una de las claves candidatas que no se eligieron como PK. Si los datos deben ser únicos, necesita un índice único, ya sea PK o no. Este es un problema de integridad de datos. (Tenga en cuenta que esto también es cierto cada vez que usa una clave sustituta; las personas se meten en problemas con las claves sustitutas porque se olvidan de crear índices únicos en las claves candidatas).

En ocasiones, hay ocasiones en las que desea más de una clave sustituta (que generalmente son PK si las tiene). En este caso, lo que desea no son más PK, son más campos con claves autogeneradas. La mayoría de los DB no permiten esto, pero hay formas de evitarlo. Primero considere si el segundo campo podría calcularse en función de la primera clave autogenerada (Campo1 * -1, por ejemplo) o tal vez la necesidad de una segunda clave autogenerada realmente significa que debe crear una tabla relacionada. Las tablas relacionadas pueden estar en una relación uno a uno. Para hacer cumplir eso, agregue el PK de la tabla primaria a la tabla secundaria y luego agregue el nuevo campo autogenerado a la tabla y luego los campos que sean apropiados para esta tabla. Luego, elija una de las dos claves como PK y coloque un índice único en la otra (el campo autogenerado no tiene que ser un PK). Y asegúrese de agregar el FK al campo que está en la tabla principal. En general, si no tiene campos adicionales para la tabla secundaria, debe examinar por qué cree que necesita dos campos autogenerados.

HLGEM
fuente
0

Se dieron buenas respuestas técnicas de una mejor manera que yo. Solo puedo agregar a este tema:

Si desea algo que no está permitido / aceptable, es una buena razón para dar un paso atrás.

  1. Comprenda el núcleo de por qué no es aceptable.
  2. Excava más en documentación / artículos de revistas / web y etc.
  3. Analizar / revisar el diseño actual y señalar fallas importantes.
  4. Considere y pruebe cada paso durante el nuevo diseño.
  5. Siempre mira hacia adelante e intenta crear una solución adaptativa.

Espero que ayude a alguien.

Tom Lime
fuente
1
consejos genéricos (aunque útiles), no una respuesta a la pregunta específica.
Bradford Needham el
-3

Sí, es posible en SQL, pero no podemos configurar más de una clave primaria en MsAccess. Entonces, no sé sobre las otras bases de datos.

CREATE TABLE CHAPTER (
    BOOK_ISBN VARCHAR(50) NOT NULL,
    IDX INT NOT NULL,
    TITLE VARCHAR(100) NOT NULL,
    NUM_OF_PAGES INT,
    PRIMARY KEY (BOOK_ISBN, IDX)
);
Stema
fuente
Una tabla SQL solo puede tener una PK.
philipxy