• Twitter
  • LinkedIn
  • Facebook
  • Youtube
  • Mail
  • English
    • French
    • Italian
    • Spanish
    • German
2ndQuadrant | PostgreSQL
PostgreSQL Solutions for the Enterprise
  • Contact Us
  • Support & Services
    • Support
      • 24/7 Production Support
      • Developer Support
      • IBM Z Production Support
    • DBA Services
      • Remote DBA
      • Database Monitoring
    • Consulting Services
      • Health Check
      • Performance Tuning
      • Database Security Audit
      • PostgreSQL Upgrade
    • Migration Services
      • Migrate to PostgreSQL
      • Migration Assessment
  • Products
    • HA Postgres Clusters
    • Postgres-BDR
    • 2ndQPostgres
    • pglogical
      • Installation instruction for pglogical
      • Documentation
    • repmgr
      • Installation instruction for repmgr
    • Barman
    • Postgres Cloud Manager
    • SQL Firewall
    • Postgres-XL
    • OmniDB
    • Postgres Installer
    • 2UDA
  • Downloads
    • Whitepapers
      • Highly Available Postgres Clusters
      • AlwaysOn Postgres
      • Postgres-BDR
      • PostgreSQL Security Best Practices
    • Case Studies
      • Performance Tuning
        • BenchPrep
        • tastyworks
      • Distributed Clusters
        • European Space Agency (ESA)
        • Telefónica del Sur
        • Animal Logic
      • Database Administration
        • Agilis Systems
      • Professional Training
        • Met Office
        • London & Partners
      • Database Upgrades
        • Alfred Wegener Institute (AWI)
      • Database Migration
        • Healthcare Software Solutions (HSS)
        • Navionics
    • Installers
      • Postgres Installer
      • 2UDA – Unified Data Analytics
  • Training
    • Training Catalog and Scheduled Courses
      • Advanced Development & Performance
      • Linux for PostgreSQL DBAs
      • Postgres-BDR
      • PostgreSQL Database Administration
      • PostgreSQL Data Warehousing & Partitioning
      • PostgreSQL for Developers
      • PostgreSQL Immersion
      • PostgreSQL Immersion for Cloud Databases
      • PostgreSQL Security
      • Postgres-XL-10
      • Practical SQL
      • Replication, Backup & Disaster Recovery
    • PostgreSQL Training Chicago
    • PostgreSQL Training London
  • Books
    • PostgreSQL 11 Administration Cookbook
    • PostgreSQL 10 Administration Cookbook
    • PostgreSQL High Availability Cookbook – 2nd Edition
    • PostgreSQL 9 Administration Cookbook – 3rd Edition
    • PostgreSQL Server Programming Cookbook – 2nd Edition
    • PostgreSQL 9 Cookbook – Chinese Edition
  • PostgreSQL
    • PostgreSQL – History
    • 2ndQuadrant’s Passion for PostgreSQL
    • Who uses PostgreSQL?
    • PostgreSQL FAQ
    • PostgreSQL vs MySQL
    • Business Case for PostgreSQL
    • Security Information
  • Webinars
    • Using SSL with PostgreSQL and pgbouncer
  • About Us
    • About 2ndQuadrant
    • What Does “2ndQuadrant” Mean?
    • News
    • Events
    • Careers
    • Team Profile
  • Blog
  • Menu
You are here: Home / Blog / 2ndQuadrant / PostgreSQL 12: Foreign Keys and Partitioned Tables
PostgreSQL 12 Foreign Keys and Partitioned Tables
alvherre

PostgreSQL 12: Foreign Keys and Partitioned Tables

October 14, 2019/0 Comments/in 2ndQuadrant, Alvaro's PlanetPostgreSQL, PostgreSQL /by alvherre

Now that PostgreSQL 12 is out, we consider foreign keys to be fully compatible with partitioned tables. You can have a partitioned table on either side of a foreign key constraint, and everything will work correctly.

Why do I point this out? Two reasons: first, when partitioned tables were first introduced in PostgreSQL 10, they didn’t support foreign keys at all; you couldn’t create FKs on partitioned tables, nor create FKs that referenced a partitioned table. Second, because the (early days) table inheritance feature didn’t really support foreign keys either. All this means that for the first time it is possible in PostgreSQL to maintain large volumes of data while maintaining referential integrity.  Now that this feature is complete, some new use cases are open to PostgreSQL that previously weren’t.

Here’s a pretty trivial example.

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

You can see there are two foreign keys here. One points to to a regular (not partitioned) table warehouses, the other points to partitioned table items. Did you notice that each foreign key is only declared once?

There are two basic operations that you want the foreign key to provide. First, if you insert a row in stock (the referencing table) that doesn’t have a corresponding row in items or warehouses (the referenced table), an error must be raised. Second, if you delete a row in either referenced table and there are matching rows in stock, that operation must be rejected too.

Both are easily verified:

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".

Good. Then you can insert matching rows in both referenced tables and a referencing row.  After that, a delete in either of the referenced tables will fail, as expected.

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".

(Of course, an UPDATE operation is for the former operation the same as an INSERT, and for the latter operation the same as a DELETE — meaning that both the original tuple and the modified tuple must be checked, if the UPDATE modifies the columns involved in the foreign key.)

If these examples seem lame to experienced users, it’s because these things work exactly the same for regular (not partitioned) tables since time immemorial.

In real usage, you would need indexes in the referencing columns in the stock table, if you ever modify the referenced tables. This is because the server needs to locate those referencing rows in order to know to throw an error or such. You can do that with the partitioned referencing table easily enough:

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

In this post I have shown the basics of foreign keys, and how they can be used on partitioned tables just like they can on regular tables. In a subsequent post I’ll cover a couple of additional features of those. Let me know in a comment if you like this PostgreSQL 12 improvement!

Tags: PG12
Share this entry
  • Share on Facebook
  • Share on Twitter
  • Share on WhatsApp
  • Share on LinkedIn
0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Search

Recent Posts

  • Postgres-BDR: It is also about fast safe upgrades October 15, 2019
  • Managing another PostgreSQL Commitfest October 15, 2019
  • PostgreSQL 12: Foreign Keys and Partitioned Tables October 14, 2019
  • A convenient way to launch psql against postgres while running pg_regress October 10, 2019
  • Replication configuration changes in PostgreSQL 12 October 7, 2019

Featured External Blogs

Tomas Vondra's Blog

Our Bloggers

  • Simon Riggs
  • Alvaro Herrera
  • Andrew Dunstan
  • Craig Ringer
  • Francesco Canovai
  • Gabriele Bartolini
  • Giulio Calacoci
  • Ian Barwick
  • Marco Nenciarini
  • Mark Wong
  • Pavan Deolasee
  • Petr Jelinek
  • Shaun Thomas
  • Tomas Vondra
  • Umair Shahid

PostgreSQL Cloud

2QLovesPG 9.6 backup Barman BDR Business Continuity community conference database DBA development devops disaster recovery greenplum Hot Standby JSON JSONB kanban logical decoding logical replication monitoring open source performance PG12 pgbarman pgday pglogical PG Phriday postgres Postgres-BDR postgres-xl PostgreSQL PostgreSQL 9.6 PostgreSQL10 PostgreSQL 11 PostgreSQL11 PostgreSQL 11 New Features postgresql repmgr Recovery release replication sql standby wal webinar
UK +44 (0)870 766 7756

US +1 650 378 1218

Support & Services

24/7 Production Support

Developer Support

Remote DBA for PostgreSQL

PostgreSQL Database Monitoring

PostgreSQL Health Check

PostgreSQL Performance Tuning

Database Security Audit

Upgrade PostgreSQL

PostgreSQL Migration Assessment

Migrate from Oracle to PostgreSQL

Products

HA Postgres Clusters

Postgres-BDR

2ndQPostgres

pglogical

repmgr

Barman

Postgres Cloud Manager

SQL Firewall

Postgres-XL

OmniDB

Postgres Installer

2UDA

Postgres Learning Center

Introducing Postgres

Blog

Webinars

Books

Videos

Training

Case Studies

Events

About Us

About 2ndQuadrant

What does 2ndQuadrant Mean?

News

Careers 

Team Profile

©2001-2019 2ndQuadrant Ltd. All rights reserved | Privacy Policy
  • Twitter
  • LinkedIn
  • Facebook
  • Youtube
  • Mail
A convenient way to launch psql against postgres while running pg_regress A convenient way to launch psql against postgres while running pg_regress Managing another PostgreSQL Commitfest
Scroll to top
×