Um novo requisito surgiu em uma antiga base de código, que basicamente permite a comunicação direta (interna) entre duas classes de usuários anteriormente não diretamente relacionadas (armazenadas em tabelas diferentes com esquema completamente diferente e, infelizmente, o código não reconhece o OO, muito menos projetada, para que não haja classe pai). Como estamos ansiosos por essa configuração antiga que nunca considerou essa funcionalidade, não há garantia de que não haja colisões de PK - dado o conjunto de dados em uso, é praticamente garantido que EXISTE.
Portanto, a solução parece óbvia: mate-a com fogo e reescreva toda a bagunça Uma tabela de mapeamento. Eu recebi duas direções para as possíveis maneiras de implementar o mapa, mas não sou um DBA, por isso não tenho certeza se existem prós e contras que perdi.
Para esclarecer a abstração, considere três grupos de dados de usuários diferentes: Professores, Administração, Estudantes (Não, isso não é tarefa de casa. Promessa!)
Mapeamento 1
(professor_id, admin_id e student_id são chaves estrangeiras para suas respectivas tabelas)
| mailing_id (KEY) | professor_id | admin_id | student_id |
-------------------------------------------------------
| 1001 | NULL | 87 | NULL |
| 1002 | 123 | NULL | NULL |
| 1003 | NULL | NULL | 123 |
O +/- dessa abordagem parece bastante pesado sobre os contras:
- Dois campos "desperdiçados" por linha
- Viola 2NF
- Vulnerável para inserir / atualizar anomalias (uma linha com apenas 0-1 conjunto de campos NULL, por exemplo)
Os profissionais não têm seus próprios méritos, no entanto:
- O mapeamento pode ser realizado com uma única pesquisa
- Determine facilmente os dados de "origem" de um determinado usuário no mailing_id
Verdade seja dita, no meu intestino, eu não gosto dessa idéia.
Mapeamento 2
(suponha que MSG_ * sejam constantes definidas, tipos de enumeração ou outro identificador adequado)
| mailing_id (KEY) | user_type (UNIQUE1) | internal_id (UNIQUE2)|
------------------------------------------------------------------
| 1001 | MSG_ADMIN | 87 |
| 1002 | MSG_PROF | 123 |
| 1003 | MSG_STUDENT | 123 |
Com essa configuração, e um índice composto exclusivo de {user_type, internal_id} as coisas ficam muito mais limpas, o 3NF é mantido e o código do aplicativo não precisa verificar anomalias de I / U.
Por outro lado, há um pouco de perda de transparência na determinação das tabelas de origem do usuário que precisam ser tratadas fora do banco de dados, equivalendo basicamente a um mapeamento no nível de aplicativo dos valores de user_type para as tabelas. No momento, estou (com bastante força) inclinando-me para esse segundo mapeamento, pois a desvantagem é um pouco menor.
MAS estou dolorosamente ciente de minhas próprias limitações e tenho certeza de que provavelmente perdi vantagens ou obstáculos em ambas as direções, por isso volto a mentes mais sábias do que as minhas.