postgres identifier primary key uuid - ghdrako/doc_snipets GitHub Wiki
integer/biginteger
CREATE TABLE users (
id integer PRIMARY KEY,
name text NOT NULL
);
INSERT INTO users (id, email, name)
SELECT COUNT(*) + 1, 'new_user' FROM users;
serial/bigserial
The data types smallserial, serial and bigserial
are not true types, but merely a notational convenience for creating unique identifier columns (similar to the AUTO_INCREMENT
property supported by some other databases).
Using a serial column to create the users table would look like this:
CREATE TABLE users (
id serial PRIMARY KEY,
name text NOT NULL
);
INSERT INTO users_serial (name) VALUES ('new user');
Using a serial column is operationally similar to the following SQL:
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
When writing automation that simply iterates through id values, note that serial columns can have gaps, even if you never DELETE (e.x. if an INSERT was rolled back — sequences live outside transactions).
IDENTITY column
serial is PostgreSQL specific (i.e. not SQL standards compliant) but it solved in Postgres 10. Postgres 10 added support for the IDENTITY column syntax in CREATE TABLE
https://www.enterprisedb.com/blog/postgresql-10-identity-columns-explained
CREATE TABLE (
id integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
email citext NOT NULL CHECK (LENGTH(email) < 255),
name text NOT NULL
)
CREATE TABLE sale (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
sold_at TIMESTAMPTZ,
amount INT
);
Instead of using GENERATED BY DEFAULT
, use GENERATED ALWAYS
. It prevent to accidently set fixed value to identity column. It cause problem if the same value next was generated automaticali - duplicate key.
Random Numeric IDs
from secrets import randbelow
# ...
def create_user():
"""
Add new user to the database (using secure random numbers)
"""
user_id = randrange(1, MAX_RANDOM_USER_ID)
user = User(id=user_id, name="new user")
db.save(user)
Random UUIDs
There are a lot of versions of UUID, but let's discuss the ones we're more likely to use/see day to day.
- UUIDv1
Version 1 UUIDs have three two components:
a 60 bit date-time (at nanosecond precision)
a 48 bit [MAC address](https://en.wikipedia.org/wiki/MAC_address)
You can generate v1 UUIDs in Postgres natively thanks to the uuid-ossp contrib module. Here's how to generate a v1 UUID with random MAC address:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION
SELECT uuid_generate_v1mc();
uuid_generate_v1mc
--------------------------------------
dd1bbf10-0b47-11ed-80de-db48f6faaf86
(1 row)
db=# SELECT uuid_generate_v4() AS uuid;
uuid
──────────────────────────────────────
8e55146d-0ce5-40ab-a346-5dbd466ff5f2
Starting at version 13 there is a built-in function to generate random (version 4) UUIDs:
db=# SELECT gen_random_uuid() AS uuid;
uuid
──────────────────────────────────────
ba1ac0f5-5d4d-4d80-974d-521dbdcca2b2
The uuid-ossp
extension is still needed if you want to generate UUIDs other than version 4.