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_productw tym przypadku.
Dodałem serialkolumny jako zastępcze klucze podstawowe . W Postgres 10 lub nowszym rozważmy zamiast tego IDENTITYkolumnę . 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 textlub varchar.
Nie używaj nazw podstawowych typów danych, takich datejak 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 productna product( product_namelub 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 billmiałoby się nazywać . bill_idw tym przypadku prawdopodobnie wystarczy.
pricejest 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_producti jest typu numeric, jak również. Ponownie, integerjeś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_idlub bill_idpowinno się zmienić, zmiana jest kaskadowana do wszystkich zależnych wpisów w bill_producti nic się nie psuje. To tylko odniesienia bez własnego znaczenia.
Użyłem również ON DELETE CASCADEdo 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, productaby zaznaczyć przestarzałe wiersze („usuwanie nietrwałe”).
Wszystkie kolumny w tym podstawowym przykładzie kończą się wartościami NOT NULL, więc NULLwartości nie są dozwolone. (Tak, wszystkie kolumny - kolumny klucza podstawowego są definiowane UNIQUE NOT NULLautomatycznie). Dzieje się tak, ponieważ NULLwartości nie miałyby sensu w żadnej z kolumn. Ułatwia życie początkującym. Ale nie uciekniesz tak łatwo, i tak musisz zrozumieć NULLobsługę . Dodatkowe kolumny mogą zezwalać na NULLwartości, funkcje i łączenia mogą wprowadzać NULLwartości w zapytaniach itp.
Przeczytaj rozdział CREATE TABLEw 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_productjest włączony (bill_id, product_id)w moim przykładzie, możesz chcieć dodać kolejny indeks tylko product_idlub (product_id, bill_id)jeśli masz zapytania szukające podanego product_idi 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.