Nu PostgreSQL 12 uit is, beschouwen we externe sleutels als volledig compatibel met gepartitioneerde tabellen. Je kunt een gepartitioneerde tabel hebben aan weerszijden van een externe sleutelbeperking, en alles zal correct werken.
Waarom wijs ik hierop? Twee redenen:ten eerste, toen gepartitioneerde tabellen voor het eerst werden geïntroduceerd in PostgreSQL 10, ondersteunden ze helemaal geen externe sleutels; je kon geen FK's maken op gepartitioneerde tabellen, noch FK's maken die verwijzen naar een gepartitioneerde tabel. Ten tweede, omdat de (vroegere) functie voor het overnemen van tabellen ook niet echt buitenlandse sleutels ondersteunde. Dit alles betekent dat het voor het eerst in PostgreSQL mogelijk is om grote hoeveelheden data te onderhouden met behoud van referentiële integriteit. Nu deze functie is voltooid, staan er enkele nieuwe gebruiksscenario's open voor PostgreSQL die dat voorheen niet waren.
Hier is een vrij triviaal voorbeeld.
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);
U kunt hier zien dat er twee externe sleutels zijn. Men wijst naar een gewone (niet gepartitioneerde) tabel magazijnen , de andere verwijst naar gepartitioneerde tabel items . Is het je opgevallen dat elke externe sleutel maar één keer wordt gedeclareerd?
Er zijn twee basisbewerkingen die u met de externe sleutel wilt uitvoeren. Ten eerste, als u een rij invoegt in voorraad (de verwijzing tabel) die geen overeenkomstige rij heeft in items of magazijnen (de verwezen tabel), moet er een fout worden gemaakt. Ten tweede, als u een rij verwijdert in een van beide tabellen waarnaar wordt verwezen en er zijn overeenkomende rijen in voorraad , moet die bewerking ook worden afgewezen.
Beide zijn eenvoudig te verifiëren:
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".
Goed. Vervolgens kunt u overeenkomende rijen invoegen in zowel tabellen waarnaar wordt verwezen als een verwijzende rij. Daarna zal een verwijdering in een van de tabellen waarnaar wordt verwezen, mislukken, zoals verwacht.
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".
(Natuurlijk een UPDATE bewerking is voor de vorige bewerking hetzelfde als een INSERT , en voor de laatste bewerking hetzelfde als een DELETE — wat betekent dat zowel de originele tuple als de gewijzigde tuple moeten worden gecontroleerd, als de UPDATE wijzigt de kolommen die betrokken zijn bij de externe sleutel.)
Als deze voorbeelden voor ervaren gebruikers zwak lijken, komt dat omdat deze dingen sinds onheuglijke tijden precies hetzelfde werken voor gewone (niet gepartitioneerde) tabellen.
In echt gebruik zou u indexen nodig hebben in de referentiekolommen in de aandelen tabel, als u ooit de tabellen waarnaar wordt verwezen, wijzigt. Dit komt omdat de server die verwijzende rijen moet lokaliseren om te weten of er een fout of iets dergelijks optreedt. U kunt dat eenvoudig genoeg doen met de gepartitioneerde referentietabel:
CREATE INDEX ON stock (item_id); CREATE INDEX ON stock (warehouse_id);
In dit bericht heb ik de basis van externe sleutels laten zien en hoe ze kunnen worden gebruikt op gepartitioneerde tabellen, net zoals op gewone tabellen. In een volgende post zal ik een paar extra functies daarvan behandelen. Laat me in een reactie weten of je deze PostgreSQL 12-verbetering leuk vindt!