2008-10-20 19 views

Respuesta

158

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.

+10

+1 por mencionar Índices únicos –

441

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:Here is a link con una descripción más detallada de las claves primarias compuestas.

+14

+1 por el enlace, Adam. Definitivamente me ayudó mucho. Gracias. –

+0

En este ejemplo, se necesitan BIDH userid y userdataid para identificar/encontrar una fila única. No estoy seguro de cuál era la intención del OP, pero vine a ver si podía identificar de manera única una fila con uno de los conjuntos de claves. Por ejemplo, me gustaría identificar 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í. – Benitok

+0

@Benitok Como se menciona en la [respuesta] de RB. (Https://stackoverflow.com/a/217948/206552), puede usar índices únicos para hacer lo que está buscando (una columna única e indexada independiente de otras columnas únicas e indexadas en la misma tabla). Asegúrese de consultar su sabor específico del manual de SQL para obtener detalles sobre la sintaxis exacta del lenguaje utilizado. – 4AM

2

Algunas personas usan el término "clave principal" para referirse exactamente a 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 se puede hacer esto, se produce 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, que son capaces de definir más de una columna de generación automática de una tabla.

+5

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

+0

No tengo un caso de uso en mente, pero si alguna vez hubo una necesidad, algunas marcas de bases de datos soportarían esto y otras no. Es todo lo que digo. –

31

Una tabla puede tener varias 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 una práctica común, si hay varias claves presentes en una tabla, designar una de las claves candidatas como la 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 principal entre las claves candidatas.

+4

De acuerdo. Todas las claves son iguales (ninguna es 'primaria') en el modelo lógico. La elección de qué tecla en la implementación física obtiene la designación PRIMARY KEY es arbitra y depende del vendedor/producto. – onedaywhen

+2

Diría que depende del diseñador de la base de datos. –

+0

Acabo de encontrar un caso de uso donde esto es obligatorio. Tengo una tabla que será creada/administrada por Entity Framework, que, por lo que puedo deducir, no admite restricciones compuestas exclusivas para claves no primarias en la actualidad. Sin embargo, admite claves primarias compuestas. Los datos también se vincularán a un sistema de base de datos remota que no admite claves compuestas en absoluto. Me he ido con la creación de un PK compuesto en EF, pero también agrego una columna GUID no anulable que el otro sistema puede usar para identificar de forma única. –

-2

Sí, es posible en SQL, pero no podemos establecer más de una clave principal 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) 
); 
12

Esta es la respuesta tanto para la cuestión principal y para la pregunta de @ Kalmi de

What would be the point of having multiple auto-generating columns?

Este código de abajo tiene una clave principal 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 | 
+--------+----+---------+ 
+0

Esto funciona si especifica la columna de incremento automático primero en la definición de la clave principal. (Tal vez esto cambió, acabo de probarlo en 5.6) – CTarczon

6

Según lo observado por los otros, es posible tener claves primarias de múltiples columnas. Sin embargo, debe tener en cuenta que si tiene algunos functional dependencies que no se introducen con una clave, debe considerar normalizing como su relación.

Ejemplo:

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

No puede haber una dependencia funcional entre id -> name,email, street, zip_code and area Pero a menudo un zip_code se asocia con una area y por lo tanto hay un dependecy funcional interna entre zip_code -> area.

Así, uno puede considerar dividir en otra tabla:

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

Así que es consistente con la third normal form.

1

Se dieron buenas respuestas técnicas de 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 revista/web y 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 adaptable.

Espero que ayude a alguien.

+1

consejos genéricos (aunque útiles), no una respuesta a la pregunta específica. –

2

Una clave principal es la clave que identifica de forma única un registro y se utiliza 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 varios campos en una clave principal (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 obtener más de una clave sustituta (que generalmente son PK si los tienes).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.

+14

El primer párrafo aquí es completamente incorrecto. – sqlvogel

7

Clave principal es 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 de negocios" que comprenda 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 tecla 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 compromiso.

Considere este ejemplo ::

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

donde la tupla "(p_id, Apellido)" requiere una restricción de unicidad, y puede ser un largo Unicode LastName más un número entero de 4 bytes, sería Deseable para (1) aplicar esta restricción de forma declarativa como "AGREGAR CONSTRAINT pk_PersonID ÚNICA NO CULPABLE (P_Id, Apellido)" y (2) declarar por separado una clave sustituta pequeña para ser 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 Modelo Físico. 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.

+2

¿Puedes traducir esto al inglés? – Jasir

1

No es posible tener dos claves principales al mismo tiempo. 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 la base de datos relacional, una 'llave super' es un subconjunto de atributos que identifican de forma única una tupla o registro 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.

Cuestiones relacionadas