Eu acredito que o título é autoexplicativo. Como você cria a estrutura da tabela no PostgreSQL para fazer um relacionamento muitos para muitos.
Meu exemplo:
Product(name, price);
Bill(name, date, Products);
sql
database
postgresql
database-design
many-to-many
Radu Gheorghiu
fonte
fonte
Respostas:
As instruções SQL DDL (linguagem de definição de dados) podem ter a seguinte aparência:
Fiz alguns ajustes:
O relacionamento n: m é normalmente implementado por uma tabela separada -
bill_product
neste caso.Eu adicionei
serial
colunas como chaves primárias substitutas . No Postgres 10 ou posterior, considere umaIDENTITY
coluna . Vejo:Eu recomendo fortemente, porque o nome de um produto dificilmente é único (não é uma boa "chave natural"). Além disso, impor exclusividade e referenciar a coluna em chaves estrangeiras é normalmente mais barato com um código de 4 bytes
integer
(ou mesmo 8 bytesbigint
) do que com uma string armazenada comotext
ouvarchar
.Não use nomes de tipos de dados básicos
date
como identificadores . Embora isso seja possível, é um estilo incorreto e leva a erros e mensagens de erro confusos. Use identificadores legais, minúsculas e sem aspas . Nunca use palavras reservadas e evite identificadores de maiúsculas e minúsculas entre aspas, se possível."nome" não é um bom nome. Mudei o nome da coluna da tabela
product
paraproduct
(ouproduct_name
ou similar). Essa é uma convenção de nomenclatura melhor . Caso contrário, quando você junta algumas tabelas em uma consulta - o que você faz muito em um banco de dados relacional - você acaba com várias colunas chamadas "nome" e tem que usar aliases de coluna para resolver a bagunça. Isso não ajuda. Outro antipadrão amplamente difundido seria apenas "id" como nome da coluna.Não tenho certeza de qual seria o nome de a
bill
.bill_id
provavelmente será suficiente neste caso.price
é do tipo de dadosnumeric
para armazenar números fracionários precisamente conforme inseridos (tipo de precisão arbitrária em vez de tipo de ponto flutuante). Se você lida exclusivamente com números inteiros, faça com queinteger
. Por exemplo, você pode economizar preços em centavos .O
amount
("Products"
na sua pergunta) vai para a tabela de ligaçãobill_product
e também é do tiponumeric
. Novamente,integer
se você lidar exclusivamente com números inteiros.Você vê as chaves estrangeiras em
bill_product
? Eu criei tanto a mudanças em cascata:ON UPDATE CASCADE
. Se umproduct_id
oubill_id
deve ser alterado, a alteração é enviada em cascata para todas as entradas dependentes embill_product
e nada é interrompido. Essas são apenas referências sem significado próprio.Eu também usei
ON DELETE CASCADE
parabill_id
: Se uma conta for excluída, seus detalhes morrem com ela.Não é assim para produtos: você não deseja excluir um produto que é usado em uma fatura. O Postgres irá gerar um erro se você tentar isso. Você adicionaria outra coluna para
product
marcar linhas obsoletas ("exclusão reversível").Todas as colunas neste exemplo básico acabam sendo
NOT NULL
, portanto, osNULL
valores não são permitidos. (Sim, todas as colunas - colunas de chave primária são definidasUNIQUE NOT NULL
automaticamente.) Isso porque osNULL
valores não fariam sentido em nenhuma das colunas. Facilita a vida de um iniciante. Mas você não vai escapar tão facilmente, você precisa entender oNULL
manuseio de qualquer maneira. Colunas adicionais podem permitirNULL
valores, funções e junções podem introduzirNULL
valores em consultas etc.Leia o capítulo no
CREATE TABLE
manual .As chaves primárias são implementadas com um índice exclusivo nas colunas de chave, que agiliza as consultas com condições na (s) coluna (s) PK. No entanto, a sequência de colunas-chave é relevante em chaves com várias colunas. Uma vez que o PK ativado
bill_product
está ativado(bill_id, product_id)
no meu exemplo, você pode querer adicionar outro índice apenasproduct_id
ou(product_id, bill_id)
se tiver consultas procurando por um dadoproduct_id
e nãobill_id
. Vejo:Leia o capítulo sobre índices no manual .
fonte
bill_product
? Normalmente ele deve se parece com:CREATE INDEX idx_bill_product_id ON booked_rates(bill_id, product_id)
. Isto está certo?bill
. Precisamos do valor por item adicionado embill_product
.