Many MySQL DBAs have expressed interest in learning about PostgreSQL and this series is a guided tour through the basics. One of the ‘Wow! That is Different!’ things for MySQL DBAs looking at PostgreSQL are sequences. Sequences can be used as a rough equivalent to MySQL’s AUTO_INCREMENT but that is only part of the story. Sequences are much more than just for auto-incrementing columns. And the video can be found here.
SERIAL != SERIAL
First, PostgreSQL has a SERIAL data type. They are defined as SMALLSERIAL, SERIAL, and BIGSERIAL that consume two, four, or eight bytes of memory. And respectively they count up to 32,767 or 2,147,483,647, or 9,223,372,036,854,775,807.
MySQL has a keyword named SERIAL that is shorthand for BIGINT NOT NULL AUTO_INCREMENT UNIQUE.
For the first example, we can create a smile table.
1 2 3 4 5 6 7 8 9 10 11 12 13 | dvdrental=# CREATE SCHEMA test; CREATE SCHEMA dvdrental=# \c test You are now connected to database "test" as user "percona". test=# CREATE TABLE x (x SERIAL, y CHAR(20), z CHAR(20)); CREATE TABLE test=# \d x Table "public.x" Column | Type | Collation | Nullable | Default --------+---------------+-----------+----------+------------------------------ x | integer | | not null | nextval('<span style="color: #ff0000;">x_x_seq</span>'::regclass) y | character(20) | | | z | character(20) | | | |
Column x gets a default value from a sequence named x_x_seq using the NEXTVAL() function.
Then we can add some simple data.
1 2 3 4 5 6 7 8 | test=# INSERT INTO X (y,z) VALUES (100,200),(300,450); INSERT 0 2 test=# SELECT * FROM x; x | y | z ---+----------------------+---------------------- 1 | 100 | 200 2 | 300 | 450 (2 rows) |
Note that we did not enter any values for column x and that the server supplied the value from the x_x_seq sequence. Use \d to see that the table and the sequence were created together.
1 2 3 4 5 6 | test=# \d List of relations Schema | Name | Type | Owner --------+---------+----------+--------- public | x | table | percona public | x_x_seq | sequence | percona |
Sequences by themselves
But sequences can be declared without a table. In the following example, a sequence is created that will start at 1,001. To fetch the next value from the sequence and increment that sequence, use the NEXTVAL() function.
1 2 3 4 5 6 7 8 9 10 11 12 13 | test=# CREATE SEQUENCE order_id START 1001; CREATE SEQUENCE test=# SELECT NEXTVAL('order_id'); nextval --------- 1001 (1 row) test=# SELECT NEXTVAL('order_id'); nextval --------- 1002 (1 row) |
There are two ways to check the current count. The first is to query the sequence directly:
1 2 3 4 5 | test=# select * from order_id; last_value | log_cnt | is_called ------------+---------+----------- 1002 | 31 | t (1 row) |
Ignore all the columns except for the last_value, at least for now. Or use the CUIRRVAL() function.
1 2 3 4 5 | test=# select currval('order_id'); currval --------- 1003 (1 row) |
Sequences are not series
A Series, as the name implies, is a series of numbers. But they can not be referenced like a sequence can to the automatic valuation of a column. But they are very handy for generating data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | test=# create table test1 as (select generate_series(1,100) as id); SELECT 100 test=# \d test1 Table "public.test1" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- id | integer | | | test=#<strong> select * from test1 limit 5;</strong> id ---- 1 2 3 4 5 (5 rows) |
Wrap-around sequences
Sequences can start or end at numbers you desire and can also wrap around to start again if you use the CYCLE qualifier. Here we create a repeating sequence of one or two that wraps around.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | test=# create sequence wrap_seq as int minvalue 1 maxvalue 2 CYCLE; CREATE SEQUENCE test=# select NEXTVAL('wrap_seq'); nextval --------- 1 (1 row) test=# select NEXTVAL('wrap_seq'); nextval --------- 2 (1 row) test=# select NEXTVAL('wrap_seq'); nextval --------- 1 (1 row) test=# select NEXTVAL('wrap_seq'); nextval --------- 2 (1 row) |
The details
Information on the status of a sequence can be had by using \d.
1 2 3 4 5 6 7 8 9 10 11 | test=# \d order_id; Sequence "public.order_id" Type | Start | Minimum | Maximum | Increment | Cycles? | Cache --------+-------+---------+---------------------+-----------+---------+------- bigint | 1001 | 1 | 9223372036854775807 | 1 | no | 1 test=# \d wrap_seq; Sequence "public.wrap_seq" Type | Start | Minimum | Maximum | Increment | Cycles? | Cache ---------+-------+---------+---------+-----------+---------+------- integer | 1 | 1 | 2 | 1 | yes | 1 |
Next episode — Explaining EXPLAIN
Stay tuned!
The past videos for PostgreSQL for MySQL Database Administrators (DBA) can be found here: episode one, episode two, episode three, and episode four.