PostgreSQL SERIAL (original) (raw)

Last Updated : 15 Jul, 2025

When working with **PostgreSQL, we need to create tables with unique primary keys. PostgreSQL offers a powerful feature known as the **SERIAL pseudo-type which simplifies generating auto-incrementing sequences for columns.

In this article, we’ll learn about the **PostgreSQL SERIAL pseudo-type by explain how it works and provide practical examples with outputs.

What is PostgreSQL SERIAL?

In **PostgreSQL, the **SERIAL pseudo-type allows you to create an **auto-incrementing integer column, typically used for primary keys.

It automatically generates a sequence of numbers that increase by one for each new row. This feature simplifies the process of creating unique identifiers for each row in a table.

Key Points of PostgreSQL SERIAL:

Types of SERIAL in PostgreSQL

PostgreSQL offers three variations of the **SERIAL pseudo-type, depending on the storage size and value range:

  1. SMALLSERIAL: Uses 2 bytes and supports values from 1 to 32,767.
  2. SERIAL: Uses 4 bytes and supports values from 1 to 2,147,483,647.
  3. BIGSERIAL: Uses 8 bytes and supports values from 1 to 9,223,372,036,854,775,807.

SERIAL Types Comparison Table

Type Storage Size Value Range
SMALLSERIAL 2 bytes 1 to 32,767
SERIAL 4 bytes 1 to 2,147,483,647
BIGSERIAL 8 bytes 1 to 9,223,372,036,854,775,807

How to Use SERIAL in PostgreSQL

Syntax for Defining a SERIAL Column

To define a **SERIAL column in PostgreSQL, you simply specify the type as **SERIAL when creating the table. Here's the basic syntax:

CREATE TABLE table_name (
column_name SERIAL
);

Example 1: Creating an Auto-Incremented Column Using SERIAL

Let’s create a table employees with an auto-incrementing emp_id column using the **PostgreSQL SERIAL pseudo-type.

CREATE TABLE employees (
emp_id SERIAL PRIMARY KEY,
emp_name TEXT NOT NULL,
emp_email VARCHAR(100) NOT NULL,
emp_age SMALLINT
);

In this example:

Inserting Data into the Table

Now, let’s insert some data into the employees table, omitting the emp_id column since it will be auto-generated.

INSERT INTO employees (emp_name, emp_email, emp_age)
VALUES
('Alice', 'alice@example.com', 30),
('Bob', 'bob@example.com', 35),
('Charlie', 'charlie@example.com', 28);

**Output:

emp_id emp_name emp_email emp_age
1 Alice alice@example.com 30
2 Bob bob@example.com 35
3 Charlie charlie@example.com 28

As shown, the **PostgreSQL serial column example automatically assigns sequential values (1, 2, 3, …) to the emp_id column.

Using the DEFAULT Keyword with SERIAL

You can explicitly insert a value into the **SERIAL column using the **DEFAULT keyword. This is useful if you want to ensure that the next available sequence value is used.

Example 2: Inserting Values Using DEFAULT

INSERT INTO employees (emp_id, emp_name, emp_email, emp_age)
VALUES
(DEFAULT, 'David', 'david@example.com', 32);

**Output:

emp_id emp_name emp_email emp_age
1 Alice alice@example.com 30
2 Bob bob@example.com 35
3 Charlie charlie@example.com 28
4 David david@example.com 32

The **DEFAULT keyword inserts the next value in the sequence for emp_id.

Using the RETURNING Clause with SERIAL

The **RETURNING clause is a handy feature that allows you to retrieve the value of the **SERIAL column immediately after inserting a row.

Example 3: Inserting Data and Returning the SERIAL Value

INSERT INTO employees (emp_name, emp_email, emp_age)
VALUES ('Emma', 'emma@example.com', 29)
RETURNING emp_id;

**Output:

emp_id
5

The **RETURNING clause retrieves the newly inserted emp_id value (5 in this case).

Getting the Sequence Name of a SERIAL Column

If you want to retrieve the sequence name associated with a **SERIAL column, you can use the **pg_get_serial_sequence() function.

Example 4: Retrieving the Sequence Name

SELECT pg_get_serial_sequence('employees', 'emp_id');

**Output:

pg_get_serial_sequence
public.employees_emp_id_seq

This shows that the sequence name for the emp_id column is employees_emp_id_seq.

Getting the Current Value of the SERIAL Sequence

To get the current value generated by the **SERIAL sequence, use the **currval() function.

Example 5: Retrieving the Current Sequence Value

SELECT currval(pg_get_serial_sequence('employees', 'emp_id'));

**Output:

currval
5

This confirms that the last value generated by the sequence is 5.

SERIAL vs BIGSERIAL in PostgreSQL

Understanding the difference between **SERIAL and **BIGSERIAL is crucial when designing your database schema. **SERIAL is suitable for most applications, but if we need a larger range of values then consider using **BIGSERIAL.

Example 6: Creating a BIGSERIAL Column

CREATE TABLE large_numbers (
big_id BIGSERIAL PRIMARY KEY,
description TEXT
);

This table uses **BIGSERIAL to ensure it can accommodate larger values.

Important Points about SERIAL Type in PostgreSQL

Conclusion

The **PostgreSQL SERIAL pseudo-type is an efficient way to handle auto-incrementing columns, especially for primary keys. By using the **SERIAL, **BIGSERIAL, or **SMALLSERIAL types, you can simplify your table designs while ensuring that unique, sequential values are automatically generated for each new row. The examples provided in this article should give you a clear understanding of how to use **SERIAL in PostgreSQL.