On 04-02-2015 21:44, Matheus Saraiva wrote:
Em Qua, 2015-02-04 às 13:39 -0200, Matheus de Oliveira escreveu:
2015-02-04 12:50 GMT-02:00 Matheus Saraiva
<[email protected]>:
Um campo 'x' da tabela 'A' pode se relacionar tanto com o
campo 'x' da
tabela 'B' quanto com o campo 'x' da tabela 'C'.
Sei que dá para criar duas chaves separadas na tabela 'A' uma
que
relaciona A(x)=>B(x) e outra que relaciona A(x)=>C(x). Mas na
hora de
incluir, alterar? Isso daria certo? Tipo digamos que na tabela
'C'
exista dados gravados mas a tabela 'B' esteja vazia. Daria
erro na hora
de inserir dados em 'A'? Ou seja, o erro que informa que o
valor
informado em A(x) não existe em B(x)?
Não, não dá certo.
Não entendi o porquê de não dar certo. Uma coluna pode sim referenciar
duas tabelas sem problemas, e o erro retornado pelo PostgreSQL será
exatamente sobre qual tabela o valor não foi encontrado.
O que você tem que fazer é, na tabela A criar dois campos, vamos dizer
B_x e C_x. Daí quando o relacionamento for de A=>B o campo B_x recebe
o valor enquanto o C_x fica com valor NULL (quando um campo é NULL a
FK não é verificada), e vice-versa para A=>C.
Caso você precise forçar que apenas ou um outro esteja no
relacionamento, você pode usar uma CHECK CONSTRAINT. Por exemplo, para
forçar *exatamente* um ter relacionamento você pode usar: CHECK(B_x IS
NULL <> C_x IS NULL).
E se esse além de uma chave estrangeira o campo em 'A' também precisar
ser uma chave primária? Uma tabela não pode ter duas chaves primárias,
além do que uma chave primária não pode ser nula.
Se você precisar de duas chaves de unicidade na mesma tabela isso não é
um problema. Uma chave primária nada mais é do que uma restrição de
unicidade com valores não nulos, então, é só criar uma restrição de
unicidade (CONSTRAINT ... UNIQUE) e forçar que o campo não seja nulo
(NOT NULL). O resultado é o mesmo e você pode ter quantas restrições quiser.
Eu pensei em fazer dessa forma para não ter que criar duas tabelas
individuais uma que se relacionaria com 'B' e outra que se relacionaria
com 'C', pois a única coisa que elas teriam de diferente seria apenas o
nome. Os campos (quantidade, nome, tipos, etc.) seriam os mesmos, até os
dados que serão guardados seriam iguais.
Então faça como você mesmo propôs, duas chaves estrangeiras. Sim,
funciona e acabei de testar aqui pra ter certeza.
Então minha ideia era algo parecido com orientação a objetos. 'A' seria
como um objeto que poderia se relacionar tanto com 'B' como com 'C'. O
problema é a direção do relacionamento, é 'A' quem deve apontar para 'B'
ou 'C' e não o contrário.
Isso não é um problema, você cria ambas as restrições de chave
estrangeira na tabela A.
A modelagem utilizada é análoga à uma nota fiscal e os itens que compõe
a nota. 'B' seria a nota propriamente dita, com os dados do cabeçalho da
nota, já 'A' seria a tabela que conteria os itens da nota. Um produto
(registro) em 'A' apontaria para a nota (registro) em 'B' a qual
pertence.
Agora imagine que a tabela 'C' seria um orçamento. Seria ideal usar a
mesma tabela 'A' pois os itens que estão presentes em uma nota podem ser
utilizados também em um orçamento.
Agora, com sua explicação, pensemos assim, veja se entendi direito
A - Itens de nota
B - Cabeçalho da nota
C - Orçamentos
O que entendo é que você está tentando usar o máximo possível de chaves
naturais, logo, B e C usarão a mesma chave, ou seja, o número de um
orçamento no fim será também o número da nota (o que me parece bizarro
ao pensar mas talvez seu sistema seja particularmente diferente por
alguma razão do seu modelo de negócio).
Logo:
A (coluna_chave) -> B(ID)
A (coluna_chave) -> C(ID)
Isso parece funcionar no modelo. No mundo real é que parece estranho.
Mas pelo visto acho que não tem como, terei que criar tabelas separadas.
Não entendi esta sua afirmação. Colunas separadas talvez façam sentido
em A(orcamento_id, nota_id) por causa do mundo real. Mas se você puder
ter um identificar de nota que seja o mesmo de um orçamento, melhor pra
você.
[]s
Flavio Gurgel
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral