Pelo que entendi, a terceira forma normal (3NF) basicamente significa que deve haver exatamente uma chave.
No. 2NF, 3NF e Boyce Codd Normal Form (BCNF) lidam com dependências funcionais . Uma tabela em 2NF significa que não há dependências parciais de chave em que uma coluna não chave depende de algum subconjunto adequado de uma chave de várias colunas. Tabelas como a do nosso exemplo já estão em 2NF, pois cada chave candidata é uma única coluna. Uma tabela no 3NF significa que todas as colunas que não são de chave também não dependem funcionalmente de alguma outra coluna que não seja de chave, criando, assim, uma dependência transitiva. Não importa se há uma ou cem chaves candidatas. Na verdade, é o BCNF, não o 3NF, que é a forma normal "final" em relação às dependências funcionais. Isso ocorre porque uma tabela pode estar no 3NF e ainda não no BCNF, pois pode haver várias chaves candidatas que se sobrepõem. Assim, quando usamos o termo 3NF para significar "totalmente normalizado" com relação às dependências funcionais, o que realmente queremos dizer é BCNF.
Se uma tabela com uma coluna id de incremento automático também possuir uma coluna conhecida por ser única e não nula, por exemplo, número do seguro social, essa outra coluna poderá ser usada como chave.
Não só poderia ser, mas também deve ser, se queremos garantir que os dados armazenados no banco de dados permaneçam consistentes com as regras que identificamos no mundo real!
Ignorando questões práticas / comerciais (por exemplo, risco de segurança / privacidade ao passar o SSN como uma chave / FK), de um aspecto estritamente de projeto de esquema, essa tabela não estaria no 3NF porque existem efetivamente 2 chaves?
Como explicado acima, se a tabela está ou não em 3NF (ou mais importante, em BCNF) é ortogonal a quantas chaves candidatas ela contém.
A resposta variaria se houvesse uma chave exclusiva na outra coluna? Se sim, por quê?
Não, simplesmente porque determinar se a tabela está ou não na 3NF não tem nada a ver com quantas chaves candidatas ela possui. Em vez disso, tem tudo a ver com garantir que todas as colunas sem chave sejam totalmente funcionalmente dependentes dessas chaves candidatas.
Mas isso faz abrir um ponto interessante. Observe que uma chave exclusiva quando definida como uma restrição em um DBMS não é a mesma que um identificador exclusivo definido como uma regra de negócios em um modelo de negócios conceitual. Talvez em nosso mundo sempre conheçamos o SSN da pessoa e, portanto, ela sirva como uma chave candidata para uma pessoa, e talvez também introduzamos uma chave substituta no esquema lógico que chamamos de ID da pessoa . Nosso modelo de negócios inclui a regra que afirma que o SSN é um identificador exclusivo para uma pessoa em nosso mundo. Isso implica uma dependência funcionalde todos os atributos descritivos nesse atributo de identidade. Essa regra não muda apenas porque esquecemos ou optamos por não informar o DBMS. É exatamente por isso que é vital que a restrição seja declarada - para que o DBMS possa garantir que os dados armazenados sejam consistentes com as regras do modelo de negócios! Se não criamos essa restrição exclusiva no SSN, agora podemos criar inadvertidamente mais de uma linha para a mesma pessoa com o mesmo SSN; cada linha com um ID de pessoa diferente!
Uma excelente cartilha sobre esses tópicos é a Practical Database Foundation Series, de Fabian Pascal, e a Database Design and Relational Theory , de Chris Date , da qual essa resposta é derivada. Embora cada artigo de Fabian seja uma leitura obrigatória, o artigo 1 (que define claramente a diferença entre os níveis conceitual, lógico e físico) e o artigo 4 (que define claramente os vários tipos de chaves) abordam especificamente essa questão. Da mesma forma, o livro inteiro de Chris é uma leitura obrigatória, enquanto a Parte II é a seção dedicada à normalização com relação à dependência funcional.