Posso ter várias chaves primárias em uma única tabela?
Posso ter várias chaves primárias em uma única tabela?
Respostas:
Uma tabela pode ter uma chave primária composta, que é uma chave primária feita de duas ou mais colunas. Por exemplo:
CREATE TABLE userdata (
userid INT,
userdataid INT,
info char(200),
primary key (userid, userdataid)
);
Atualização: Aqui está um link com uma descrição mais detalhada das chaves primárias compostas.
Uma tabela pode ter várias chaves candidatas. Cada chave candidata é uma coluna ou conjunto de colunas que são ÚNICAS, juntas e também NÃO NULAS. Portanto, especificar valores para todas as colunas de qualquer chave candidata é suficiente para determinar se há uma linha que atenda aos critérios ou nenhuma linha.
Chaves candidatas são um conceito fundamental no modelo de dados relacionais.
É prática comum, se várias chaves estiverem presentes em uma tabela, designar uma das chaves candidatas como chave primária. Também é prática comum fazer com que qualquer chave estrangeira da tabela faça referência à chave primária, em vez de qualquer outra chave candidata.
Eu recomendo essas práticas, mas não há nada no modelo relacional que exija a seleção de uma chave primária entre as chaves candidatas.
Esta é a resposta para a pergunta principal e para a pergunta de @ Kalmi sobre
Qual seria o sentido de ter várias colunas de geração automática?
Este código abaixo tem uma chave primária composta. Uma de suas colunas é incrementada automaticamente. Isso funcionará apenas no MyISAM. O InnoDB gerará um erro " ERRO 1075 (42000): definição de tabela incorreta; pode haver apenas uma coluna automática e deve ser definida como uma chave ".
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 |
+--------+----+---------+
(Tenho estudado muito isso)
Chaves candidatas - é necessária uma combinação mínima de colunas para identificar exclusivamente uma linha da tabela.
Chaves compostas - 2 ou mais colunas.
Fontes:
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
Conforme observado pelos outros, é possível ter chaves primárias com várias colunas. Note-se, no entanto, que se você tiver algumas dependências funcionais que não são introduzidas por uma chave, considere normalizar sua relação.
Exemplo:
Person(id, name, email, street, zip_code, area)
Pode haver uma dependência funcional entre id -> name,email, street, zip_code and area
Mas, frequentemente, a zip_code
é associado a area
e, portanto, existe uma dependência funcional interna entre eles zip_code -> area
.
Assim, pode-se considerar dividi-lo em outra tabela:
Person(id, name, email, street, zip_code)
Area(zip_code, name)
Para que seja consistente com a terceira forma normal .
Chave Primária é uma notação muito infeliz, devido à conotação de "Primária" e a associação subconsciente em conseqüência do Modelo Lógico. Assim, evito usá-lo. Em vez disso, refiro-me à Chave Substituta do Modelo Físico e às Chaves Naturais do Modelo Lógico.
É importante que o Modelo Lógico para cada Entidade tenha pelo menos um conjunto de "atributos de negócios" que compreendam uma Chave para a entidade. Boyce, Codd, Date e outros se referem a eles no Modelo Relacional como Chaves Candidatas. Quando criamos tabelas para essas Entidades, as Chaves Candidatas se tornam Chaves Naturais nessas tabelas. É somente através dessas Chaves Naturais que os usuários conseguem identificar exclusivamente as linhas nas tabelas; como chaves substitutas sempre devem estar ocultas dos usuários. Isso ocorre porque as Chaves Substitutas não têm significado comercial.
No entanto, o Modelo Físico para nossas tabelas, em muitos casos, será ineficiente sem uma Chave de Substituição. Lembre-se de que as colunas não cobertas de um índice não agrupado em cluster só podem ser encontradas (em geral) por meio de uma Pesquisa de Chave no índice agrupado (ignore as tabelas implementadas como pilhas por um momento). Quando nossas Chaves Naturais disponíveis são amplas, isso (1) aumenta a largura de nossos nós de folhas não agrupados em cluster, aumentando os requisitos de armazenamento e os acessos de leitura para pesquisas e varreduras desse índice não agrupado; e (2) reduz a dispersão do índice em cluster, aumentando a altura e o tamanho do índice, aumentando novamente os requisitos de leitura e armazenamento para os índices em cluster; e (3) aumenta os requisitos de cache para nossos índices em cluster. perseguindo outros índices e dados fora do cache.
É aqui que uma pequena chave substituta, designada ao RDBMS como "a chave primária", é benéfica. Quando definida como a chave de cluster, para ser usada para pesquisas de chaves no índice de cluster de índices não em cluster e pesquisas de chave estrangeira de tabelas relacionadas, todas essas desvantagens desaparecem. Nossas fan-outs de índice em cluster aumentam novamente para reduzir a altura e o tamanho do índice em cluster, reduz a carga de cache para nossos índices em cluster, diminuem as leituras ao acessar dados através de qualquer mecanismo (seja varredura de índice, busca de índice, pesquisa de chave sem cluster ou pesquisa de chave estrangeira) e diminuir os requisitos de armazenamento para índices em cluster e não clusterizado de nossas tabelas.
Observe que esses benefícios ocorrem apenas quando a chave substituta é pequena e a chave de cluster. Se um GUID for usado como chave de cluster, a situação geralmente será pior do que se a menor chave natural disponível tivesse sido usada. Se a tabela estiver organizada como um heap, o RowID de 8 bytes (heap) será usado para pesquisas de chaves, o que é melhor que um GUID de 16 bytes, mas com menos desempenho que um número inteiro de 4 bytes.
Se um GUID precisar ser usado devido a restrições de negócios, vale a pena procurar uma chave de cluster melhor. Se, por exemplo, um identificador de site pequeno e um "número de sequência de site" de 4 bytes for possível, esse design poderá oferecer um desempenho melhor que um GUID como Chave Substituta.
Se as consequências de um heap (junção de hash talvez) tornarem o armazenamento preferido, os custos de uma chave de cluster mais ampla precisam ser equilibrados na análise de trade-off.
Considere este exemplo ::
ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
onde a tupla " (P_Id, LastName) " requer uma restrição de exclusividade e pode ser um Sobrenome Unicode longo mais um número inteiro de 4 bytes, seria desejável (1) impor declarativamente essa restrição como " ADD CONSTRAINT pk_PersonID UNIQUE NONCLUSTERED (P_Id , Sobrenome) "e (2) declaram separadamente uma Chave Substituta pequena como a" Chave Primária "de um índice em cluster. Vale a pena notar que o Anita possivelmente deseja apenas adicionar o Sobrenome a essa restrição para tornar esse campo coberto, o que é desnecessário em um índice clusterizado porque TODOS os campos são cobertos por ele.
A capacidade do SQL Server de designar uma Chave Primária como não clusterizada é uma circunstância histórica infeliz, devido a uma combinação do significado "chave natural ou candidata preferida" (do Modelo Lógico) com o significado "chave de pesquisa no armazenamento" do Physical Modelo. Meu entendimento é que o SYBASE SQL Server originalmente sempre usava um RowID de 4 bytes, em um heap ou em um índice clusterizado, como a "chave de pesquisa no armazenamento" do Modelo Físico.
Algumas pessoas usam o termo "chave primária" para significar exatamente uma coluna inteira que obtém seus valores gerados por algum mecanismo automático. Por exemplo, AUTO_INCREMENT
no MySQL ou IDENTITY
no Microsoft SQL Server. Você está usando a chave primária nesse sentido?
Nesse caso, a resposta depende da marca do banco de dados que você está usando. No MySQL, você não pode fazer isso, você recebe um erro:
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
Em algumas outras marcas de banco de dados, você pode definir mais de uma coluna de geração automática em uma tabela.
Ter duas chaves primárias ao mesmo tempo, não é possível. Mas (supondo que você não tenha estragado o caso com chave composta), pode ser o que você precisa é tornar um atributo único.
CREATE t1(
c1 int NOT NULL,
c2 int NOT NULL UNIQUE,
...,
PRIMARY KEY (c1)
);
No entanto, observe que no banco de dados relacional uma 'super chave' é um subconjunto de atributos que identificam exclusivamente uma tupla ou linha em uma tabela. Uma 'chave' é uma 'super chave' que possui uma propriedade adicional que remove qualquer atributo da chave, faz com que essa chave não seja mais uma 'super chave' (ou simplesmente uma 'chave' é uma super chave mínima). Se houver mais chaves, todas elas são chaves candidatas. Selecionamos uma das chaves candidatas como chave primária. É por isso que falar sobre várias chaves primárias para uma relação ou tabela está sendo um conflito.
Uma chave primária é a chave que identifica exclusivamente um registro e é usada em todos os índices. É por isso que você não pode ter mais de um. Geralmente, também é a chave usada para ingressar em tabelas filho, mas isso não é um requisito. O objetivo real de uma PK é garantir que algo permita identificar exclusivamente um registro, para que as alterações nos dados afetem o registro correto e para que os índices possam ser criados.
No entanto, você pode colocar vários campos em uma chave primária (uma PK composta). Isso tornará suas junções mais lentas (especialmente se forem campos maiores do tipo string) e seus índices maiores, mas poderá remover a necessidade de fazer junções em algumas das tabelas filho, portanto, quanto ao desempenho e design, leve-os em um caso caso a caso. Quando você faz isso, cada campo em si não é exclusivo, mas a combinação deles é. Se um ou mais dos campos em uma chave composta também forem exclusivos, você precisará de um índice exclusivo. É provável que, se um campo for único, este seja um candidato melhor para o PK.
Agora, às vezes, você tem mais de um candidato para o PK. Nesse caso, você escolhe um como PK ou usa uma chave substituta (eu pessoalmente prefiro chaves substitutas para esta instância). E (isso é crítico!), Você adiciona índices exclusivos a cada uma das chaves candidatas que não foram escolhidas como PK. Se os dados precisam ser exclusivos, eles precisam de um índice exclusivo, seja o PK ou não. Este é um problema de integridade de dados. (Observe que isso também é verdade sempre que você usa uma chave substituta; as pessoas enfrentam problemas com chaves substitutas porque esquecem de criar índices exclusivos nas chaves candidatas.)
Ocasionalmente, há momentos em que você deseja mais de uma chave substituta (que geralmente é a PK, se você a possuir). Nesse caso, o que você deseja não é mais PK, são mais campos com chaves geradas automaticamente. A maioria dos bancos de dados não permite isso, mas existem maneiras de contornar isso. Primeiro, considere se o segundo campo pode ser calculado com base na primeira chave gerada automaticamente (campo1 * -1 por exemplo) ou talvez a necessidade de uma segunda chave gerada automaticamente realmente signifique que você deve criar uma tabela relacionada. As tabelas relacionadas podem estar em um relacionamento um para um. Você aplicaria isso adicionando a PK da tabela pai à tabela filha e, em seguida, adicionando o novo campo gerado automaticamente à tabela e, em seguida, quaisquer campos apropriados para esta tabela. Em seguida, escolha uma das duas chaves como PK e coloque um índice exclusivo na outra (o campo gerado automaticamente não precisa ser uma PK). E certifique-se de adicionar o FK ao campo que está na tabela pai. Em geral, se você não tiver campos adicionais para a tabela filho, precisará examinar por que acha que precisa de dois campos gerados automaticamente.
Boas respostas técnicas foram dadas da melhor maneira possível. Eu sou apenas pode adicionar a este tópico:
Se você deseja algo que não é permitido / aceitável, é uma boa razão para dar um passo atrás.
Espero que ajude alguém.
Sim, é possível no SQL, mas não podemos definir mais de uma chave primária no MsAccess. Então, não conheço os outros bancos de dados.
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)
);