PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да приложим връзка много към много в PostgreSQL?

SQL DDL (език за дефиниция на данни) може да изглежда така:

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
);

Направих няколко корекции:

  • Връзката n:m обикновено се изпълнява от отделна таблица - bill_product в този случай.

  • Добавих serial колони като сурогатни първични ключове . В Postgres 10 или по-нова версия помислете за IDENTITY колона вместо това. Вижте:

    • Безопасно преименувайте таблици с помощта на колони от сериен първичен ключ
    • Колона на таблицата с автоматично увеличение
    • https://www.2ndquadrant.com/en/blog/postgresql-10-identity-columns/

    Горещо препоръчвам това, защото името на даден продукт едва ли е уникално (не е добър "естествен ключ"). Също така, налагането на уникалност и препращане към колоната във външни ключове обикновено е по-евтино с 4-байтово integer (или дори 8-байтов bigint ), отколкото с низ, съхранен като text или varchar .

  • Не използвайте имена на основни типове данни като date като идентификатори . Въпреки че това е възможно, това е лош стил и води до объркващи грешки и съобщения за грешки. Използвайте легални идентификатори с малки букви, които не са в кавички. Никога не използвайте запазени думи и избягвайте двойни кавички, ако можете.

  • "име" не е добро име. Преименувах колоната на таблицата product да бъде product (или product_name или подобен). Това е по-добронаименуване . В противен случай, когато се присъедините към няколко таблици в заявка - което правите много в релационна база данни - в крайна сметка получавате множество колони с име "име" и трябва да използвате псевдоними на колони, за да разрешите бъркотията. Това не е полезно. Друг широко разпространен анти-модел би бил просто "id" като име на колона.
    Не съм сигурен какво е името на bill би било. bill_id вероятно ще бъде достатъчно в този случай.

  • price е от тип данни numeric за съхраняване на дробни числа точно както са въведени (тип с произволна точност вместо тип с плаваща запетая). Ако работите изключително с цели числа, направете това integer . Например, можете да запазите цени като цента .

  • amount ("Products" във вашия въпрос) отива в таблицата за свързване bill_product и е от тип numeric също така. Отново integer ако работите изключително с цели числа.

  • Виждате външните ключове в bill_product ? Създадох и двете за каскадна промяна:ON UPDATE CASCADE . Ако product_id или bill_id трябва да се промени, промяната е каскадна към всички зависими записи в bill_product и нищо не се счупва. Това са само препратки без собствено значение.
    Използвах и ON DELETE CASCADE за bill_id :Ако сметката бъде изтрита, нейните детайли умират заедно с нея.
    Не е така за продуктите:Не искате да изтриете продукт, който се използва в сметката. Postgres ще изведе грешка, ако опитате това. Бихте добавили друга колона към product вместо това да маркирате остарели редове („soft-delete“).

  • Всички колони в този основен пример се оказват NOT NULL , така че NULL стойности не са разрешени. (Да, всички колони - колоните с първичен ключ са дефинирани UNIQUE NOT NULL автоматично.) Това е защото NULL стойностите няма да имат смисъл в нито една от колоните. Това улеснява живота на начинаещия. Но няма да се измъкнете толкова лесно, трябва да разберете NULL боравене така или иначе. Допълнителните колони може да позволяват NULL стойности, функции и съединения могат да въвеждат NULL стойности в заявки и др.

  • Прочетете главата за CREATE TABLE в ръководството.

  • Първичните ключове се реализират с уникален индекс на ключовите колони, което прави заявките с условия в колоната(ите) на PK бързо. Въпреки това, последователността на ключовите колони е уместна в многоколонните ключове. Тъй като PK на bill_product е на (bill_id, product_id) в моя пример може да искате да добавите друг индекс само към product_id или (product_id, bill_id) ако имате заявки, търсещи даден product_id и без bill_id . Вижте:

    • Сложен първичен ключ на PostgreSQL
    • Съставният индекс добър ли е и за заявки в първото поле?
    • Работа с индекси в PostgreSQL
  • Прочетете главата за индексите в ръководството.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да получа текущото име на часовата зона в Postgres 9.3?

  2. Групиран LIMIT в PostgreSQL:показване на първите N реда за всяка група?

  3. Експортирайте конкретни редове от PostgreSQL таблица като INSERT SQL скрипт

  4. Клаузата CHECK за обновяеми изгледи

  5. Как да създадете Postgres таблица с уникален комбиниран първичен ключ?