Eu tenho uma tabela em que as linhas podem ser relacionadas entre si e, logicamente, o relacionamento segue nos dois sentidos (basicamente, é sem sentido) entre as duas linhas. (E se você está se perguntando, sim, essa realmente deve ser uma tabela. São duas coisas exatamente da mesma entidade / tipo lógico.) Posso pensar em algumas maneiras de representar isso:
- Armazene o relacionamento e seu reverso
- Armazene o relacionamento de uma maneira, impeça o banco de dados de armazená-lo de outra maneira e tenha dois índices com ordens opostas para os FKs (um índice sendo o índice PK)
- Armazene o relacionamento de uma maneira com dois índices e permita que o segundo seja inserido de qualquer maneira (soa meio nojento, mas ei, completo)
- Crie algum tipo de tabela de agrupamento e tenha um FK na tabela original. (Levanta muitas perguntas. A tabela de agrupamento só teria um número; por que até a tabela? Tornar FK NULLable ou ter grupos com uma única linha associada?)
Quais são alguns dos principais prós e contras dessas formas e, é claro, existe alguma maneira em que eu não tenha pensado?
Aqui está um SQLFiddle para jogar: http://sqlfiddle.com/#!12/7ee1a/1/0 . (Por acaso é o PostgreSQL, já que é isso que estou usando, mas não acho que essa pergunta seja muito específica do PostgreSQL.) Atualmente, ele armazena o relacionamento e seu inverso apenas como exemplo.
fonte
Respostas:
O que você projetou é bom. O que precisa ser adicionado é uma restrição para tornar o relacionamento sem direção. Portanto, você não pode ter uma
(1,5)
linha sem a(5,1)
adição de uma linha.Isso pode ser realizado * com uma restrição de auto-referência na tabela de pontes.
*: pode ser realizado no Postgres, Oracle, DB2 e todos os DBMS que implementaram restrições de chave estrangeira como o padrão SQL descreve (adiado, por exemplo, verificado no final da transação). A verificação adiada não é realmente necessária, como no SQL Servidor que os verifica no final da instrução e essa construção ainda funciona. Você não pode fazer isso no MySQL porque "O InnoDB verifica as restrições UNIQUE e FOREIGN KEY linha por linha" .
Portanto, no Postgres, o seguinte corresponderá aos seus requisitos:
Testado em: SQL-Fiddle
Se você tentar adicionar uma linha
(1,5)
:Falha com:
Além disso, você pode adicionar uma
CHECK
restrição se quiser proibir(y,y)
linhas:Existem outras maneiras de implementar isso, como você menciona, como armazenar apenas uma direção do relacionamento (em uma linha, não em duas) forçando o ID mais baixo
x_id1
e o ID mais alto nax_id2
coluna. Parece mais fácil de implementar, mas geralmente leva a consultas mais complexas posteriormente:fonte