If data integrity is critical for your systems, you should be using UUIDs for keys. True, they take up a bit more space in storage and memory and aren’t quite as fast. But since UUIDs are by definition unique, your data is more likely to be consistent.

An example:

begin;
create table products (product_id serial primary key);
create table orders   (order_id serial primary key,
                       product_id integer references products not null);

insert into products values (default), (default);
insert into orders (product_id)  select product_id from products;
insert into orders (product_id)  select order_id from orders; -- OOPS! This worked! Should've failed!

We accidently inserted bad data into the orders table in that second insert. We should’ve been selecting from the products table, not the orders table. But because the primary keys of products and orders share the same values, postgresql didn’t complain and let us insert incorrect data.

Let’s fix this.

begin;
create extension "uuid-ossp";
create table products (product_id  uuid primary key default uuid_generate_v4());
create table orders   (order_id    uuid primary key default uuid_generate_v4(),
                      product_id   uuid references products not null);

insert into products values (default), (default);
insert into orders (product_id)  select product_id from products;
insert into orders (product_id)  select order_id from orders;  -- HOORAY! This failed to insert.

-- The above insert fails with:
-- ERROR:  insert or update on table "orders" violates foreign key constraint "orders_product_id_fkey"
-- DETAIL:  Key (product_id)=(a593fdde-e172-4546-8e7a-174a5bd9d94b) is not present in table "products".

Now we aren’t allowed to insert an incorrect product_id into the orders table.

For more information on UUIDs in postgres:

comments powered by Disqus