2015-02-05 6:39 GMT-02:00 Flavio Henrique Araque Gurgel <[email protected]>:
> 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.
>
hm... Agora me confundi, não sei entendi bem como isso funcionaria.
Vamos imaginar o seguinte, temos uma nota com B.ID=3 e um orçamento com C.ID=4,
na tabela A você teria então diversos registros com A.ID=3 e vários com A.ID=4.
O problema é, se você tem duas FKs da coluna A.ID para B.ID e C.ID, quando
A.ID for 3 a FK para C.ID vai ser violada, e quando A.ID=4 a FK para B.ID é
que será violada. Exemplo:
postgres=# CREATE TEMP TABLE b(id integer PRIMARY KEY);
CREATE TABLE
postgres=# INSERT INTO b VALUES(3);
INSERT 0 1
postgres=# CREATE TEMP TABLE c(id integer PRIMARY KEY);
CREATE TABLE
postgres=# INSERT INTO c VALUES(4);
INSERT 0 1
postgres=# CREATE TEMP TABLE a(id integer, FOREIGN KEY (id) REFERENCES
b(id), FOREIGN KEY (id) REFERENCES c(id));
CREATE TABLE
postgres=# INSERT INTO a VALUES(3);
ERROR: 23503: insert or update on table "a" violates foreign key
constraint "a_id_fkey1"
DETAIL: Key (id)=(3) is not present in table "c".
SCHEMA NAME: pg_temp_2
TABLE NAME: a
CONSTRAINT NAME: a_id_fkey1
LOCATION: ri_ReportViolation, ri_triggers.c:3232
postgres=# INSERT INTO a VALUES(4);
ERROR: 23503: insert or update on table "a" violates foreign key
constraint "a_id_fkey"
DETAIL: Key (id)=(4) is not present in table "b".
SCHEMA NAME: pg_temp_2
TABLE NAME: a
CONSTRAINT NAME: a_id_fkey
LOCATION: ri_ReportViolation, ri_triggers.c:3232
Estou entendendo que B e C são disjuntas, assim sendo eu diria para ter uma
outra tabela, vamos chamá-la de D (talvez "Pedidos" no exemplo?), que terá
as informações em comum de ambas as tabelas B e C (por exemplo, data de
lançamento, cliente, etc.) e ambas tabelas B e C tem FKs para D, da mesma
forma que A tem FK para D. Deve ser então garantido de outra forma que o ID
em A esteja correspondendo corretamente em B para nota ou C para
orçamentos, nesse caso podemos adicionar mais duas colunas em A uma com FK
para cada um e garantir com trigger que elas tenham o mesmo ID que a coluna
referenciando D ou que sejam NULL. Nesse caso as tabelas do meu exemplo
ficariam como (não testei):
CREATE TEMP TABLE d(id integer PRIMARY KEY);
CREATE TEMP TABLE c(id integer PRIMARY KEY REFERENCES d(id));
CREATE TEMP TABLE b(id integer PRIMARY KEY REFERENCES d(id));
CREATE TEMP TABLE a(
id integer PRIMARY KEY REFERENCES d(id),
b_id integer REFERENCES b(id),
c_id integer REFERENCES c(id),
CHECK(b_id IS NULL OR b_id = id),
CHECK(c_id IS NULL OR c_id = id),
CHECK(b_id IS NULL <> c_id IS NULL)
);
Por favor, me corrijam se eu estiver falando alguma besteira... ;-)
Atenciosamente,
--
Matheus de Oliveira
Analista de Banco de Dados
Dextra Sistemas - MPS.Br nível F!
www.dextra.com.br/postgres
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral