¿Puedo tener varias claves principales en una sola tabla?

¿Puedo tener varias claves principales en una sola tabla?

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.

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 de forma similar a una clave principal, ya que impondrán valores únicos y acelerarán la consulta de esos valores.

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

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

Es práctica común, si hay varias claves 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 principal, en lugar de a 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.

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

¿Cuál sería el sentido de tener múltiples columnas de autogeneración?

Este código a continuación tiene una clave primaria compuesta. Una de sus columnas se incrementa automáticamente. Esto funcionará solo en MyISAM. InnoDB generará un error ” ERROR 1075 (42000): definición incorrecta de la tabla; 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 | +--------+----+---------+ 

La Clave principal es una notación muy desafortunada, debido a la connotación de “Primario” y la asociación subconsciente en consecuencia con el Modelo lógico. Por lo tanto, evito usarlo. En cambio, me refiero a la clave sustituta del modelo físico y la clave (s) natural 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 claves candidatas. Cuando construimos 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 manera única las filas en las tablas; como las claves sustitutas siempre deben estar ocultas para los usuarios. Esto se debe a que las claves sustitutas no tienen ningún significado 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 nuestra (s) clave (s) natural (es) disponible (s) son amplias, (1) amplía el ancho de nuestros nodos hoja no agrupados, aumentando 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, aumentando de nuevo 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 principal” resulta beneficiosa. Cuando se establece como la clave de clúster, para que se use para búsquedas de claves en el índice agrupado de índices no agrupados y búsquedas de claves externas de tablas relacionadas, todas estas desventajas desaparecen. Nuestras divisiones agrupadas de índices aumentan nuevamente para reducir el tamaño y el tamaño del índice agrupado, reducir la carga del caché para nuestros índices agrupados, disminuir lecturas al acceder a 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 agrupamiento. 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 rendimiento que un entero de 4 bytes.

Si se debe utilizar un GUID debido a restricciones comerciales, vale la pena buscar una mejor clave de clúster. Si, por ejemplo, un identificador de sitio pequeño y un “número de secuencia de sitio” de 4 bytes es factible, ese diseño podría ofrecer un mejor rendimiento que un GUID como clave sustituta.

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

Considera 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 exclusividad, y puede ser un apellido Unicode extenso más un entero de 4 bytes, sería deseable (1) aplicar esta restricción de manera declarativa como ” AGREGAR RESTRICCIÓN pk_PersonID ÚNICA NO CLASIFICADA (P_Id , LastName) “y (2) declaran por separado una pequeña clave sustituta como la” clave principal “de un índice agrupado. Vale la pena señalar que Anita posiblemente solo desee agregar el apellido a esta restricción para hacer de ese campo cubierto, lo cual no es necesario en un índice agrupado porque TODOS los campos están cubiertos por él.

La capacidad en SQL Server para designar una clave principal 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. Según entiendo, 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.

Como lo señalaron los demás, es posible tener claves primarias de múltiples columnas. Sin embargo, debe tenerse en cuenta que si tiene algunas dependencias funcionales que no son introducidas por una clave, debería considerar la normalización de 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 Sin embargo, a menudo se asocia un zip_code con un area y, por lo tanto, existe 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 .

Algunas personas usan el término “clave principal” para significar exactamente una columna entera que obtiene sus valores generados por algún mecanismo automático. Por ejemplo AUTO_INCREMENT en MySQL o IDENTITY en Microsoft SQL Server. ¿Estás usando la clave principal en este sentido?

Si es así, la respuesta depende de la marca de la base de datos que está utilizando. En MySQL, no puedes hacer esto, obtienes 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 base de datos, puede definir más de una columna de autogeneración en una tabla.

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

Sin embargo, puede poner múltiples campos en una clave primaria (una PK compuesta). Esto hará que tus uniones sean más lentas (especialmente si son campos de tipo cadena más grandes) y tus índices más grandes, pero puede eliminar la necesidad de hacer combinaciones en algunas de las tablas secundarias, por lo que en cuanto a rendimiento y diseño, tómalo en caso de caso base Cuando haces 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, tiene más de un candidato para PK. En este caso, elige uno como PK o usa 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 tienen problemas con las claves sustitutas porque olvidan crear índices únicos en las claves candidatas).

Ocasionalmente, es posible que desee más de una clave sustituta (que generalmente es la PK si las tiene). En este caso, lo que desea no son más PK’s, sino 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 se puede calcular en función de la primera clave autogenerada (Campo1 * -1 por ejemplo) o tal vez la necesidad de una segunda clave autogenerada realmente signifique que debe crear una tabla relacionada. Las tablas relacionadas pueden estar en una relación de uno a uno. Haría cumplir eso agregando el PK de la tabla padre a la tabla secundaria y luego agregando el nuevo campo autogenerado a la tabla y luego cualesquiera campos apropiados para esta tabla. A continuación, elija una de las dos claves como PK y coloque un índice único en el otro (el campo autogenerado no tiene que ser PK). Y asegúrese de agregar el FK al campo que está en la tabla padre. En general, si no tiene campos adicionales para la tabla secundaria, debe examinar por qué cree que necesita dos campos autogenerados.

(He estado estudiando esto, mucho)

Solo puede haber 1 clave primaria.
Pero puede tener múltiples claves Alternas.

En simple este es el caso:

  • Puede haber múltiples claves Candidatas (columnas mínimas, para identificar de manera única la fila) en una tabla.
  • Una de las claves candidatas se elige específicamente y se denomina Clave principal
  • Todas las demás claves candidatas se denominan claves alternativas
  • Tanto la clave principal como las teclas alternativas pueden ser claves compuestas (2 o más columnas)

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

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

Si quiere 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, etc.
  3. Analiza / revisa el diseño actual y señala los principales defectos.
  4. Considere y pruebe cada paso durante el nuevo diseño.
  5. Siempre mire hacia adelante y trate de crear una solución adaptativa.

Espero que ayude a alguien.

Tener dos claves primarias al mismo tiempo, no es posible. Pero (suponiendo que no haya estropeado el caso con la clave compuesta), puede ser lo que necesite para 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 ‘superclave’ es un subconjunto de atributos que identifican de manera única una tupla o fila en una tabla. Una ‘clave’ es una ‘superclave’ que tiene una propiedad adicional que elimina cualquier atributo de la tecla, hace que esa clave deje de ser una ‘superclave’ (o simplemente una ‘clave’ es una súper clave 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 múltiples claves primarias para una relación o tabla es estar en conflicto.

Sí, es posible en SQL, pero no podemos establecer 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) );