sql >> Database teknologi >  >> RDS >> PostgreSQL

PostgreSQL 12:Fremmednøgler og opdelte tabeller

Nu hvor PostgreSQL 12 er ude, anser vi fremmednøgler for at være fuldt kompatible med partitionerede tabeller. Du kan have en partitioneret tabel på hver side af en fremmednøglebegrænsning, og alt vil fungere korrekt.

Hvorfor påpeger jeg dette? To grunde:For det første, da partitionerede tabeller først blev introduceret i PostgreSQL 10, understøttede de slet ikke fremmednøgler; du kunne ikke oprette FK'er på partitionerede tabeller, og du kunne heller ikke oprette FK'er, der refererede til en partitioneret tabel. For det andet fordi funktionen (tidligere dage) tabelarv heller ikke rigtig understøttede fremmednøgler. Alt dette betyder, at det for første gang er muligt i PostgreSQL at vedligeholde store mængder data og samtidig bevare referenceintegriteten. Nu hvor denne funktion er færdig, er nogle nye use cases åbne for PostgreSQL, som tidligere ikke var.

Her er et ret trivielt eksempel.

CREATE TABLE items (
    item_id integer PRIMARY KEY,
    description text NOT NULL
) PARTITION BY hash (item_id);
CREATE TABLE items_0 PARTITION OF items FOR VALUES WITH (modulus 3, remainder 0);
CREATE TABLE items_1 PARTITION OF items FOR VALUES WITH (modulus 3, remainder 1);
CREATE TABLE items_2 PARTITION OF items FOR VALUES WITH (modulus 3, remainder 2);

CREATE TABLE warehouses (warehouse_id integer primary key, location text not null);

CREATE TABLE stock (
    item_id integer not null REFERENCES items,
    warehouse_id integer not null REFERENCES warehouses,
    amount int not null
) partition by hash (warehouse_id);
CREATE TABLE stock_0 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 0);
CREATE TABLE stock_1 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 1);
CREATE TABLE stock_2 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 2);
CREATE TABLE stock_3 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 3);
CREATE TABLE stock_4 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 4);

Du kan se, at der er to fremmednøgler her. Man peger på en almindelig (ikke opdelt) tabel varehuse , de andre peger på opdelte tabel elementer . Har du bemærket, at hver fremmed nøgle kun erklæres én gang?

Der er to grundlæggende handlinger, som du ønsker, at den fremmede nøgle skal levere. Først, hvis du indsætter en række i lager (den henvisning tabel), der ikke har en tilsvarende række i elementer eller varehuse (den henviste tabel), skal der rejses en fejl. For det andet, hvis du sletter en række i en af ​​de refererede tabeller, og der er matchende rækker i lager , den operation skal også afvises.

Begge kan nemt verificeres:

INSERT INTO stock values (1, 1, 10);
ERROR:  insert or update on table "stock_0" violates foreign key constraint "stock_item_id_fkey"
DETAIL:  Key (item_id)=(1) is not present in table "items".

Godt. Derefter kan du indsætte matchende rækker i både refererede tabeller og en referencerække. Derefter vil en sletning i en af ​​de refererede tabeller mislykkes, som forventet.

INSERT INTO items VALUES (1, 'item 1');
INSERT INTO warehouses VALUES (1, 'The moon');
INSERT INTO stock VALUES (1, 1, 10);

DELETE FROM warehouses;
ERROR:  update or delete on table "warehouses" violates foreign key constraint "stock_warehouse_id_fkey" on table "stock"
DETAIL:  Key (warehouse_id)=(1) is still referenced from table "stock".

DELETE FROM items;
ERROR:  update or delete on table "items_2" violates foreign key constraint "stock_item_id_fkey3" on table "stock"
DETAIL:  Key (item_id)=(1) is still referenced from table "stock".

(Selvfølgelig en OPDATERING operation er for den tidligere operation det samme som en INSERT , og for sidstnævnte operation det samme som en DELETE — hvilket betyder, at både den originale tuple og den ændrede tuple skal kontrolleres, hvis OPDATERING ændrer kolonnerne involveret i fremmednøglen.)

Hvis disse eksempler virker dårlige for erfarne brugere, er det fordi disse ting fungerer nøjagtigt det samme for almindelige (ikke opdelte) tabeller siden umindelige tider.

Ved reel brug vil du have brug for indekser i referencekolonnerne i aktien tabel, hvis du nogensinde ændrer de refererede tabeller. Dette skyldes, at serveren skal finde disse referencerækker for at vide, om den skal smide en fejl eller sådan. Du kan nemt nok gøre det med den opdelte referencetabel:

CREATE INDEX ON stock (item_id);
CREATE INDEX ON stock (warehouse_id);

I dette indlæg har jeg vist det grundlæggende i fremmednøgler, og hvordan de kan bruges på partitionerede tabeller ligesom de kan på almindelige tabeller. I et efterfølgende indlæg vil jeg dække et par ekstra funktioner af dem. Fortæl mig i en kommentar, hvis du kan lide denne PostgreSQL 12-forbedring!


  1. Sende liste<> til SQL Stored Procedure

  2. Unik begrænsning på kombination af to kolonner?

  3. INDLEDE DATAINFIL nemt konvertere ÅÅÅÅMMDD til ÅÅÅÅ-MM-DD?

  4. MySQL:Opdel kommasepareret liste i flere rækker