Atualmente estou modelando um esquema de banco de dados. Nele, os endereços são utilizados várias vezes, que seguem uma estrutura fixa. Em nossos sistemas anteriores, a relação de endereço era modelada de tal forma que o endereço continha chaves estrangeiras, por exemplo, as de um usuário.
Raciocínio: Desta forma, um endereço só pode ser anexado a um dos pais. Do meu ponto de vista, no entanto, isso é um caos absoluto, porque às vezes existem até oito chaves estrangeiras na relação de endereço, devendo-se tomar cuidado para que apenas uma seja preenchida.
Não faria muito mais sentido colocar a chave no pai, de modo que, por meio de uma restrição diferente de zero, se pudesse garantir que cada pai tenha um endereço e a relação de endereço seja limpa? O pai também raramente/nunca é navegado a partir do lado do endereço.
Ou estou violando alguma convenção fazendo isso? Nesse caso, a limpeza não pesa mais do que uma "convenção"? Se desejado, também pode-se modelar os requisitos anteriores usando gatilhos?
Abordagem atual: Restrição para garantir que apenas um FK seja definido no endereço.
Sim, então sua abordagem/a segunda abordagem geralmente é mais favorável e normalizada porque leva a menos redundância
addresses
. Mas você perde a flexibilidade deuser
ter múltiplosaddresses
dessa maneira, por causa dessa abordagem um para um. Se isso não for um requisito do esquema lógico, sua abordagem fará mais sentido.Alternativamente, para dar suporte à normalização e flexibilidade melhor dos dois mundos, você pode adicionar mais uma tabela chamada
userAddress
que é uma tabela de ponte/vinculação entre os dois, suportando um relacionamento muitos para muitos armazenando os camposuser_id
e como pares de todos para cada .address_id
addresses
user
Então resumindo:
Também para sua segunda pergunta sobre Triggers , eles não são todos implementados exatamente da mesma maneira em todos os RDBMS modernos (porque a especificação compatível com ANSI para eles é mínima em relação aos outros recursos do SQL). Portanto, para uma resposta generalizada (já que não estamos falando de um sistema de banco de dados específico no contexto desta pergunta), depende do sistema de banco de dados se você conseguir replicar o comportamento desejado por meio de um Trigger . (Vejo que você pessoalmente usa PostgreSQL , então acredito nesse contexto, então seria possível com um Trigger .)
Um usuário ou uma empresa pode ter vários endereços? Normalmente, isso é uma coisa bastante razoável. Os usuários têm endereços físicos e de correspondência. As empresas têm endereços de cobrança e endereços de entrega. Se você colocar um
address_id
nauser
tabela ou nacompany
tabela, estará limitando usuários e empresas a um único endereço que geralmente não é o que você deseja.Um usuário e uma empresa podem ter o mesmo endereço de modo que alterar um automaticamente altera o outro? Se ambos
user
ecompany
tiverem uma linha com o mesmoaddress_id
e o usuário entrar e fizer com que aaddress
linha seja atualizada, você realmente deseja que o endereço da empresa também mude? É possível que isso faça sentido em seu aplicativo, mas acho que normalmente você deseja garantir que diferentes tipos de entidades façam referência a endereços diferentes.Como regra, eu geralmente teria uma tabela de mapeamento entre
user
eaddress
que permitia um relacionamento de 1 para muitos e umaaddress_type
tabela que me permitisse especificar que tipo de endereço era. Dessa forma, eu teria flexibilidade para definir tipos de, digamos, endereço de correspondência de um usuário ou endereço de cobrança de uma empresa ou um endereço combinado de usuário/empresa. Você pode modificar o modelo de dados para impor regras como "um usuário só pode ser associado a determinados tipos de endereço" ou "um usuário e uma empresa não podem fazer referência ao mesmo address_id", mas normalmente é razoável que esses tipos de coisas sejam regras de negócios o aplicativo gerencia.1ª abordagem
criar o endereço da tabela ( address_id integer chave primária, -- campos relacionados ao endereço );
create table company( company_id integer key, -- campos relacionados à empresa )
criar tabela Usuário ( user_id int chave primária, address_id int referências de chave estrangeira Address(address_id) company_id int referências de chave estrangeira Company(company_id)
)
2º, se você tiver vários tipos de endereço, poderá mapear os tipos de endereço em uma tabela de mapeamento e ter o address_type_key em cada tabela como uma chave estrangeira .
criar tabela address_type ( address_type_id integer key, address_type varchar(100)
-- campos relacionados ao tipo de endereço );
criar o endereço da tabela ( address_id integer chave primária, address_type_id int referências de chave estrangeira address_type(address_type_id), address_line_1 varchar(100), address_line_2 varchar(100), State varchar(50), country varchar(50), postalCode varchar(10) -- campos relacionados ao endereço);
criar tabela empresa( company_id integer key, address_type_key int referências de chave estrangeira Address_type (address_type_id), address_key int Foreign Key Referências address(address_id) -- campos relacionados à empresa )
criar tabela Usuário ( user_id int chave primária, address_type_key int referências de chave estrangeira Address_type (address_type_id), address_key int referências de chave estrangeira Address(address_id) company_id int referências de chave estrangeira Company(company_id)
)