Příkazy SQL DDL (data definition language) mohou vypadat takto:
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
);
Udělal jsem pár úprav:
-
Vztah n:m je obvykle implementován samostatnou tabulkou -
bill_productv tomto případě. -
Přidal jsem
serialsloupce jako náhradní primární klíče . V Postgres 10 nebo novějších zvažteIDENTITYsloupec místo toho. Viz:- Bezpečně přejmenovávejte tabulky pomocí sloupců sériového primárního klíče
- Automaticky zvyšovat sloupec tabulky
- https://www.2ndquadrant.com/en/blog/postgresql-10-identity-columns/
Vřele to doporučuji, protože název produktu je stěží jedinečný (není dobrý „přirozený klíč“). Také vynucení jedinečnosti a odkazování na sloupec v cizích klíčích je obvykle levnější se 4bajtovým
integer(nebo dokonce 8bajtovýbigint) než s řetězcem uloženým jakotextnebovarchar. -
Nepoužívejte názvy základních datových typů jako
datejako identifikátory . I když je to možné, je to špatný styl a vede k matoucím chybám a chybovým zprávám. Používejte legální identifikátory s malými písmeny, bez uvozovek. Nikdy nepoužívejte vyhrazená slova a pokud můžete, vyhýbejte se dvojitým uvozovkám a smíšeným identifikátorům velkých a malých písmen. -
"jméno" není dobré jméno. Sloupec tabulky jsem přejmenoval na
productbýtproduct(neboproduct_namenebo podobné). To je lepší konvence pojmenování . V opačném případě, když spojíte několik tabulek v dotazu – což děláte hodně v relační databázi – skončíte s více sloupci s názvem „jméno“ a budete muset použít aliasy sloupců k vyřešení nepořádku. To není užitečné. Dalším rozšířeným anti-vzorem by bylo pouze „id“ jako název sloupce.
Nejsem si jistý, jak se jmenujebillbylo by.bill_idv tomto případě pravděpodobně postačí. -
priceje datového typunumericukládat zlomková čísla přesně tak, jak jsou zadána (typ s libovolnou přesností místo typu s plovoucí desetinnou čárkou). Pokud se zabýváte výhradně celými čísly, udělejte totointeger. Můžete například uložit ceny v centech . -
amount("Products"ve vaší otázce) přejde do propojovací tabulkybill_producta je typunumerictaké. Opětintegerpokud pracujete výhradně s celými čísly. -
Vidíte cizí klíče v
bill_product? Vytvořil jsem oba pro kaskádové změny:ON UPDATE CASCADE. Pokudproduct_idnebobill_idby se měla změnit, změna se promítne do všech závislých položek vbill_producta nic se nezlomí. To jsou jen odkazy bez vlastního významu.
Také jsem použilON DELETE CASCADEprobill_id:Pokud je účtenka smazána, její detaily zemřou spolu s ní.
Ne tak pro produkty:Nechcete smazat produkt, který je použit na účtence. Pokud se o to pokusíte, Postgres vyvolá chybu. Doproductbyste přidali další sloupec místo toho označit zastaralé řádky („soft-delete“). -
Všechny sloupce v tomto základním příkladu skončí jako
NOT NULL, takžeNULLhodnoty nejsou povoleny. (Ano, vše sloupce - sloupce primárního klíče jsou definoványUNIQUE NOT NULLautomaticky.) To proto, žeNULLhodnoty by nedávaly smysl v žádném ze sloupců. Usnadňuje život začátečníka. Ale tak snadno se nedostanete, musíte pochopitNULLmanipulace stejně. Další sloupce mohou umožnitNULLhodnoty, funkce a spojení mohou zavádětNULLhodnoty v dotazech atd. -
Přečtěte si kapitolu
CREATE TABLEv návodu. -
Primární klíče jsou implementovány s jedinečným indexem na klíčových sloupcích, díky čemuž jsou dotazy s podmínkami ve sloupcích PK rychlé. Pořadí klíčových sloupců je však relevantní ve vícesloupcových klíčích. Od PK na
bill_productje na(bill_id, product_id)v mém příkladu možná budete chtít přidat další index pouze naproduct_idnebo(product_id, bill_id)pokud máte dotazy týkající se danéhoproduct_ida žádnébill_id. Viz:- Složený primární klíč PostgreSQL
- Je složený index vhodný také pro dotazy na první pole?
- Práce s indexy v PostgreSQL
-
Přečtěte si kapitolu o rejstřících v příručce.