Como projetar esse banco de dados para evitar dependência cíclica?

12

Existem duas tabelas:

  1. Do utilizador
  2. Endereço

O usuário contém uma referência ao endereço.

Endereço contém as colunas CreatedBy e ModifiedBy, que são referência ao usuário.

Como faço para projetar esse banco de dados para evitar uma dependência cíclica?

Shashi
fonte
4
Você tem certeza de que ModifiedBy não é uma referência ao usuário do banco de dados que fez a alteração, e não ao usuário de aplicativos (que residiria na tabela Usuário)? De qualquer maneira, isso realmente não importa. Não vejo por que há um problema real?
Philᵀᴹ
Qual deles será criado primeiro. Como CreatedBy e Modifiedby são dados obrigatórios. E a tabela do usuário não deve ter o endereço como nulo. Problema com ovo de galinha. Como eu resolver isso criando um novo UserAddress tabela que contém a referência para ID do usuário e AddressID
Shashi
2
Você sempre pode usar restrições adiadas se o seu DBMS as suportar.
Colin 'Hart
Nota: O modelo relacional suporta duas inserções ou atualizações como uma operação atômica, é uma pena que isso não seja suportado no SQL (como restrições adiadas - mesmo que eu as tenha sugerido - são bastante horríveis).
Colin 'Hart

Respostas:

7

Em vez de procurar dicas e truques (restrições adiadas incluídas), eu sugeriria que você simplesmente desenhasse esse "bloqueio de referência" - então tente algo como isto:


Fatos

  • Usuário(UserID) existe.
  • O endereço(AddressID) foi criado pelo usuário(UserID) .
  • O endereço(AddressID) foi criado em Data(DateCreated) .
  • O endereço(AddressID) foi modificado pela última vez pelo usuário(UserID) na data(ModifiedOn) .
  • O usuário(UserID) reside em Endereço(AddressID) desde a Data(ValidFrom) .

Restrições

  • Each O endereço foi criado pelo exactly one usuário . It is possible that more than one O endereço foi criado pelo the same usuário .

  • Each O endereço foi criado em exactly one Data . It is possible that more than one O endereço foi criado em the same Data .

  • For each and Data do endereço , o that endereço foi modificado pelo at most one usuário na that data .

  • For each and Data do Usuário , o that Usuário reside em at most one Endereço desde a that Data .


Lógico

insira a descrição da imagem aqui


No que diz respeito ao endereço obrigatório, verifique se, na camada do aplicativo, envolva as instruções de carregamento em uma transação - para que você obtenha tudo ou nada.

Damir Sudarevic
fonte
5

Você não tem opção a não ser criar a dependência cíclica em 2 operações, como abaixo, porque uma tabela não existe quando você cria a primeira.

CREATE TABLE A (A_ID INT PRIMARY KEY, B_FK INT);
CREATE TABLE B (B_ID INT PRIMARY KEY, A_FK INT REFERENCES A(A_ID));

ALTER TABLE A ADD B_FK INT;

Se você deseja evitar dependência cíclica. Em seguida, é necessário remover uma restrição de REFERENCES ou adicionar uma referência DELETE e UPDATE CASCADE de uma maneira. Você também pode implementar um TRIGGER se sua lógica for um pouco complexa.

PollusB
fonte
1
A remoção das restrições remove a dependência cíclica da definição, mas não do design. Você pode adicionar uma tabela de eventos para registrar o UserID e o AddressID que criaram ou modificaram o endereço pela última vez, mas isso apenas move a dependência um passo adiante. Indo de outra maneira, se a tabela Usuário tivesse colunas CreatedBy e ModifiedBy, a dependência cíclica existiria em uma tabela. Isso é semelhante a uma tabela de funcionários com uma coluna de supervisor em que o supervisor também é um funcionário. Como Phil indicou - Não há problema.
Leigh Riffel
@LeighRiffel, eu concordo. Mas a tabela Eventos que você propõe remove realmente todas as dependências cíclicas.
ypercubeᵀᴹ
@ypercube De fato, sim; não sei como consegui atravessar esse fio. Para ficar claro, você provavelmente não deve criar uma tabela de Eventos, embora remova a dependência cíclica.
Leigh Riffel
De qualquer forma, acho que essa resposta não resolve o problema. A questão (eu acho) é sobre como evitar o caminho cíclico, e não como criar os FKs com o caminho cíclico em primeiro lugar.
ypercubeᵀᴹ