Myślę, że tytuł jest oczywisty. Jak utworzyć strukturę tabeli w PostgreSQL, aby utworzyć relację wiele do wielu.
Mój przykład:
Product(name, price);
Bill(name, date, Products);
Myślę, że tytuł jest oczywisty. Jak utworzyć strukturę tabeli w PostgreSQL, aby utworzyć relację wiele do wielu.
Mój przykład:
Product(name, price);
Bill(name, date, Products);
Odpowiedzi:
Instrukcje SQL DDL (język definicji danych) mogą wyglądać następująco:
CREATE TABLE product (
product_id serial PRIMARY KEY -- implicit primary key constraint
, product text NOT NULL
, price numeric NOT NULL DEFAULT 0
);
CREATE TABLE bill (
bill_id serial PRIMARY KEY
, bill text NOT NULL
, billdate date NOT NULL DEFAULT CURRENT_DATE
);
CREATE TABLE bill_product (
bill_id int REFERENCES bill (bill_id) ON UPDATE CASCADE ON DELETE CASCADE
, product_id int REFERENCES product (product_id) ON UPDATE CASCADE
, amount numeric NOT NULL DEFAULT 1
, CONSTRAINT bill_product_pkey PRIMARY KEY (bill_id, product_id) -- explicit pk
);
Dokonałem kilku poprawek:
N: m związek jest zwykle realizowane przez oddzielne stole - bill_product
w tym przypadku.
Dodałem serial
kolumny jako zastępcze klucze podstawowe . W Postgres 10 lub nowszym rozważmy zamiast tego IDENTITY
kolumnę . Widzieć:
Bardzo to polecam, ponieważ nazwa produktu nie jest unikalna (nie jest dobrym „naturalnym kluczem”). Ponadto wymuszanie niepowtarzalności i odwoływanie się do kolumny w kluczach obcych jest zwykle tańsze w przypadku 4-bajtowego integer
(lub nawet 8-bajtowego bigint
) niż w przypadku ciągu przechowywanego jako text
lub varchar
.
Nie używaj nazw podstawowych typów danych, takich date
jak identyfikatory . Chociaż jest to możliwe, jest to zły styl i prowadzi do mylących błędów i komunikatów o błędach. Użyj prawidłowych, małych liter, niecytowanych identyfikatorów . Nigdy nie używaj słów zastrzeżonych i unikaj podwójnych cudzysłowów mieszanych identyfikatorów wielkości liter, jeśli możesz.
„imię” nie jest dobrym imieniem. Zmieniłem nazwę kolumny tabeli product
na product
( product_name
lub podobną). To jest lepsza konwencja nazewnictwa . W przeciwnym razie, kiedy łączysz kilka tabel w zapytaniu - co robisz dużo w relacyjnej bazie danych - kończysz z wieloma kolumnami o nazwie „nazwa” i musisz użyć aliasów kolumn, aby uporządkować bałagan. To nie jest pomocne. Innym szeroko rozpowszechnionym anty-wzorcem byłby po prostu „id” jako nazwa kolumny.
Nie jestem pewien, jak bill
miałoby się nazywać . bill_id
w tym przypadku prawdopodobnie wystarczy.
price
jest typu danych numeric
do przechowywania liczb ułamkowych dokładnie tak, jak zostały wprowadzone (typ o dowolnej precyzji zamiast typu zmiennoprzecinkowego). Jeśli zajmujesz się wyłącznie liczbami całkowitymi, zrób to integer
. Na przykład możesz zapisać ceny w centach .
amount
( "Products"
W pytaniu) przechodzi w tabeli łączącej bill_product
i jest typu numeric
, jak również. Ponownie, integer
jeśli masz do czynienia wyłącznie z liczbami całkowitymi.
Widać kluczy obcych w bill_product
? I stworzył zarówno do zmian kaskadowych: ON UPDATE CASCADE
. Jeśli a product_id
lub bill_id
powinno się zmienić, zmiana jest kaskadowana do wszystkich zależnych wpisów w bill_product
i nic się nie psuje. To tylko odniesienia bez własnego znaczenia.
Użyłem również ON DELETE CASCADE
do bill_id
: Jeśli rachunek zostanie usunięty, jego szczegóły umrą wraz z nim.
Nie dotyczy to produktów: nie chcesz usuwać produktu, który jest używany na rachunku. Postgres zgłosi błąd, jeśli spróbujesz tego. Zamiast tego można dodać kolejną kolumnę do, product
aby zaznaczyć przestarzałe wiersze („usuwanie nietrwałe”).
Wszystkie kolumny w tym podstawowym przykładzie kończą się wartościami NOT NULL
, więc NULL
wartości nie są dozwolone. (Tak, wszystkie kolumny - kolumny klucza podstawowego są definiowane UNIQUE NOT NULL
automatycznie). Dzieje się tak, ponieważ NULL
wartości nie miałyby sensu w żadnej z kolumn. Ułatwia życie początkującym. Ale nie uciekniesz tak łatwo, i tak musisz zrozumieć NULL
obsługę . Dodatkowe kolumny mogą zezwalać na NULL
wartości, funkcje i łączenia mogą wprowadzać NULL
wartości w zapytaniach itp.
Przeczytaj rozdział CREATE TABLE
w instrukcji .
Klucze podstawowe są implementowane z unikalnym indeksem w kolumnach kluczy, co sprawia, że zapytania z warunkami w kolumnach PK są szybkie. Jednak sekwencja kolumn kluczy jest odpowiednia w przypadku kluczy wielokolumnowych. Ponieważ PK bill_product
jest włączony (bill_id, product_id)
w moim przykładzie, możesz chcieć dodać kolejny indeks tylko product_id
lub (product_id, bill_id)
jeśli masz zapytania szukające podanego product_id
i nie bill_id
. Widzieć:
Przeczytaj rozdział dotyczący indeksów w instrukcji .
bill_product
? Normalnie powinno to wyglądać tak: CREATE INDEX idx_bill_product_id ON booked_rates(bill_id, product_id)
. Czy to jest poprawne?
bill
. Potrzebujemy kwoty za dodany przedmiot w bill_product
.